Skip to content

Commit c6d8adc

Browse files
committed
Improvements in response to pull request comments
1 parent 5206a10 commit c6d8adc

File tree

3 files changed

+53
-52
lines changed

3 files changed

+53
-52
lines changed

cqc/MessageHandler.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828

2929
from abc import ABC, abstractmethod
30+
from collections import defaultdict
3031
import logging
3132

3233
from cqc.cqcHeader import (
@@ -183,7 +184,7 @@ def __init__(self, factory):
183184

184185
# Dictionary that stores all reference ids and their values privately for each app_id.
185186
# Query/assign like this: self.references[app_id][ref_id]
186-
self.references = {}
187+
self.references = defaultdict(dict)
187188

188189
@inlineCallbacks
189190
def handle_cqc_message(self, header, message, transport=None):
@@ -192,10 +193,6 @@ def handle_cqc_message(self, header, message, transport=None):
192193
"""
193194
self.return_messages = []
194195

195-
# References are app_id private. If this app doesn't yet have a references dictionary, create one.
196-
if header.app_id not in self.references:
197-
self.references[header.app_id] = {}
198-
199196
if header.tp in self.messageHandlers:
200197
try:
201198
should_notify = yield self.messageHandlers[header.tp](header, message)
@@ -417,14 +414,18 @@ def handle_mix(self, header: CQCHeader, data: bytes):
417414
current_position += result
418415

419416
# A TP_MIX should return the first error if there is an error message present, and otherwise return one TP_DONE
420-
# We use the next function to retrieve the first error message from the list.
421417
# Notice the [:] syntax. This ensures the underlying list is updated, and not just the variable.
422-
# See https://stackoverflow.com/questions/2361426/get-the-first-item-from-an-iterable-that-matches-a-condition
423-
# and https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating
424-
self.return_messages[:] = [next(
425-
(message for message in self.return_messages if is_error_message(message)),
426-
self.create_return_message(header.app_id, CQCType.DONE, cqc_version=header.version)
427-
)]
418+
419+
return_message = None
420+
for message in self.return_messages:
421+
if is_error_message(message):
422+
return_message = message
423+
break
424+
425+
if return_message is None:
426+
return_message = self.create_return_message(header.app_id, CQCType.DONE, cqc_version=header.version)
427+
428+
self.return_messages[:] = [return_message]
428429

429430
# The other handlers from self.message_handlers return a bool that indicates whether
430431
# self.handle_cqc_message should append a TP_DONE message. This handle_mix method does that itself
@@ -444,19 +445,19 @@ def handle_conditional(self, header: CQCHeader, data: bytes):
444445

445446
try:
446447
first_operand_value = self.references[header.app_id][if_header.first_operand]
448+
449+
if if_header.type_of_second_operand is CQCIfHeader.TYPE_VALUE:
450+
second_operand_value = if_header.second_operand
451+
else:
452+
second_operand_value = self.references[header.app_id][if_header.second_operand]
453+
# If one of the above lookups in self.references fails because the queried reference IDs haven't
454+
# been assigned earlier, a KeyError will be raised
447455
except KeyError:
448456
self.return_messages.append(
449457
self.create_return_message(header.app_id, CQC_ERR_GENERAL, cqc_version=header.version)
450458
)
451-
452-
if if_header.type_of_second_operand is CQCIfHeader.TYPE_VALUE:
453-
second_operand_value = if_header.second_operand
454-
else:
455-
try:
456-
second_operand_value = self.references[header.app_id][if_header.second_operand]
457-
except KeyError:
458-
self.return_messages.append(
459-
self.create_return_message(header.app_id, CQC_ERR_GENERAL, cqc_version=header.version))
459+
# Since the referenced IDs don't exist, we consider this IF-statement to evaluate to False.
460+
return if_header.length
460461

461462
if CQCLogicalOperator.is_true(first_operand_value, if_header.operator, second_operand_value):
462463
return 0

cqc/cqcHeader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ def _setVals(
397397
Set the fields of this header.
398398
first_operand must be a reference id.
399399
second_operand will be interpreted as eiter a reference id or a value, dependent on type_of_second_operand.
400-
type_of_second_operand must either be CQCIFHEADER.TYPE_VALUE or CQCIFHEADER.TYPE_REF_ID
400+
type_of_second_operand must either be CQCIfHeader.TYPE_VALUE or CQCIfHeader.TYPE_REF_ID
401401
"""
402402

403403
self.first_operand = first_operand

cqc/pythonLib.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ def release_all_qubits(self):
730730
"""
731731
return self.release_qubits(self.active_qubits[:])
732732

733-
# sendFactory is depecrated. Do not use it. #
733+
# sendFactory is depecrated. Use flush_factory() instead. #
734734
def sendFactory(
735735
self,
736736
qID,
@@ -1481,14 +1481,14 @@ def ref_id(self):
14811481
# override the == operator
14821482
# other can be a CQCVariable or int
14831483
def __eq__(self, other: Union['CQCVariable', int]):
1484-
return LogicalFunction(self, CQCLogicalOperator.EQ, other)
1484+
return _LogicalFunction(self, CQCLogicalOperator.EQ, other)
14851485

14861486
# override the != operator
14871487
def __ne__(self, other: Union['CQCVariable', int]):
1488-
return LogicalFunction(self, CQCLogicalOperator.NEQ, other)
1488+
return _LogicalFunction(self, CQCLogicalOperator.NEQ, other)
14891489

14901490

1491-
class LogicalFunction:
1491+
class _LogicalFunction:
14921492
"""
14931493
Private helper class. This class should never be used outside this pythonLib.
14941494
"""
@@ -1516,8 +1516,8 @@ def __init__(
15161516
self.operator = operator
15171517
self.operand_two = operand_two
15181518

1519-
def get_negation(self) -> 'LogicalFunction':
1520-
return LogicalFunction(self.operand_one, CQCLogicalOperator.opposite_of(self.operator), self.operand_two)
1519+
def get_negation(self) -> '_LogicalFunction':
1520+
return _LogicalFunction(self.operand_one, CQCLogicalOperator.opposite_of(self.operator), self.operand_two)
15211521

15221522
def get_CQCIfHeader(self) -> CQCIfHeader:
15231523
"""
@@ -1598,28 +1598,28 @@ def __exit__(self, exc_type, exc_val, exc_tb):
15981598
# current_scope is only used inside CQCMix contexts
15991599
self._conn.current_scope = None
16001600

1601-
def cqc_if(self, logical_function: LogicalFunction):
1601+
def cqc_if(self, logical_function: _LogicalFunction):
16021602
"""
16031603
Open a Python Context Manager Type to start an if-statement block.
16041604
16051605
- **Arguments**
16061606
1607-
:logical_function: A LogicalFunction instance. Never instantiate this explicitely; instead
1607+
:logical_function: A _LogicalFunction instance. Never instantiate this explicitely; instead
16081608
use the following: CQCVariable == 1 OR CQCVariable == CQCVariable.
16091609
CQCVariable can be any instance that you want to test to a value, or to another
16101610
CQCVariable. The operator can be == or !=.
16111611
The value can be any integer (though only 1 and 0 make sense).
16121612
16131613
"""
1614-
return CQCConditional(self._conn, False, logical_function)
1614+
return _CQCConditional(self._conn, False, logical_function)
16151615

16161616
def cqc_else(self):
16171617
"""
16181618
Open a Python Context Manager Type to start an else-statement block.
16191619
This will be an else-block of the last closed cqc_if-block.
16201620
"""
16211621
# Find out to which if this else belongs
1622-
return CQCConditional(self._conn, True)
1622+
return _CQCConditional(self._conn, True)
16231623

16241624
def loop(self, times: int):
16251625
"""
@@ -1630,10 +1630,10 @@ def loop(self, times: int):
16301630
:times: The number of times the commands inside body of this context should be repeated.
16311631
16321632
"""
1633-
return CQCFactory(self._conn, times)
1633+
return _CQCFactory(self._conn, times)
16341634

16351635

1636-
class CQCFactory:
1636+
class _CQCFactory:
16371637
"""
16381638
Private class to create factories inside CQCMix contexts. Never explicitely instantiate this class outside
16391639
the source code of this library.
@@ -1680,34 +1680,34 @@ def __exit__(self, exc_type, exc_val, exc_tb):
16801680
self.type_header.length = body_length
16811681

16821682

1683-
class CQCConditional(NodeMixin):
1683+
class _CQCConditional(NodeMixin):
16841684
"""
16851685
Private helper class. Never explicitely instantiate this class outside the source code of this library.
16861686
This Context Manager class is instantiated by CQCMix.cqc_if() and CQCMix.cqc_else(). Its
16871687
function is to build and pend CQC If headers.
16881688
"""
16891689

1690-
# This private class variable holds the last CQCConditional that
1690+
# This private class variable holds the last _CQCConditional that
16911691
# functioned as an IF (as opposed to an ELSE) on which __exit__ is invoked.
16921692
# In other words, it is the last closed IF statement.
16931693
# This is important so that ELSE statements can find out to which IF statement they belong.
16941694
# If this variable is None, then there either has not been aan IF statement yet, or the last
1695-
# CQCConditional was an ELSE.
1695+
# _CQCConditional was an ELSE.
16961696
_last_closed_conditional = None
16971697

1698-
def __init__(self, cqc_connection: CQCConnection, is_else: bool, logical_function: LogicalFunction = None):
1698+
def __init__(self, cqc_connection: CQCConnection, is_else: bool, logical_function: _LogicalFunction = None):
16991699
self._conn = cqc_connection
17001700
self.is_else = is_else
17011701

17021702
if is_else:
17031703
# If _last_closed_conditional is None, then there either has not been aan IF statement yet, or the last
1704-
# CQCConditional was an ELSE.
1705-
if CQCConditional._last_closed_conditional is None:
1704+
# _CQCConditional was an ELSE.
1705+
if _CQCConditional._last_closed_conditional is None:
17061706
raise CQCGeneralError('Cannot use an ELSE if there is no IF directly before it.')
17071707
else:
17081708
# Get the negation of the logical function of the IF,
17091709
# which will be the logical function for this ELSE statement
1710-
logical_function = CQCConditional._last_closed_conditional._logical_function.get_negation()
1710+
logical_function = _CQCConditional._last_closed_conditional._logical_function.get_negation()
17111711

17121712
self._logical_function = logical_function
17131713

@@ -1729,9 +1729,9 @@ def __exit__(self, exc_type, exc_val, exc_tb):
17291729

17301730
# Set _last_closed_conditional to the correct value
17311731
if (self.is_else):
1732-
CQCConditional._last_closed_conditional = None
1732+
_CQCConditional._last_closed_conditional = None
17331733
else:
1734-
CQCConditional._last_closed_conditional = self
1734+
_CQCConditional._last_closed_conditional = self
17351735

17361736
# Calculate the length of the body of the conditional
17371737
# Loop in reverse through all pending_headers to calculate the lenght of all headers
@@ -1949,15 +1949,15 @@ def check_active(self):
19491949
or self.scope_of_deactivation in self._cqc.current_scope.descendants
19501950
):
19511951

1952-
raise QubitNotActiveError("""
1953-
Qubit is not active. Possible causes:
1954-
- Qubit is sent to another node
1955-
- Qubit is measured (with inplace=False)
1956-
- Qubit is released
1957-
- Qubit is not received
1958-
- Qubit is used and created in the same factory
1959-
- Qubit is measured (with inplace=False) inside a cqc_if block earlier in the code
1960-
""")
1952+
raise QubitNotActiveError(
1953+
"Qubit is not active. Possible causes:\n"
1954+
"- Qubit is sent to another node\n"
1955+
"- Qubit is measured (with inplace=False)\n"
1956+
"- Qubit is released\n"
1957+
"- Qubit is not received\n"
1958+
"- Qubit is used and created in the same factory\n"
1959+
"- Qubit is measured (with inplace=False) inside a cqc_if block earlier in the code\n"
1960+
)
19611961

19621962
def _set_active(self, be_active):
19631963

0 commit comments

Comments
 (0)