From ed0180b29861d266320e15351a59384c0418d1f3 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Wed, 10 Jul 2024 17:50:48 +0000 Subject: [PATCH 01/34] Refactor quantum types --- src/grammar_frontend/operation.py | 8 ++-- .../quantum_circuit_handler.py | 5 +-- src/symbols/types/__init__.py | 1 + src/symbols/types/quantum_type.py | 15 +++++++ src/symbols/types/qubit.py | 17 ++++---- src/symbols/types/quint.py | 23 ++++------ src/symbols/types/qustring.py | 42 ++++++++----------- src/symbols/types/qutes_data_type.py | 2 +- 8 files changed, 57 insertions(+), 56 deletions(-) create mode 100644 src/symbols/types/quantum_type.py diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index c107077..e5b27ee 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -190,10 +190,10 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p if(first_term_symbol.symbol_declaration_static_type == QutesDataType.qustring): index = 0 string_value = "" - while index < first_term_symbol.value.number_of_chars * Qustring.default_char_size: - bin_char = bytes_str[index:Qustring.default_char_size + index] + while index < first_term_symbol.value.number_of_chars * Qustring.default_size_in_qubit: + bin_char = bytes_str[index:Qustring.default_size_in_qubit + index] string_value = string_value + Qustring.get_char_from_int(int(bin_char, 2)) - index = index + Qustring.default_char_size + index = index + Qustring.default_size_in_qubit print(string_value) else: new_value = int(bytes_str, 2) @@ -267,7 +267,7 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): array_register = target_symbol.quantum_register block_size = 1 try: - block_size = target_symbol.value.default_block_size + block_size = target_symbol.value.default_size_in_qubit except: pass array_size = int(len(target_symbol.quantum_register)/block_size) diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 1f34d4b..00cd897 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -52,14 +52,13 @@ def declare_quantum_register(self, variable_name : str, quantum_variable : any) self._registers_states[new_register] = quantum_variable.get_quantum_state() return new_register + # TODO: this should be a correlation operation, or a measure and then update. + # We cannot rely on quantum_variable.get_quantum_state() def replace_quantum_register(self, variable_name : str, quantum_variable : any) -> QuantumRegister: register_to_update = self._varname_to_register[variable_name] if(register_to_update is None): raise SystemError("Error trying to update an undeclared quantum register") - #TODO: can we handle qubit like quint and qustring? - # if(isinstance(quantum_variable, Qubit)): - # pass if(isinstance(quantum_variable, Qubit) or isinstance(quantum_variable, Quint) or isinstance(quantum_variable, Qustring)): #TODO-CRITICAL: this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value and changing the name from update to replace. #Delete old quantum register and reference diff --git a/src/symbols/types/__init__.py b/src/symbols/types/__init__.py index bf61c6f..ef10031 100644 --- a/src/symbols/types/__init__.py +++ b/src/symbols/types/__init__.py @@ -1,5 +1,6 @@ # Aliasing for easy importing through the code from symbols.types.qubit import Qubit +from symbols.types.quantum_type import QuantumType from symbols.types.quint import Quint from symbols.types.qustring import Qustring from symbols.types.qutes_data_type import QutesDataType \ No newline at end of file diff --git a/src/symbols/types/quantum_type.py b/src/symbols/types/quantum_type.py new file mode 100644 index 0000000..f9709af --- /dev/null +++ b/src/symbols/types/quantum_type.py @@ -0,0 +1,15 @@ +from symbols.types import Qubit + +class QuantumType: + default_value = [Qubit(complex(1),complex(0))] + default_size_in_qubit = 1 + default_superposition_value = [Qubit(complex(0.5),complex(0.5))] + + def __init__(self): + pass + + def __str__(self) -> str: + return self.__to_printable__() + + def __repr__(self) -> str: + return self.__to_printable__() \ No newline at end of file diff --git a/src/symbols/types/qubit.py b/src/symbols/types/qubit.py index ae8a200..c37cd19 100644 --- a/src/symbols/types/qubit.py +++ b/src/symbols/types/qubit.py @@ -3,7 +3,14 @@ import cmath class Qubit(): - default_block_size = 1 + def __init__(self, alpha : complex = complex(1), beta : complex = complex(0)): + self.size:int = 1 + self.alpha = complex(alpha) + self.beta = complex(beta) + self.phase = Phase.Positive if (alpha * beta).real >= 0 else Phase.Negative + self.is_superposition = cmath.isclose(abs(alpha), abs(beta)) + self.qubit_state:list[Qubit] = [self] + def from_string(literal : str) -> 'Qubit': try: literal = literal.removesuffix(QutesParser.literal_to_string(QutesParser.QUBIT_LITERAL_POSTFIX)) @@ -46,14 +53,6 @@ def fromValue(var_value : any) -> 'Qubit': else: return Qubit(complex(1), complex(0)) raise TypeError(f"Cannot convert {type(var_value)} to qubit.") - - def __init__(self, alpha : complex = complex(1), beta : complex = complex(0)): - self.size:int = 1 - self.alpha = complex(alpha) - self.beta = complex(beta) - self.phase = Phase.Positive if (alpha * beta).real >= 0 else Phase.Negative - self.is_superposition = cmath.isclose(abs(alpha), abs(beta)) - self.qubit_state:list[Qubit] = [self] def get_quantum_state(self) -> list[complex]: return [self.alpha, self.beta] diff --git a/src/symbols/types/quint.py b/src/symbols/types/quint.py index 0029308..1ed17ca 100644 --- a/src/symbols/types/quint.py +++ b/src/symbols/types/quint.py @@ -2,11 +2,17 @@ from utils.phase import Phase import utils from symbols.types import Qubit +from symbols.types import QuantumType -class Quint(): +class Quint(QuantumType): default_value = [Qubit(complex(1),complex(0))] default_superposition_value = [Qubit(complex(0.5),complex(0.5))] - default_block_size = 1 + default_size_in_qubit = 1 + + def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): + super().__init__() + self.qubit_state:list[Qubit] = qubits + self.size:int = len(self.qubit_state) def init_from_string(literal : str) -> 'Quint': qubits = [] @@ -74,11 +80,6 @@ def fromValue(var_value : any) -> 'Quint': raise TypeError(f"Cannot convert {type(var_value)} to quint.") except: raise TypeError(f"Cannot convert {type(var_value)} to quint.") - - - def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): - self.qubit_state:list[Qubit] = qubits - self.size:int = len(self.qubit_state) def get_quantum_state(self) -> list[complex] : #TODO: this doesn't make any sense, outside of the initialization phase we should not rely on the quantum state. @@ -107,10 +108,4 @@ def __to_printable__(self) -> str: for qubit in self.qubit_state: str += f"{qubit}, " str += ']' - return str - - def __str__(self) -> str: - return self.__to_printable__() - - def __repr__(self) -> str: - return self.__to_printable__() \ No newline at end of file + return str \ No newline at end of file diff --git a/src/symbols/types/qustring.py b/src/symbols/types/qustring.py index 569629e..1382bc7 100644 --- a/src/symbols/types/qustring.py +++ b/src/symbols/types/qustring.py @@ -1,17 +1,24 @@ from grammar_frontend.qutes_parser import QutesParser import utils, math from symbols.types import Qubit, Quint +from symbols.types import QuantumType -class Qustring(): +class Qustring(QuantumType): # note: chr and ord, parse int and char in ASCII for char of size 7 bits - default_value = [Qubit(complex(1),complex(0))] - superposition_char = '*' - not_valid_char = 'X' # allowed_chars = ['a', 'b', 'c', 'd', superposition_char, not_valid_char] # allowed_chars = ['0', '1', superposition_char, not_valid_char] + superposition_char = '*' + not_valid_char = 'X' allowed_chars = ['0', '1'] - default_char_size = math.ceil(math.log2(len(allowed_chars))) - default_block_size = default_char_size + default_size_in_qubit = math.ceil(math.log2(len(allowed_chars))) + default_value = [Qubit(complex(1),complex(0))] * default_size_in_qubit + default_superposition_value = [Qubit(complex(0.5),complex(0.5))] * default_size_in_qubit + + def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): + super().__init__() + self.qubit_state:list[Qubit] = qubits + self.size:int = len(self.qubit_state) + self.number_of_chars:int = int(self.size / Qustring.default_size_in_qubit) def get_char_from_int(int_value:int): if(int_value > len(Qustring.allowed_chars)): @@ -22,8 +29,7 @@ def get_int_from_char(char_value:str): try: return Qustring.allowed_chars.index(char_value) except: - return len(Qustring.allowed_chars)-1 - + return len(Qustring.allowed_chars)-1 def init_from_string(literal : str) -> 'Qustring': qubits = [] @@ -34,26 +40,18 @@ def init_from_string(literal : str) -> 'Qustring': for char in literal: if(char == Qustring.superposition_char): - qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.default_char_size, True) + qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.default_size_in_qubit, True) else: - qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.default_char_size) + qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.default_size_in_qubit) qubits.extend(qubyte.qubit_state) return Qustring(qubits) - def init_from_size(number_of_bits : int) -> 'Qustring': - return Qustring(Qustring.default_value*number_of_bits) - def fromValue(var_value : any) -> 'Qustring': if(isinstance(var_value, Qubit)): return Qustring([var_value]) if(isinstance(var_value, str)): return Qustring.init_from_string(var_value) raise TypeError(f"Cannot convert {type(var_value)} to quint.") - - def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): - self.qubit_state:list[Qubit] = qubits - self.size:int = len(self.qubit_state) - self.number_of_chars:int = int(self.size / Qustring.default_char_size) def get_quantum_state(self) -> list[complex] : #TODO: this doesn't make any sense, outside of the initialization phase we should not rely on the quantum state. @@ -76,10 +74,4 @@ def __to_printable__(self) -> str: for qubit in self.qubit_state: str += f"{qubit}, " str += ']' - return str - - def __str__(self) -> str: - return self.__to_printable__() - - def __repr__(self) -> str: - return self.__to_printable__() \ No newline at end of file + return str \ No newline at end of file diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index 11999be..a67e0ca 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -38,7 +38,7 @@ def is_array_type(type:'QutesDataType'): def get_array_word_bit(type:'QutesDataType'): match type: case QutesDataType.qustring: - return Qustring.default_char_size + return Qustring.default_size_in_qubit case _: return 1 From 3def377e44d62c6af78d9b3b88b2bbe7279b0dcb Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Wed, 10 Jul 2024 21:26:53 +0000 Subject: [PATCH 02/34] Add arrays to grammar, refactor quantum types --- playground/examples/arrays.qut | 3 + specification/grammar/qutes_parser.g4 | 27 +- src/grammar_frontend/expression.py | 24 + src/grammar_frontend/literal.py | 13 +- src/grammar_frontend/operation.py | 1 + src/qutes_antlr/qutes_parser.py | 561 ++++++++++++++---------- src/qutes_antlr/qutes_parserListener.py | 34 +- src/qutes_antlr/qutes_parserVisitor.py | 18 +- src/symbols/symbol.py | 26 +- src/symbols/types/__init__.py | 3 +- src/symbols/types/quantum_array_type.py | 8 + src/symbols/types/quantum_type.py | 20 +- src/symbols/types/qubit.py | 20 +- src/symbols/types/quint.py | 19 +- src/symbols/types/qustring.py | 16 +- src/symbols/types/qutes_data_type.py | 127 +++++- src/symbols/variables_handler.py | 10 + src/tests/test_array_access.py | 22 + src/tests/test_grover.py | 2 - src/tests/test_operations.py | 2 - 20 files changed, 635 insertions(+), 321 deletions(-) create mode 100644 playground/examples/arrays.qut create mode 100644 src/symbols/types/quantum_array_type.py create mode 100644 src/tests/test_array_access.py diff --git a/playground/examples/arrays.qut b/playground/examples/arrays.qut new file mode 100644 index 0000000..0cbed13 --- /dev/null +++ b/playground/examples/arrays.qut @@ -0,0 +1,3 @@ +qubit b = 1q; +qubit c = 0q; +qubit[] a = [b, c, |+>]; \ No newline at end of file diff --git a/specification/grammar/qutes_parser.g4 b/specification/grammar/qutes_parser.g4 index 29951ba..6dd5e3a 100644 --- a/specification/grammar/qutes_parser.g4 +++ b/specification/grammar/qutes_parser.g4 @@ -38,36 +38,43 @@ expr // Order: https://en.wikipedia.org/wiki/Order_of_operations#Programming_lan : ROUND_PARENTHESIS_OPEN expr ROUND_PARENTHESIS_CLOSE #ParentesizeExpression | literal #LiteralExpression | qualifiedName #QualifiedNameExpression - // Array access - | functionName ROUND_PARENTHESIS_OPEN functionCallParams? ROUND_PARENTHESIS_CLOSE #FunctionCallExpression + | array #ArrayExpression + // Function call, scope, array/member access + | functionName ROUND_PARENTHESIS_OPEN termList? ROUND_PARENTHESIS_CLOSE #FunctionCallExpression + | expr SQUARE_PARENTHESIS_OPEN expr SQUARE_PARENTHESIS_CLOSE #ArrayAccessExpression + // Unary operators, sizeof and type casts | expr op=(AUTO_INCREMENT | AUTO_DECREMENT) #PostfixOperator | op=(NOT | ADD | SUB | AUTO_INCREMENT | AUTO_DECREMENT) expr #PrefixOperator - // cast operation + // Multiplication, division, modulo | expr op=(MULTIPLY | DIVIDE | MODULE) expr #MultiplicativeOperator + // Addition and subtraction | expr op=(ADD | SUB) expr #SumOperator + // Bitwise shift left and right | expr op=(LSHIFT | RSHIFT) expr #ShiftOperator + // Comparisons less-greater, then, equallity, inequality | expr op=(GREATEREQUAL | LOWEREQUAL | GREATER | LOWER ) expr #RelationalOperator | expr op=(EQUAL | NOT_EQUAL) expr #EqualityOperator + // Logical AND then OR | expr op=AND expr #LogicAndOperator | expr op=OR expr #LogicOrOperator - // | expr op=(AUTO_SUM | AUTO_DECREMENT | AUTO_MODULE | AUTO_DIVIDE | AUTO_MODULE) expr #AutoAssignmentOperator + // Assignment and auto assignment operators | expr op=(AUTO_SUM | AUTO_DECREMENT | AUTO_MODULE | AUTO_DIVIDE | AUTO_MODULE) expr #AutoAssignmentOperator | op=(MCX | MCZ | MCY | SWAP) termList #MultipleUnaryOperator | op=(PRINT | PAULIY | PAULIZ | HADAMARD | MEASURE) expr #UnaryOperator | op=MCP termList BY expr #MultipleUnaryPhaseOperator | termList op=IN_STATEMENT qualifiedName #GroverOperator ; -functionCallParams - : (literal | qualifiedName) (COMMA functionCallParams)? - ; - termList : (literal | qualifiedName) (COMMA termList)? ; +array + : SQUARE_PARENTHESIS_OPEN termList SQUARE_PARENTHESIS_CLOSE + ; + variableType - : type - | qualifiedName + : type (SQUARE_PARENTHESIS_OPEN SQUARE_PARENTHESIS_CLOSE)? + | qualifiedName (SQUARE_PARENTHESIS_OPEN SQUARE_PARENTHESIS_CLOSE)? ; type diff --git a/src/grammar_frontend/expression.py b/src/grammar_frontend/expression.py index 8c5dd24..57b8abb 100644 --- a/src/grammar_frontend/expression.py +++ b/src/grammar_frontend/expression.py @@ -5,6 +5,7 @@ from symbols.variables_handler import VariablesHandler from quantum_circuit import QuantumCircuitHandler from grammar_frontend.qutes_base_visitor import QutesBaseVisitor +from symbols.types import QutesDataType class QutesGrammarExpressionVisitor(QutesBaseVisitor): def __init__(self, symbols_tree:ScopeTreeNode, quantum_circuit_handler : QuantumCircuitHandler, scope_handler:ScopeHandlerForSymbolsUpdate, variables_handler:VariablesHandler, verbose:bool = False): @@ -21,6 +22,9 @@ def visitLiteralExpression(self, ctx:qutes_parser.LiteralExpressionContext): def visitQualifiedNameExpression(self, ctx:qutes_parser.QualifiedNameExpressionContext): return self.visit(ctx.qualifiedName()) + + def visitArrayExpression(self, ctx:qutes_parser.ArrayExpressionContext): + return self.visit(ctx.array()) def visitFunctionCallExpression(self, ctx:qutes_parser.FunctionCallExpressionContext): function_name = self.visit(ctx.functionName()) @@ -62,3 +66,23 @@ def __visitFunctionCall(self, function_name, function_params, tokenIndex): self.scope_handler.end_function() return result + + def visitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionContext): + array_symbol:Symbol = self.visit(ctx.expr(0)) + index_symbol:Symbol = self.visit(ctx.expr(1)) + + array_value = self.variables_handler.get_value(array_symbol) + index_value = self.variables_handler.get_value(index_symbol) + array_unit_type_size = array_symbol.get_array_unit_type() + + if array_symbol.is_classical_type(): + result = array_value[index_value] + return self.variables_handler.create_anonymous_symbol(QutesDataType.type_of(result), result, ctx.start.tokenIndex) + else: + array_unit_type_size = QutesDataType.get_size_in_qubit(array_unit_type_size) + result = array_symbol.quantum_register[index_value*array_unit_type_size:array_unit_type_size] + #TODO: non posso passare un array di qubit per creare il simbolo anonimo, dovrei sfruttare il circuit handler + # Oppure devo aggiornare il metodo create_anonymous_symbol per gestire quantum register + # In questo caso dovrebbe gestirli come se fossero reference type. + return self.variables_handler.create_anonymous_symbol_from_quantum_register(array_unit_type_size, result, ctx.start.tokenIndex) + diff --git a/src/grammar_frontend/literal.py b/src/grammar_frontend/literal.py index a9ceda9..4dbb210 100644 --- a/src/grammar_frontend/literal.py +++ b/src/grammar_frontend/literal.py @@ -24,16 +24,6 @@ def visitFunctionDeclarationParams(self, ctx:qutes_parser.FunctionDeclarationPar params.append(param) return params[::-1] - def visitFunctionCallParams(self, ctx:qutes_parser.FunctionCallParamsContext): - param = self.visit(ctx.literal()) if ctx.literal() else self.visit(ctx.qualifiedName()) - params = [] - if(ctx.functionCallParams()): - params = self.visit(ctx.functionCallParams()) - if(not isinstance(params, list)): - params = [params] - params.append(param) - return params[::-1] - def visitTermList(self, ctx:qutes_parser.TermListContext) -> list[Symbol]: term = self.visit(ctx.literal()) if ctx.literal() else self.visit(ctx.qualifiedName()) terms = [] @@ -43,6 +33,9 @@ def visitTermList(self, ctx:qutes_parser.TermListContext) -> list[Symbol]: terms = [terms] terms.append(term) return terms[::-1] + + def visitArray(self, ctx:qutes_parser.ArrayContext) -> list[Symbol]: + return self.visit(ctx.termList()) def visitVariableType(self, ctx:qutes_parser.VariableTypeContext): value = str(ctx.getText()) diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index e5b27ee..ba535f3 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -286,6 +286,7 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): for term in termList: if(not QutesDataType.is_array_type(target_symbol.casted_static_type)): + #TODO: Write tests for this case. self.quantum_circuit_handler.push_equals_operation(array_register, term.value) if(len(array_register) == 1): if(phase_kickback_ancilla == None): diff --git a/src/qutes_antlr/qutes_parser.py b/src/qutes_antlr/qutes_parser.py index 47cb278..e676b38 100644 --- a/src/qutes_antlr/qutes_parser.py +++ b/src/qutes_antlr/qutes_parser.py @@ -10,7 +10,7 @@ def serializedATN(): return [ - 4,1,77,235,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7, + 4,1,77,245,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7, 6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13, 2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,1,0, 5,0,42,8,0,10,0,12,0,45,9,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -18,83 +18,87 @@ def serializedATN(): 1,10,1,12,1,73,9,1,1,1,1,1,1,1,1,1,1,1,3,1,80,8,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,3,1,102,8,1,1,2,1,2,1,2,3,2,107,8,2,1,3,1,3,1,3,1,3,3,3,113,8, - 3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3,4,125,8,4,1,4,1,4,1, - 4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3,4,144, - 8,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4, - 1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,5,4,169,8,4,10,4,12,4,172,9,4,1, - 5,1,5,3,5,176,8,5,1,5,1,5,3,5,180,8,5,1,6,1,6,3,6,184,8,6,1,6,1, - 6,3,6,188,8,6,1,7,1,7,3,7,192,8,7,1,8,1,8,1,9,1,9,1,9,5,9,199,8, - 9,10,9,12,9,202,9,9,1,9,1,9,3,9,206,8,9,1,10,1,10,1,11,1,11,1,12, - 1,12,1,12,1,12,1,12,1,12,1,12,3,12,219,8,12,1,13,1,13,1,14,1,14, - 1,15,1,15,1,16,1,16,1,17,1,17,1,18,1,18,1,19,1,19,1,19,0,1,8,20, - 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,0,12,2,0, - 28,28,30,30,2,0,13,15,40,41,2,0,19,19,23,25,2,0,20,21,27,29,1,0, - 10,12,1,0,13,14,1,0,37,38,1,0,33,36,1,0,31,32,1,0,40,41,1,0,1,8, - 2,0,67,67,69,70,261,0,43,1,0,0,0,2,101,1,0,0,0,4,103,1,0,0,0,6,108, - 1,0,0,0,8,143,1,0,0,0,10,175,1,0,0,0,12,183,1,0,0,0,14,191,1,0,0, - 0,16,193,1,0,0,0,18,205,1,0,0,0,20,207,1,0,0,0,22,209,1,0,0,0,24, - 218,1,0,0,0,26,220,1,0,0,0,28,222,1,0,0,0,30,224,1,0,0,0,32,226, - 1,0,0,0,34,228,1,0,0,0,36,230,1,0,0,0,38,232,1,0,0,0,40,42,3,2,1, - 0,41,40,1,0,0,0,42,45,1,0,0,0,43,41,1,0,0,0,43,44,1,0,0,0,44,46, - 1,0,0,0,45,43,1,0,0,0,46,47,5,0,0,1,47,1,1,0,0,0,48,49,5,53,0,0, - 49,50,3,8,4,0,50,51,3,2,1,0,51,102,1,0,0,0,52,53,5,53,0,0,53,54, - 3,8,4,0,54,55,3,2,1,0,55,56,5,54,0,0,56,57,3,2,1,0,57,102,1,0,0, - 0,58,59,5,55,0,0,59,60,3,8,4,0,60,61,3,2,1,0,61,102,1,0,0,0,62,63, - 5,56,0,0,63,64,3,2,1,0,64,65,5,55,0,0,65,66,3,8,4,0,66,102,1,0,0, - 0,67,71,5,57,0,0,68,70,3,2,1,0,69,68,1,0,0,0,70,73,1,0,0,0,71,69, - 1,0,0,0,71,72,1,0,0,0,72,74,1,0,0,0,73,71,1,0,0,0,74,102,5,58,0, - 0,75,76,3,14,7,0,76,77,3,22,11,0,77,79,5,59,0,0,78,80,3,4,2,0,79, - 78,1,0,0,0,79,80,1,0,0,0,80,81,1,0,0,0,81,82,5,60,0,0,82,83,3,2, - 1,0,83,102,1,0,0,0,84,85,3,6,3,0,85,86,5,47,0,0,86,102,1,0,0,0,87, - 88,3,18,9,0,88,89,5,39,0,0,89,90,3,8,4,0,90,91,5,47,0,0,91,102,1, - 0,0,0,92,93,5,9,0,0,93,94,3,8,4,0,94,95,5,47,0,0,95,102,1,0,0,0, - 96,97,3,8,4,0,97,98,5,47,0,0,98,102,1,0,0,0,99,102,7,0,0,0,100,102, - 5,47,0,0,101,48,1,0,0,0,101,52,1,0,0,0,101,58,1,0,0,0,101,62,1,0, - 0,0,101,67,1,0,0,0,101,75,1,0,0,0,101,84,1,0,0,0,101,87,1,0,0,0, - 101,92,1,0,0,0,101,96,1,0,0,0,101,99,1,0,0,0,101,100,1,0,0,0,102, - 3,1,0,0,0,103,106,3,6,3,0,104,105,5,65,0,0,105,107,3,4,2,0,106,104, - 1,0,0,0,106,107,1,0,0,0,107,5,1,0,0,0,108,109,3,14,7,0,109,112,3, - 20,10,0,110,111,5,39,0,0,111,113,3,8,4,0,112,110,1,0,0,0,112,113, - 1,0,0,0,113,7,1,0,0,0,114,115,6,4,-1,0,115,116,5,59,0,0,116,117, - 3,8,4,0,117,118,5,60,0,0,118,144,1,0,0,0,119,144,3,24,12,0,120,144, - 3,18,9,0,121,122,3,22,11,0,122,124,5,59,0,0,123,125,3,10,5,0,124, - 123,1,0,0,0,124,125,1,0,0,0,125,126,1,0,0,0,126,127,5,60,0,0,127, - 144,1,0,0,0,128,129,7,1,0,0,129,144,3,8,4,12,130,131,7,2,0,0,131, - 144,3,12,6,0,132,133,7,3,0,0,133,144,3,8,4,3,134,135,5,26,0,0,135, - 136,3,12,6,0,136,137,5,18,0,0,137,138,3,8,4,2,138,144,1,0,0,0,139, - 140,3,12,6,0,140,141,5,51,0,0,141,142,3,18,9,0,142,144,1,0,0,0,143, - 114,1,0,0,0,143,119,1,0,0,0,143,120,1,0,0,0,143,121,1,0,0,0,143, - 128,1,0,0,0,143,130,1,0,0,0,143,132,1,0,0,0,143,134,1,0,0,0,143, - 139,1,0,0,0,144,170,1,0,0,0,145,146,10,11,0,0,146,147,7,4,0,0,147, - 169,3,8,4,12,148,149,10,10,0,0,149,150,7,5,0,0,150,169,3,8,4,11, - 151,152,10,9,0,0,152,153,7,6,0,0,153,169,3,8,4,10,154,155,10,8,0, - 0,155,156,7,7,0,0,156,169,3,8,4,9,157,158,10,7,0,0,158,159,7,8,0, - 0,159,169,3,8,4,8,160,161,10,6,0,0,161,162,5,16,0,0,162,169,3,8, - 4,7,163,164,10,5,0,0,164,165,5,17,0,0,165,169,3,8,4,6,166,167,10, - 13,0,0,167,169,7,9,0,0,168,145,1,0,0,0,168,148,1,0,0,0,168,151,1, - 0,0,0,168,154,1,0,0,0,168,157,1,0,0,0,168,160,1,0,0,0,168,163,1, - 0,0,0,168,166,1,0,0,0,169,172,1,0,0,0,170,168,1,0,0,0,170,171,1, - 0,0,0,171,9,1,0,0,0,172,170,1,0,0,0,173,176,3,24,12,0,174,176,3, - 18,9,0,175,173,1,0,0,0,175,174,1,0,0,0,176,179,1,0,0,0,177,178,5, - 65,0,0,178,180,3,10,5,0,179,177,1,0,0,0,179,180,1,0,0,0,180,11,1, - 0,0,0,181,184,3,24,12,0,182,184,3,18,9,0,183,181,1,0,0,0,183,182, - 1,0,0,0,184,187,1,0,0,0,185,186,5,65,0,0,186,188,3,12,6,0,187,185, - 1,0,0,0,187,188,1,0,0,0,188,13,1,0,0,0,189,192,3,16,8,0,190,192, - 3,18,9,0,191,189,1,0,0,0,191,190,1,0,0,0,192,15,1,0,0,0,193,194, - 7,10,0,0,194,17,1,0,0,0,195,200,5,74,0,0,196,197,5,63,0,0,197,199, - 5,74,0,0,198,196,1,0,0,0,199,202,1,0,0,0,200,198,1,0,0,0,200,201, - 1,0,0,0,201,206,1,0,0,0,202,200,1,0,0,0,203,206,3,20,10,0,204,206, - 3,22,11,0,205,195,1,0,0,0,205,203,1,0,0,0,205,204,1,0,0,0,206,19, - 1,0,0,0,207,208,5,74,0,0,208,21,1,0,0,0,209,210,5,74,0,0,210,23, - 1,0,0,0,211,219,3,38,19,0,212,219,3,36,18,0,213,219,3,34,17,0,214, - 219,3,28,14,0,215,219,3,30,15,0,216,219,3,32,16,0,217,219,3,26,13, - 0,218,211,1,0,0,0,218,212,1,0,0,0,218,213,1,0,0,0,218,214,1,0,0, - 0,218,215,1,0,0,0,218,216,1,0,0,0,218,217,1,0,0,0,219,25,1,0,0,0, - 220,221,5,75,0,0,221,27,1,0,0,0,222,223,5,71,0,0,223,29,1,0,0,0, - 224,225,5,72,0,0,225,31,1,0,0,0,226,227,5,73,0,0,227,33,1,0,0,0, - 228,229,5,68,0,0,229,35,1,0,0,0,230,231,7,11,0,0,231,37,1,0,0,0, - 232,233,5,66,0,0,233,39,1,0,0,0,18,43,71,79,101,106,112,124,143, - 168,170,175,179,183,187,191,200,205,218 + 3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3,4,126,8,4,1,4,1, + 4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3, + 4,145,8,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1, + 4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,5,4,175, + 8,4,10,4,12,4,178,9,4,1,5,1,5,3,5,182,8,5,1,5,1,5,3,5,186,8,5,1, + 6,1,6,1,6,1,6,1,7,1,7,1,7,3,7,195,8,7,1,7,1,7,1,7,3,7,200,8,7,3, + 7,202,8,7,1,8,1,8,1,9,1,9,1,9,5,9,209,8,9,10,9,12,9,212,9,9,1,9, + 1,9,3,9,216,8,9,1,10,1,10,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12, + 1,12,3,12,229,8,12,1,13,1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,17, + 1,17,1,18,1,18,1,19,1,19,1,19,0,1,8,20,0,2,4,6,8,10,12,14,16,18, + 20,22,24,26,28,30,32,34,36,38,0,12,2,0,28,28,30,30,2,0,13,15,40, + 41,2,0,19,19,23,25,2,0,20,21,27,29,1,0,10,12,1,0,13,14,1,0,37,38, + 1,0,33,36,1,0,31,32,1,0,40,41,1,0,1,8,2,0,67,67,69,70,273,0,43,1, + 0,0,0,2,101,1,0,0,0,4,103,1,0,0,0,6,108,1,0,0,0,8,144,1,0,0,0,10, + 181,1,0,0,0,12,187,1,0,0,0,14,201,1,0,0,0,16,203,1,0,0,0,18,215, + 1,0,0,0,20,217,1,0,0,0,22,219,1,0,0,0,24,228,1,0,0,0,26,230,1,0, + 0,0,28,232,1,0,0,0,30,234,1,0,0,0,32,236,1,0,0,0,34,238,1,0,0,0, + 36,240,1,0,0,0,38,242,1,0,0,0,40,42,3,2,1,0,41,40,1,0,0,0,42,45, + 1,0,0,0,43,41,1,0,0,0,43,44,1,0,0,0,44,46,1,0,0,0,45,43,1,0,0,0, + 46,47,5,0,0,1,47,1,1,0,0,0,48,49,5,53,0,0,49,50,3,8,4,0,50,51,3, + 2,1,0,51,102,1,0,0,0,52,53,5,53,0,0,53,54,3,8,4,0,54,55,3,2,1,0, + 55,56,5,54,0,0,56,57,3,2,1,0,57,102,1,0,0,0,58,59,5,55,0,0,59,60, + 3,8,4,0,60,61,3,2,1,0,61,102,1,0,0,0,62,63,5,56,0,0,63,64,3,2,1, + 0,64,65,5,55,0,0,65,66,3,8,4,0,66,102,1,0,0,0,67,71,5,57,0,0,68, + 70,3,2,1,0,69,68,1,0,0,0,70,73,1,0,0,0,71,69,1,0,0,0,71,72,1,0,0, + 0,72,74,1,0,0,0,73,71,1,0,0,0,74,102,5,58,0,0,75,76,3,14,7,0,76, + 77,3,22,11,0,77,79,5,59,0,0,78,80,3,4,2,0,79,78,1,0,0,0,79,80,1, + 0,0,0,80,81,1,0,0,0,81,82,5,60,0,0,82,83,3,2,1,0,83,102,1,0,0,0, + 84,85,3,6,3,0,85,86,5,47,0,0,86,102,1,0,0,0,87,88,3,18,9,0,88,89, + 5,39,0,0,89,90,3,8,4,0,90,91,5,47,0,0,91,102,1,0,0,0,92,93,5,9,0, + 0,93,94,3,8,4,0,94,95,5,47,0,0,95,102,1,0,0,0,96,97,3,8,4,0,97,98, + 5,47,0,0,98,102,1,0,0,0,99,102,7,0,0,0,100,102,5,47,0,0,101,48,1, + 0,0,0,101,52,1,0,0,0,101,58,1,0,0,0,101,62,1,0,0,0,101,67,1,0,0, + 0,101,75,1,0,0,0,101,84,1,0,0,0,101,87,1,0,0,0,101,92,1,0,0,0,101, + 96,1,0,0,0,101,99,1,0,0,0,101,100,1,0,0,0,102,3,1,0,0,0,103,106, + 3,6,3,0,104,105,5,65,0,0,105,107,3,4,2,0,106,104,1,0,0,0,106,107, + 1,0,0,0,107,5,1,0,0,0,108,109,3,14,7,0,109,112,3,20,10,0,110,111, + 5,39,0,0,111,113,3,8,4,0,112,110,1,0,0,0,112,113,1,0,0,0,113,7,1, + 0,0,0,114,115,6,4,-1,0,115,116,5,59,0,0,116,117,3,8,4,0,117,118, + 5,60,0,0,118,145,1,0,0,0,119,145,3,24,12,0,120,145,3,18,9,0,121, + 145,3,12,6,0,122,123,3,22,11,0,123,125,5,59,0,0,124,126,3,10,5,0, + 125,124,1,0,0,0,125,126,1,0,0,0,126,127,1,0,0,0,127,128,5,60,0,0, + 128,145,1,0,0,0,129,130,7,1,0,0,130,145,3,8,4,12,131,132,7,2,0,0, + 132,145,3,10,5,0,133,134,7,3,0,0,134,145,3,8,4,3,135,136,5,26,0, + 0,136,137,3,10,5,0,137,138,5,18,0,0,138,139,3,8,4,2,139,145,1,0, + 0,0,140,141,3,10,5,0,141,142,5,51,0,0,142,143,3,18,9,0,143,145,1, + 0,0,0,144,114,1,0,0,0,144,119,1,0,0,0,144,120,1,0,0,0,144,121,1, + 0,0,0,144,122,1,0,0,0,144,129,1,0,0,0,144,131,1,0,0,0,144,133,1, + 0,0,0,144,135,1,0,0,0,144,140,1,0,0,0,145,176,1,0,0,0,146,147,10, + 11,0,0,147,148,7,4,0,0,148,175,3,8,4,12,149,150,10,10,0,0,150,151, + 7,5,0,0,151,175,3,8,4,11,152,153,10,9,0,0,153,154,7,6,0,0,154,175, + 3,8,4,10,155,156,10,8,0,0,156,157,7,7,0,0,157,175,3,8,4,9,158,159, + 10,7,0,0,159,160,7,8,0,0,160,175,3,8,4,8,161,162,10,6,0,0,162,163, + 5,16,0,0,163,175,3,8,4,7,164,165,10,5,0,0,165,166,5,17,0,0,166,175, + 3,8,4,6,167,168,10,14,0,0,168,169,5,61,0,0,169,170,3,8,4,0,170,171, + 5,62,0,0,171,175,1,0,0,0,172,173,10,13,0,0,173,175,7,9,0,0,174,146, + 1,0,0,0,174,149,1,0,0,0,174,152,1,0,0,0,174,155,1,0,0,0,174,158, + 1,0,0,0,174,161,1,0,0,0,174,164,1,0,0,0,174,167,1,0,0,0,174,172, + 1,0,0,0,175,178,1,0,0,0,176,174,1,0,0,0,176,177,1,0,0,0,177,9,1, + 0,0,0,178,176,1,0,0,0,179,182,3,24,12,0,180,182,3,18,9,0,181,179, + 1,0,0,0,181,180,1,0,0,0,182,185,1,0,0,0,183,184,5,65,0,0,184,186, + 3,10,5,0,185,183,1,0,0,0,185,186,1,0,0,0,186,11,1,0,0,0,187,188, + 5,61,0,0,188,189,3,10,5,0,189,190,5,62,0,0,190,13,1,0,0,0,191,194, + 3,16,8,0,192,193,5,61,0,0,193,195,5,62,0,0,194,192,1,0,0,0,194,195, + 1,0,0,0,195,202,1,0,0,0,196,199,3,18,9,0,197,198,5,61,0,0,198,200, + 5,62,0,0,199,197,1,0,0,0,199,200,1,0,0,0,200,202,1,0,0,0,201,191, + 1,0,0,0,201,196,1,0,0,0,202,15,1,0,0,0,203,204,7,10,0,0,204,17,1, + 0,0,0,205,210,5,74,0,0,206,207,5,63,0,0,207,209,5,74,0,0,208,206, + 1,0,0,0,209,212,1,0,0,0,210,208,1,0,0,0,210,211,1,0,0,0,211,216, + 1,0,0,0,212,210,1,0,0,0,213,216,3,20,10,0,214,216,3,22,11,0,215, + 205,1,0,0,0,215,213,1,0,0,0,215,214,1,0,0,0,216,19,1,0,0,0,217,218, + 5,74,0,0,218,21,1,0,0,0,219,220,5,74,0,0,220,23,1,0,0,0,221,229, + 3,38,19,0,222,229,3,36,18,0,223,229,3,34,17,0,224,229,3,28,14,0, + 225,229,3,30,15,0,226,229,3,32,16,0,227,229,3,26,13,0,228,221,1, + 0,0,0,228,222,1,0,0,0,228,223,1,0,0,0,228,224,1,0,0,0,228,225,1, + 0,0,0,228,226,1,0,0,0,228,227,1,0,0,0,229,25,1,0,0,0,230,231,5,75, + 0,0,231,27,1,0,0,0,232,233,5,71,0,0,233,29,1,0,0,0,234,235,5,72, + 0,0,235,31,1,0,0,0,236,237,5,73,0,0,237,33,1,0,0,0,238,239,5,68, + 0,0,239,35,1,0,0,0,240,241,7,11,0,0,241,37,1,0,0,0,242,243,5,66, + 0,0,243,39,1,0,0,0,18,43,71,79,101,106,112,125,144,174,176,181,185, + 194,199,201,210,215,228 ] class qutes_parser ( Parser ): @@ -145,8 +149,8 @@ class qutes_parser ( Parser ): RULE_functionDeclarationParams = 2 RULE_variableDeclaration = 3 RULE_expr = 4 - RULE_functionCallParams = 5 - RULE_termList = 6 + RULE_termList = 5 + RULE_array = 6 RULE_variableType = 7 RULE_type = 8 RULE_qualifiedName = 9 @@ -162,10 +166,10 @@ class qutes_parser ( Parser ): RULE_boolean = 19 ruleNames = [ "program", "statement", "functionDeclarationParams", - "variableDeclaration", "expr", "functionCallParams", - "termList", "variableType", "type", "qualifiedName", - "variableName", "functionName", "literal", "string", - "qubit", "quint", "qustring", "float", "integer", "boolean" ] + "variableDeclaration", "expr", "termList", "array", "variableType", + "type", "qualifiedName", "variableName", "functionName", + "literal", "string", "qubit", "quint", "qustring", "float", + "integer", "boolean" ] EOF = Token.EOF INT_TYPE=1 @@ -302,7 +306,7 @@ def program(self): self.state = 43 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & 837813568856974334) != 0) or ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): + while (((_la) & ~0x3f) == 0 and ((1 << _la) & 3143656578070668286) != 0) or ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): self.state = 40 self.statement() self.state = 45 @@ -767,7 +771,7 @@ def statement(self): self.state = 71 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & 837813568856974334) != 0) or ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): + while (((_la) & ~0x3f) == 0 and ((1 << _la) & 3143656578070668286) != 0) or ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): self.state = 68 self.statement() self.state = 73 @@ -1224,8 +1228,8 @@ def ROUND_PARENTHESIS_OPEN(self): return self.getToken(qutes_parser.ROUND_PARENTHESIS_OPEN, 0) def ROUND_PARENTHESIS_CLOSE(self): return self.getToken(qutes_parser.ROUND_PARENTHESIS_CLOSE, 0) - def functionCallParams(self): - return self.getTypedRuleContext(qutes_parser.FunctionCallParamsContext,0) + def termList(self): + return self.getTypedRuleContext(qutes_parser.TermListContext,0) def enterRule(self, listener:ParseTreeListener): @@ -1402,6 +1406,31 @@ def accept(self, visitor:ParseTreeVisitor): return visitor.visitChildren(self) + class ArrayExpressionContext(ExprContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.ExprContext + super().__init__(parser) + self.copyFrom(ctx) + + def array(self): + return self.getTypedRuleContext(qutes_parser.ArrayContext,0) + + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterArrayExpression" ): + listener.enterArrayExpression(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitArrayExpression" ): + listener.exitArrayExpression(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitArrayExpression" ): + return visitor.visitArrayExpression(self) + else: + return visitor.visitChildren(self) + + class MultipleUnaryPhaseOperatorContext(ExprContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.ExprContext @@ -1539,6 +1568,38 @@ def accept(self, visitor:ParseTreeVisitor): return visitor.visitChildren(self) + class ArrayAccessExpressionContext(ExprContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.ExprContext + super().__init__(parser) + self.copyFrom(ctx) + + def expr(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(qutes_parser.ExprContext) + else: + return self.getTypedRuleContext(qutes_parser.ExprContext,i) + + def SQUARE_PARENTHESIS_OPEN(self): + return self.getToken(qutes_parser.SQUARE_PARENTHESIS_OPEN, 0) + def SQUARE_PARENTHESIS_CLOSE(self): + return self.getToken(qutes_parser.SQUARE_PARENTHESIS_CLOSE, 0) + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterArrayAccessExpression" ): + listener.enterArrayAccessExpression(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitArrayAccessExpression" ): + listener.exitArrayAccessExpression(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitArrayAccessExpression" ): + return visitor.visitArrayAccessExpression(self) + else: + return visitor.visitChildren(self) + + class LogicOrOperatorContext(ExprContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.ExprContext @@ -1581,7 +1642,7 @@ def expr(self, _p:int=0): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 143 + self.state = 144 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,7,self._ctx) if la_ == 1: @@ -1614,30 +1675,38 @@ def expr(self, _p:int=0): pass elif la_ == 4: - localctx = qutes_parser.FunctionCallExpressionContext(self, localctx) + localctx = qutes_parser.ArrayExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx self.state = 121 - self.functionName() + self.array() + pass + + elif la_ == 5: + localctx = qutes_parser.FunctionCallExpressionContext(self, localctx) + self._ctx = localctx + _prevctx = localctx self.state = 122 + self.functionName() + self.state = 123 self.match(qutes_parser.ROUND_PARENTHESIS_OPEN) - self.state = 124 + self.state = 125 self._errHandler.sync(self) _la = self._input.LA(1) if ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): - self.state = 123 - self.functionCallParams() + self.state = 124 + self.termList() - self.state = 126 + self.state = 127 self.match(qutes_parser.ROUND_PARENTHESIS_CLOSE) pass - elif la_ == 5: + elif la_ == 6: localctx = qutes_parser.PrefixOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 128 + self.state = 129 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 3298534940672) != 0)): @@ -1645,15 +1714,15 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 129 + self.state = 130 self.expr(12) pass - elif la_ == 6: + elif la_ == 7: localctx = qutes_parser.MultipleUnaryOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 130 + self.state = 131 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 59244544) != 0)): @@ -1661,15 +1730,15 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 131 + self.state = 132 self.termList() pass - elif la_ == 7: + elif la_ == 8: localctx = qutes_parser.UnaryOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 132 + self.state = 133 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 942669824) != 0)): @@ -1677,39 +1746,39 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 133 + self.state = 134 self.expr(3) pass - elif la_ == 8: + elif la_ == 9: localctx = qutes_parser.MultipleUnaryPhaseOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 134 - localctx.op = self.match(qutes_parser.MCP) self.state = 135 - self.termList() + localctx.op = self.match(qutes_parser.MCP) self.state = 136 - self.match(qutes_parser.BY) + self.termList() self.state = 137 + self.match(qutes_parser.BY) + self.state = 138 self.expr(2) pass - elif la_ == 9: + elif la_ == 10: localctx = qutes_parser.GroverOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 139 - self.termList() self.state = 140 - localctx.op = self.match(qutes_parser.IN_STATEMENT) + self.termList() self.state = 141 + localctx.op = self.match(qutes_parser.IN_STATEMENT) + self.state = 142 self.qualifiedName() pass self._ctx.stop = self._input.LT(-1) - self.state = 170 + self.state = 176 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,9,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1717,17 +1786,17 @@ def expr(self, _p:int=0): if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 168 + self.state = 174 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,8,self._ctx) if la_ == 1: localctx = qutes_parser.MultiplicativeOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 145 + self.state = 146 if not self.precpred(self._ctx, 11): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 11)") - self.state = 146 + self.state = 147 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 7168) != 0)): @@ -1735,18 +1804,18 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 147 + self.state = 148 self.expr(12) pass elif la_ == 2: localctx = qutes_parser.SumOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 148 + self.state = 149 if not self.precpred(self._ctx, 10): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 10)") - self.state = 149 + self.state = 150 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not(_la==13 or _la==14): @@ -1754,18 +1823,18 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 150 + self.state = 151 self.expr(11) pass elif la_ == 3: localctx = qutes_parser.ShiftOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 151 + self.state = 152 if not self.precpred(self._ctx, 9): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 9)") - self.state = 152 + self.state = 153 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not(_la==37 or _la==38): @@ -1773,18 +1842,18 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 153 + self.state = 154 self.expr(10) pass elif la_ == 4: localctx = qutes_parser.RelationalOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 154 + self.state = 155 if not self.precpred(self._ctx, 8): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 8)") - self.state = 155 + self.state = 156 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 128849018880) != 0)): @@ -1792,18 +1861,18 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 156 + self.state = 157 self.expr(9) pass elif la_ == 5: localctx = qutes_parser.EqualityOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 157 + self.state = 158 if not self.precpred(self._ctx, 7): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 7)") - self.state = 158 + self.state = 159 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not(_la==31 or _la==32): @@ -1811,44 +1880,59 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 159 + self.state = 160 self.expr(8) pass elif la_ == 6: localctx = qutes_parser.LogicAndOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 160 + self.state = 161 if not self.precpred(self._ctx, 6): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 6)") - self.state = 161 - localctx.op = self.match(qutes_parser.AND) self.state = 162 + localctx.op = self.match(qutes_parser.AND) + self.state = 163 self.expr(7) pass elif la_ == 7: localctx = qutes_parser.LogicOrOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 163 + self.state = 164 if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") - self.state = 164 - localctx.op = self.match(qutes_parser.OR) self.state = 165 + localctx.op = self.match(qutes_parser.OR) + self.state = 166 self.expr(6) pass elif la_ == 8: + localctx = qutes_parser.ArrayAccessExpressionContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) + self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) + self.state = 167 + if not self.precpred(self._ctx, 14): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 14)") + self.state = 168 + self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) + self.state = 169 + self.expr(0) + self.state = 170 + self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) + pass + + elif la_ == 9: localctx = qutes_parser.PostfixOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 166 + self.state = 172 if not self.precpred(self._ctx, 13): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 13)") - self.state = 167 + self.state = 173 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not(_la==40 or _la==41): @@ -1859,7 +1943,7 @@ def expr(self, _p:int=0): pass - self.state = 172 + self.state = 178 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,9,self._ctx) @@ -1872,7 +1956,7 @@ def expr(self, _p:int=0): return localctx - class FunctionCallParamsContext(ParserRuleContext): + class TermListContext(ParserRuleContext): __slots__ = 'parser' def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1890,59 +1974,58 @@ def qualifiedName(self): def COMMA(self): return self.getToken(qutes_parser.COMMA, 0) - def functionCallParams(self): - return self.getTypedRuleContext(qutes_parser.FunctionCallParamsContext,0) + def termList(self): + return self.getTypedRuleContext(qutes_parser.TermListContext,0) def getRuleIndex(self): - return qutes_parser.RULE_functionCallParams + return qutes_parser.RULE_termList def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterFunctionCallParams" ): - listener.enterFunctionCallParams(self) + if hasattr( listener, "enterTermList" ): + listener.enterTermList(self) def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitFunctionCallParams" ): - listener.exitFunctionCallParams(self) + if hasattr( listener, "exitTermList" ): + listener.exitTermList(self) def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitFunctionCallParams" ): - return visitor.visitFunctionCallParams(self) + if hasattr( visitor, "visitTermList" ): + return visitor.visitTermList(self) else: return visitor.visitChildren(self) - def functionCallParams(self): + def termList(self): - localctx = qutes_parser.FunctionCallParamsContext(self, self._ctx, self.state) - self.enterRule(localctx, 10, self.RULE_functionCallParams) - self._la = 0 # Token type + localctx = qutes_parser.TermListContext(self, self._ctx, self.state) + self.enterRule(localctx, 10, self.RULE_termList) try: self.enterOuterAlt(localctx, 1) - self.state = 175 + self.state = 181 self._errHandler.sync(self) token = self._input.LA(1) if token in [66, 67, 68, 69, 70, 71, 72, 73, 75]: - self.state = 173 + self.state = 179 self.literal() pass elif token in [74]: - self.state = 174 + self.state = 180 self.qualifiedName() pass else: raise NoViableAltException(self) - self.state = 179 + self.state = 185 self._errHandler.sync(self) - _la = self._input.LA(1) - if _la==65: - self.state = 177 + la_ = self._interp.adaptivePredict(self._input,11,self._ctx) + if la_ == 1: + self.state = 183 self.match(qutes_parser.COMMA) - self.state = 178 - self.functionCallParams() + self.state = 184 + self.termList() except RecognitionException as re: @@ -1954,78 +2037,55 @@ def functionCallParams(self): return localctx - class TermListContext(ParserRuleContext): + class ArrayContext(ParserRuleContext): __slots__ = 'parser' def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser - def literal(self): - return self.getTypedRuleContext(qutes_parser.LiteralContext,0) - - - def qualifiedName(self): - return self.getTypedRuleContext(qutes_parser.QualifiedNameContext,0) - - - def COMMA(self): - return self.getToken(qutes_parser.COMMA, 0) + def SQUARE_PARENTHESIS_OPEN(self): + return self.getToken(qutes_parser.SQUARE_PARENTHESIS_OPEN, 0) def termList(self): return self.getTypedRuleContext(qutes_parser.TermListContext,0) + def SQUARE_PARENTHESIS_CLOSE(self): + return self.getToken(qutes_parser.SQUARE_PARENTHESIS_CLOSE, 0) + def getRuleIndex(self): - return qutes_parser.RULE_termList + return qutes_parser.RULE_array def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterTermList" ): - listener.enterTermList(self) + if hasattr( listener, "enterArray" ): + listener.enterArray(self) def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitTermList" ): - listener.exitTermList(self) + if hasattr( listener, "exitArray" ): + listener.exitArray(self) def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitTermList" ): - return visitor.visitTermList(self) + if hasattr( visitor, "visitArray" ): + return visitor.visitArray(self) else: return visitor.visitChildren(self) - def termList(self): + def array(self): - localctx = qutes_parser.TermListContext(self, self._ctx, self.state) - self.enterRule(localctx, 12, self.RULE_termList) + localctx = qutes_parser.ArrayContext(self, self._ctx, self.state) + self.enterRule(localctx, 12, self.RULE_array) try: self.enterOuterAlt(localctx, 1) - self.state = 183 - self._errHandler.sync(self) - token = self._input.LA(1) - if token in [66, 67, 68, 69, 70, 71, 72, 73, 75]: - self.state = 181 - self.literal() - pass - elif token in [74]: - self.state = 182 - self.qualifiedName() - pass - else: - raise NoViableAltException(self) - self.state = 187 - self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,13,self._ctx) - if la_ == 1: - self.state = 185 - self.match(qutes_parser.COMMA) - self.state = 186 - self.termList() - - + self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) + self.state = 188 + self.termList() + self.state = 189 + self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) @@ -2046,6 +2106,12 @@ def type_(self): return self.getTypedRuleContext(qutes_parser.TypeContext,0) + def SQUARE_PARENTHESIS_OPEN(self): + return self.getToken(qutes_parser.SQUARE_PARENTHESIS_OPEN, 0) + + def SQUARE_PARENTHESIS_CLOSE(self): + return self.getToken(qutes_parser.SQUARE_PARENTHESIS_CLOSE, 0) + def qualifiedName(self): return self.getTypedRuleContext(qutes_parser.QualifiedNameContext,0) @@ -2074,19 +2140,40 @@ def variableType(self): localctx = qutes_parser.VariableTypeContext(self, self._ctx, self.state) self.enterRule(localctx, 14, self.RULE_variableType) + self._la = 0 # Token type try: - self.state = 191 + self.state = 201 self._errHandler.sync(self) token = self._input.LA(1) if token in [1, 2, 3, 4, 5, 6, 7, 8]: self.enterOuterAlt(localctx, 1) - self.state = 189 + self.state = 191 self.type_() + self.state = 194 + self._errHandler.sync(self) + _la = self._input.LA(1) + if _la==61: + self.state = 192 + self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) + self.state = 193 + self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) + + pass elif token in [74]: self.enterOuterAlt(localctx, 2) - self.state = 190 + self.state = 196 self.qualifiedName() + self.state = 199 + self._errHandler.sync(self) + _la = self._input.LA(1) + if _la==61: + self.state = 197 + self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) + self.state = 198 + self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) + + pass else: raise NoViableAltException(self) @@ -2158,7 +2245,7 @@ def type_(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 193 + self.state = 203 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 510) != 0)): self._errHandler.recoverInline(self) @@ -2226,23 +2313,23 @@ def qualifiedName(self): localctx = qutes_parser.QualifiedNameContext(self, self._ctx, self.state) self.enterRule(localctx, 18, self.RULE_qualifiedName) try: - self.state = 205 + self.state = 215 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,16,self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 195 + self.state = 205 self.match(qutes_parser.SYMBOL_LITERAL) - self.state = 200 + self.state = 210 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,15,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: - self.state = 196 + self.state = 206 self.match(qutes_parser.DOT) - self.state = 197 + self.state = 207 self.match(qutes_parser.SYMBOL_LITERAL) - self.state = 202 + self.state = 212 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,15,self._ctx) @@ -2250,13 +2337,13 @@ def qualifiedName(self): elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 203 + self.state = 213 self.variableName() pass elif la_ == 3: self.enterOuterAlt(localctx, 3) - self.state = 204 + self.state = 214 self.functionName() pass @@ -2306,7 +2393,7 @@ def variableName(self): self.enterRule(localctx, 20, self.RULE_variableName) try: self.enterOuterAlt(localctx, 1) - self.state = 207 + self.state = 217 self.match(qutes_parser.SYMBOL_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2353,7 +2440,7 @@ def functionName(self): self.enterRule(localctx, 22, self.RULE_functionName) try: self.enterOuterAlt(localctx, 1) - self.state = 209 + self.state = 219 self.match(qutes_parser.SYMBOL_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2424,42 +2511,42 @@ def literal(self): localctx = qutes_parser.LiteralContext(self, self._ctx, self.state) self.enterRule(localctx, 24, self.RULE_literal) try: - self.state = 218 + self.state = 228 self._errHandler.sync(self) token = self._input.LA(1) if token in [66]: self.enterOuterAlt(localctx, 1) - self.state = 211 + self.state = 221 self.boolean() pass elif token in [67, 69, 70]: self.enterOuterAlt(localctx, 2) - self.state = 212 + self.state = 222 self.integer() pass elif token in [68]: self.enterOuterAlt(localctx, 3) - self.state = 213 + self.state = 223 self.float_() pass elif token in [71]: self.enterOuterAlt(localctx, 4) - self.state = 214 + self.state = 224 self.qubit() pass elif token in [72]: self.enterOuterAlt(localctx, 5) - self.state = 215 + self.state = 225 self.quint() pass elif token in [73]: self.enterOuterAlt(localctx, 6) - self.state = 216 + self.state = 226 self.qustring() pass elif token in [75]: self.enterOuterAlt(localctx, 7) - self.state = 217 + self.state = 227 self.string() pass else: @@ -2510,7 +2597,7 @@ def string(self): self.enterRule(localctx, 26, self.RULE_string) try: self.enterOuterAlt(localctx, 1) - self.state = 220 + self.state = 230 self.match(qutes_parser.STRING_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2557,7 +2644,7 @@ def qubit(self): self.enterRule(localctx, 28, self.RULE_qubit) try: self.enterOuterAlt(localctx, 1) - self.state = 222 + self.state = 232 self.match(qutes_parser.QUBIT_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2604,7 +2691,7 @@ def quint(self): self.enterRule(localctx, 30, self.RULE_quint) try: self.enterOuterAlt(localctx, 1) - self.state = 224 + self.state = 234 self.match(qutes_parser.QUINT_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2651,7 +2738,7 @@ def qustring(self): self.enterRule(localctx, 32, self.RULE_qustring) try: self.enterOuterAlt(localctx, 1) - self.state = 226 + self.state = 236 self.match(qutes_parser.QUSTRING_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2698,7 +2785,7 @@ def float_(self): self.enterRule(localctx, 34, self.RULE_float) try: self.enterOuterAlt(localctx, 1) - self.state = 228 + self.state = 238 self.match(qutes_parser.FLOAT_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2752,7 +2839,7 @@ def integer(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 230 + self.state = 240 _la = self._input.LA(1) if not(((((_la - 67)) & ~0x3f) == 0 and ((1 << (_la - 67)) & 13) != 0)): self._errHandler.recoverInline(self) @@ -2804,7 +2891,7 @@ def boolean(self): self.enterRule(localctx, 38, self.RULE_boolean) try: self.enterOuterAlt(localctx, 1) - self.state = 232 + self.state = 242 self.match(qutes_parser.BOOL_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2856,6 +2943,10 @@ def expr_sempred(self, localctx:ExprContext, predIndex:int): if predIndex == 7: + return self.precpred(self._ctx, 14) + + + if predIndex == 8: return self.precpred(self._ctx, 13) diff --git a/src/qutes_antlr/qutes_parserListener.py b/src/qutes_antlr/qutes_parserListener.py index bd7d433..56734dd 100644 --- a/src/qutes_antlr/qutes_parserListener.py +++ b/src/qutes_antlr/qutes_parserListener.py @@ -251,6 +251,15 @@ def exitParentesizeExpression(self, ctx:qutes_parser.ParentesizeExpressionContex pass + # Enter a parse tree produced by qutes_parser#ArrayExpression. + def enterArrayExpression(self, ctx:qutes_parser.ArrayExpressionContext): + pass + + # Exit a parse tree produced by qutes_parser#ArrayExpression. + def exitArrayExpression(self, ctx:qutes_parser.ArrayExpressionContext): + pass + + # Enter a parse tree produced by qutes_parser#MultipleUnaryPhaseOperator. def enterMultipleUnaryPhaseOperator(self, ctx:qutes_parser.MultipleUnaryPhaseOperatorContext): pass @@ -287,21 +296,21 @@ def exitUnaryOperator(self, ctx:qutes_parser.UnaryOperatorContext): pass - # Enter a parse tree produced by qutes_parser#LogicOrOperator. - def enterLogicOrOperator(self, ctx:qutes_parser.LogicOrOperatorContext): + # Enter a parse tree produced by qutes_parser#ArrayAccessExpression. + def enterArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionContext): pass - # Exit a parse tree produced by qutes_parser#LogicOrOperator. - def exitLogicOrOperator(self, ctx:qutes_parser.LogicOrOperatorContext): + # Exit a parse tree produced by qutes_parser#ArrayAccessExpression. + def exitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionContext): pass - # Enter a parse tree produced by qutes_parser#functionCallParams. - def enterFunctionCallParams(self, ctx:qutes_parser.FunctionCallParamsContext): + # Enter a parse tree produced by qutes_parser#LogicOrOperator. + def enterLogicOrOperator(self, ctx:qutes_parser.LogicOrOperatorContext): pass - # Exit a parse tree produced by qutes_parser#functionCallParams. - def exitFunctionCallParams(self, ctx:qutes_parser.FunctionCallParamsContext): + # Exit a parse tree produced by qutes_parser#LogicOrOperator. + def exitLogicOrOperator(self, ctx:qutes_parser.LogicOrOperatorContext): pass @@ -314,6 +323,15 @@ def exitTermList(self, ctx:qutes_parser.TermListContext): pass + # Enter a parse tree produced by qutes_parser#array. + def enterArray(self, ctx:qutes_parser.ArrayContext): + pass + + # Exit a parse tree produced by qutes_parser#array. + def exitArray(self, ctx:qutes_parser.ArrayContext): + pass + + # Enter a parse tree produced by qutes_parser#variableType. def enterVariableType(self, ctx:qutes_parser.VariableTypeContext): pass diff --git a/src/qutes_antlr/qutes_parserVisitor.py b/src/qutes_antlr/qutes_parserVisitor.py index cff0cb9..0191cc7 100644 --- a/src/qutes_antlr/qutes_parserVisitor.py +++ b/src/qutes_antlr/qutes_parserVisitor.py @@ -144,6 +144,11 @@ def visitParentesizeExpression(self, ctx:qutes_parser.ParentesizeExpressionConte return self.visitChildren(ctx) + # Visit a parse tree produced by qutes_parser#ArrayExpression. + def visitArrayExpression(self, ctx:qutes_parser.ArrayExpressionContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by qutes_parser#MultipleUnaryPhaseOperator. def visitMultipleUnaryPhaseOperator(self, ctx:qutes_parser.MultipleUnaryPhaseOperatorContext): return self.visitChildren(ctx) @@ -164,13 +169,13 @@ def visitUnaryOperator(self, ctx:qutes_parser.UnaryOperatorContext): return self.visitChildren(ctx) - # Visit a parse tree produced by qutes_parser#LogicOrOperator. - def visitLogicOrOperator(self, ctx:qutes_parser.LogicOrOperatorContext): + # Visit a parse tree produced by qutes_parser#ArrayAccessExpression. + def visitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionContext): return self.visitChildren(ctx) - # Visit a parse tree produced by qutes_parser#functionCallParams. - def visitFunctionCallParams(self, ctx:qutes_parser.FunctionCallParamsContext): + # Visit a parse tree produced by qutes_parser#LogicOrOperator. + def visitLogicOrOperator(self, ctx:qutes_parser.LogicOrOperatorContext): return self.visitChildren(ctx) @@ -179,6 +184,11 @@ def visitTermList(self, ctx:qutes_parser.TermListContext): return self.visitChildren(ctx) + # Visit a parse tree produced by qutes_parser#array. + def visitArray(self, ctx:qutes_parser.ArrayContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by qutes_parser#variableType. def visitVariableType(self, ctx:qutes_parser.VariableTypeContext): return self.visitChildren(ctx) diff --git a/src/symbols/symbol.py b/src/symbols/symbol.py index 02567e8..437608c 100644 --- a/src/symbols/symbol.py +++ b/src/symbols/symbol.py @@ -9,8 +9,16 @@ class SymbolClass(Enum): VariableSymbol = auto() class Symbol(): - def __init__(self, name:str, symbol_class:SymbolClass, symbol_declaration_static_type:QutesDataType, casted_static_type:QutesDataType, value:any, parent_scope:ScopeTreeNode, ast_token_index:int, quantum_register : QuantumRegister | None = None, params = []): - super().__init__() + def __init__(self, + name:str, + symbol_class:SymbolClass, + symbol_declaration_static_type:QutesDataType, + casted_static_type:QutesDataType, + value:any, + parent_scope:ScopeTreeNode, + ast_token_index:int, + quantum_register : QuantumRegister | None = None, + params = []): self.name:str = name self.symbol_class:SymbolClass = symbol_class self.symbol_declaration_static_type:QutesDataType = symbol_declaration_static_type @@ -36,7 +44,18 @@ def function_matches_signature(self, function_name:str, function_params:list['Sy return False return True return False - + + def is_classical(self) -> bool: + return not QutesDataType.is_quantum_type(self.symbol_declaration_static_type) + + def is_quantum(self) -> bool: + return QutesDataType.is_quantum_type(self.symbol_declaration_static_type) + + def is_array(self) -> bool: + return QutesDataType.is_array_type(self.symbol_declaration_static_type) + + def get_array_unit_type(self) -> bool: + pass #TODO: handle def __to_printable__(self) -> str: if self.symbol_class is SymbolClass.FunctionSymbol: @@ -44,7 +63,6 @@ def __to_printable__(self) -> str: else: return f"{self.parent_scope.scope_type_detail}.{self.name}={self.value}({self.symbol_declaration_static_type.name}/{self.casted_static_type.name}/{self.ast_token_index})" - def __str__(self) -> str: return self.__to_printable__() diff --git a/src/symbols/types/__init__.py b/src/symbols/types/__init__.py index ef10031..f81a2df 100644 --- a/src/symbols/types/__init__.py +++ b/src/symbols/types/__init__.py @@ -1,6 +1,7 @@ # Aliasing for easy importing through the code -from symbols.types.qubit import Qubit from symbols.types.quantum_type import QuantumType +from symbols.types.quantum_array_type import QuantumArrayType +from symbols.types.qubit import Qubit from symbols.types.quint import Quint from symbols.types.qustring import Qustring from symbols.types.qutes_data_type import QutesDataType \ No newline at end of file diff --git a/src/symbols/types/quantum_array_type.py b/src/symbols/types/quantum_array_type.py new file mode 100644 index 0000000..654f907 --- /dev/null +++ b/src/symbols/types/quantum_array_type.py @@ -0,0 +1,8 @@ +from typing import TypeVar +from symbols.types import QuantumType + +T = TypeVar("T") + +class QuantumArrayType(QuantumType[T]): + def __init__(self) -> None: + pass \ No newline at end of file diff --git a/src/symbols/types/quantum_type.py b/src/symbols/types/quantum_type.py index f9709af..79f9a4a 100644 --- a/src/symbols/types/quantum_type.py +++ b/src/symbols/types/quantum_type.py @@ -1,13 +1,23 @@ -from symbols.types import Qubit +from typing import Generic, TypeVar -class QuantumType: - default_value = [Qubit(complex(1),complex(0))] - default_size_in_qubit = 1 - default_superposition_value = [Qubit(complex(0.5),complex(0.5))] +T = TypeVar("T") +class QuantumType(Generic[T]): def __init__(self): pass + def get_default_value(): + raise NotImplementedError("get_default_value method must be implemented in derived class") + + def get_default_superposition_value(): + raise NotImplementedError("get_default_superposition_value method must be implemented in derived class") + + def get_default_size_in_qubit(): + raise NotImplementedError("get_default_size_in_qubit method must be implemented in derived class") + + def __to_printable__(self) -> str: + raise NotImplementedError("__to_printable__ method must be implemented in derived class") + def __str__(self) -> str: return self.__to_printable__() diff --git a/src/symbols/types/qubit.py b/src/symbols/types/qubit.py index c37cd19..25b2d76 100644 --- a/src/symbols/types/qubit.py +++ b/src/symbols/types/qubit.py @@ -1,8 +1,9 @@ from grammar_frontend.qutes_parser import QutesParser +from symbols.types import QuantumType from utils.phase import Phase import cmath -class Qubit(): +class Qubit(QuantumType['Qubit']): def __init__(self, alpha : complex = complex(1), beta : complex = complex(0)): self.size:int = 1 self.alpha = complex(alpha) @@ -11,6 +12,15 @@ def __init__(self, alpha : complex = complex(1), beta : complex = complex(0)): self.is_superposition = cmath.isclose(abs(alpha), abs(beta)) self.qubit_state:list[Qubit] = [self] + def get_default_value(): + return Qubit(complex(1),complex(0)) + + def get_default_superposition_value(): + return Qubit(complex(0.5),complex(0.5)) + + def get_default_size_in_qubit(): + return 1 + def from_string(literal : str) -> 'Qubit': try: literal = literal.removesuffix(QutesParser.literal_to_string(QutesParser.QUBIT_LITERAL_POSTFIX)) @@ -69,10 +79,4 @@ def __to_printable__(self) -> str: if(self.is_superposition): return f"|{spin_str}>" else: - return f"[(\u03B1:{self.alpha})|0> {spin_str} (\u03B2:{self.beta})|1>]" - - def __str__(self) -> str: - return self.__to_printable__() - - def __repr__(self) -> str: - return self.__to_printable__() \ No newline at end of file + return f"[(\u03B1:{self.alpha})|0> {spin_str} (\u03B2:{self.beta})|1>]" \ No newline at end of file diff --git a/src/symbols/types/quint.py b/src/symbols/types/quint.py index 1ed17ca..af3feca 100644 --- a/src/symbols/types/quint.py +++ b/src/symbols/types/quint.py @@ -1,19 +1,22 @@ from grammar_frontend.qutes_parser import QutesParser -from utils.phase import Phase +from symbols.types import Qubit, QuantumType import utils -from symbols.types import Qubit -from symbols.types import QuantumType - -class Quint(QuantumType): - default_value = [Qubit(complex(1),complex(0))] - default_superposition_value = [Qubit(complex(0.5),complex(0.5))] - default_size_in_qubit = 1 +class Quint(QuantumType['Quint']): def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): super().__init__() self.qubit_state:list[Qubit] = qubits self.size:int = len(self.qubit_state) + def get_default_value(): + return [Qubit(complex(1),complex(0))] * Qubit.get_default_size_in_qubit() + + def get_default_superposition_value(): + return [Qubit(complex(0.5),complex(0.5))] * Qubit.get_default_size_in_qubit() + + def get_default_size_in_qubit(): + return 1 + def init_from_string(literal : str) -> 'Quint': qubits = [] qubit_literal_postfix = QutesParser.literal_to_string(QutesParser.QUBIT_LITERAL_POSTFIX) diff --git a/src/symbols/types/qustring.py b/src/symbols/types/qustring.py index 1382bc7..50ed683 100644 --- a/src/symbols/types/qustring.py +++ b/src/symbols/types/qustring.py @@ -1,18 +1,15 @@ from grammar_frontend.qutes_parser import QutesParser -import utils, math from symbols.types import Qubit, Quint from symbols.types import QuantumType +import utils, math -class Qustring(QuantumType): +class Qustring(QuantumType['Qustring']): # note: chr and ord, parse int and char in ASCII for char of size 7 bits # allowed_chars = ['a', 'b', 'c', 'd', superposition_char, not_valid_char] # allowed_chars = ['0', '1', superposition_char, not_valid_char] superposition_char = '*' not_valid_char = 'X' allowed_chars = ['0', '1'] - default_size_in_qubit = math.ceil(math.log2(len(allowed_chars))) - default_value = [Qubit(complex(1),complex(0))] * default_size_in_qubit - default_superposition_value = [Qubit(complex(0.5),complex(0.5))] * default_size_in_qubit def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): super().__init__() @@ -20,6 +17,15 @@ def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): self.size:int = len(self.qubit_state) self.number_of_chars:int = int(self.size / Qustring.default_size_in_qubit) + def get_default_value(): + return [Qubit(complex(1),complex(0))] * Qubit.get_default_size_in_qubit() + + def get_default_superposition_value(): + return [Qubit(complex(0.5),complex(0.5))] * Qubit.get_default_size_in_qubit() + + def get_default_size_in_qubit(): + return math.ceil(math.log2(len(Qubit.allowed_chars))) + def get_char_from_int(int_value:int): if(int_value > len(Qustring.allowed_chars)): return Qustring.allowed_chars[-1] diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index a67e0ca..e216246 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -1,9 +1,12 @@ +#TODO: try refactor import directly from symbols.types from symbols.types.qubit import Qubit from symbols.types.quint import Quint from symbols.types.qustring import Qustring +from symbols.types.quantum_array_type import QuantumArrayType from enum import Enum, auto class QutesDataType(Enum): + # Primitive types undefined = -1 bool = 1 int = auto() @@ -13,6 +16,14 @@ class QutesDataType(Enum): quint = auto() qustring = auto() void = auto() + # Array types + bool_array = auto() + int_array = auto() + float_array = auto() + string_array = auto() + qubit_array = auto() + quint_array = auto() + qustring_array = auto() def is_quantum_type(type:str): return QutesDataType.is_quantum_type(QutesDataType.from_string_type(type)) @@ -29,18 +40,10 @@ def is_classical_type(type:'QutesDataType'): def is_array_type(type:str): return QutesDataType.is_array_type(QutesDataType.from_string_type(type)) - def get_array_word_bit(type:str): - return QutesDataType.get_array_word_bit(QutesDataType.from_string_type(type)) - def is_array_type(type:'QutesDataType'): - return type in [QutesDataType.qustring, QutesDataType.quint] - - def get_array_word_bit(type:'QutesDataType'): - match type: - case QutesDataType.qustring: - return Qustring.default_size_in_qubit - case _: - return 1 + return type in [ + QutesDataType.qustring, QutesDataType.quint, QutesDataType.string, # Can be access by [] operator but not really array types + QutesDataType.bool_array, QutesDataType.int_array, QutesDataType.float_array, QutesDataType.string_array, QutesDataType.qubit_array, QutesDataType.quint_array, QutesDataType.qustring_array] def type_of(var_value : any) -> 'QutesDataType': from symbols import Symbol @@ -60,27 +63,45 @@ def type_of(var_value : any) -> 'QutesDataType': return QutesDataType.quint if isinstance(var_value, Qustring): return QutesDataType.qustring + if isinstance(var_value, list): + if(len(var_value) == 0): + return QutesDataType.bool_array + return QutesDataType.promote_unit_to_array_type(QutesDataType.type_of(var_value[0])) + if isinstance(var_value, QuantumArrayType): + return QutesDataType.qubit_array + # TODO: Subscripted generics cannot be used with class and instance checks + # if isinstance(var_value, QuantumArrayType[Qubit]): + # return QutesDataType.qubit_array + # if isinstance(var_value, QuantumArrayType[Quint]): + # return QutesDataType.quint_array + # if isinstance(var_value, QuantumArrayType[Qustring]): + # return QutesDataType.qustring_array if isinstance(var_value, Symbol): return var_value.symbol_declaration_static_type return QutesDataType.undefined def from_string_type(var_definition_type : str) -> 'QutesDataType': to_match = var_definition_type.lower() + is_array_type = False + if(to_match.endswith("[]")): + to_match = to_match.removesuffix("[]") + is_array_type = True + match to_match: case "bool": - return QutesDataType.bool + return QutesDataType.bool if not is_array_type else QutesDataType.bool_array case "int": - return QutesDataType.int + return QutesDataType.int if not is_array_type else QutesDataType.int_array case "float": - return QutesDataType.float + return QutesDataType.float if not is_array_type else QutesDataType.float_array case "string": - return QutesDataType.string + return QutesDataType.string if not is_array_type else QutesDataType.string_array case "qubit": - return QutesDataType.qubit + return QutesDataType.qubit if not is_array_type else QutesDataType.qubit_array case "quint": - return QutesDataType.quint + return QutesDataType.quint if not is_array_type else QutesDataType.quint_array case "qustring": - return QutesDataType.qustring + return QutesDataType.qustring if not is_array_type else QutesDataType.qustring_array case "void": return QutesDataType.void case _: @@ -108,6 +129,25 @@ def promote_classical_to_quantum_value(classical_value: any) -> Qubit | Quint | case _: return QutesDataType.undefined + def promote_unit_to_array_type(unit_type : 'QutesDataType') -> 'QutesDataType': + match unit_type: + case QutesDataType.bool: + return QutesDataType.bool_array + case QutesDataType.int: + return QutesDataType.int_array + case QutesDataType.float: + return QutesDataType.float_array + case QutesDataType.string: + return QutesDataType.string_array + case QutesDataType.qubit: + return QutesDataType.qubit_array + case QutesDataType.quint: + return QutesDataType.quint_array + case QutesDataType.qustring: + return QutesDataType.qustring_array + case _: + return QutesDataType.undefined + def get_default_value(var_type : 'QutesDataType'): match var_type: case QutesDataType.bool: @@ -124,10 +164,45 @@ def get_default_value(var_type : 'QutesDataType'): return Quint() case QutesDataType.qustring: return Qustring() + case QutesDataType.bool_array: + return [] + case QutesDataType.int_array: + return [] + case QutesDataType.float_array: + return [] + case QutesDataType.string_array: + return [] + case QutesDataType.qubit_array: + return QuantumArrayType[Qubit]() + case QutesDataType.quint_array: + return QuantumArrayType[Quint]() + case QutesDataType.qustring_array: + return QuantumArrayType[Qustring]() case QutesDataType.void: return None case _: - return QutesDataType.undefined + return None + + def get_size_in_qubit(var_type : 'QutesDataType'): + match var_type: + case QutesDataType.bool: + return 1 + case QutesDataType.qubit: + return 1 + case QutesDataType.int: + return Quint.default_size_in_qubit + case QutesDataType.quint: + return Quint.default_size_in_qubit + case QutesDataType.string: + return Qustring.default_size_in_qubit + case QutesDataType.qustring: + return Qustring.default_size_in_qubit + case QutesDataType.void: + return 0 + case QutesDataType.float: + return 1 + case _: + return 1 def promote_type(self : 'QutesDataType', to_type : 'QutesDataType') -> 'QutesDataType': if(self in TypeCastingHandler.type_promotable_to[to_type]): @@ -157,6 +232,13 @@ def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): QutesDataType.quint: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], QutesDataType.qustring: [QutesDataType.qustring, QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], QutesDataType.void: [], + QutesDataType.bool_array: [], + QutesDataType.int_array: [], + QutesDataType.float_array: [], + QutesDataType.string_array: [], + QutesDataType.qubit_array: [], + QutesDataType.quint_array: [], + QutesDataType.qustring_array: [], } type_down_castable_to : dict[Enum, list[QutesDataType]] = { #..to this types <- this types can be converted(loosing information) to.. @@ -168,6 +250,13 @@ def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): QutesDataType.quint: [QutesDataType.quint], QutesDataType.qustring: [QutesDataType.qustring], QutesDataType.void: [], + QutesDataType.bool_array: [], + QutesDataType.int_array: [], + QutesDataType.float_array: [], + QutesDataType.string_array: [], + QutesDataType.qubit_array: [], + QutesDataType.quint_array: [], + QutesDataType.qustring_array: [], } def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: diff --git a/src/symbols/variables_handler.py b/src/symbols/variables_handler.py index 55d19c9..bf8cf77 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -97,6 +97,16 @@ def create_anonymous_symbol(self, qutes_type : QutesDataType, value, ast_token_i new_symbol = Symbol(variable_name, SymbolClass.VariableSymbol, qutes_type, final_type, value, self.scope_handler.current_symbols_scope, ast_token_index) new_symbol.is_anonymous = True return new_symbol + + def create_anonymous_symbol_from_quantum_register(self, qutes_type : QutesDataType, quantum_register, ast_token_index:int) -> Symbol: + variable_name = None + symbol_value = None + definition_type = qutes_type + final_type = definition_type + + new_symbol = Symbol(variable_name, SymbolClass.VariableSymbol, qutes_type, final_type, symbol_value, self.scope_handler.current_symbols_scope, ast_token_index, quantum_register) + new_symbol.is_anonymous = True + return new_symbol def declare_function(self, anonymous_symbol : Symbol, function_name : str, input_params_definition:list[Symbol] = list(), value = None) -> Symbol: diff --git a/src/tests/test_array_access.py b/src/tests/test_array_access.py new file mode 100644 index 0000000..6001ab5 --- /dev/null +++ b/src/tests/test_array_access.py @@ -0,0 +1,22 @@ +from .qutes_base_test import QutesBaseTest + +class TestArrayAccess(QutesBaseTest): + def assert_operation_test(self, code, var_name, expected_value_of_var): + result = self.parse_qutes_code(code) + actual_value_of_var = str(result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value) + self.assertEqual(actual_value_of_var, str(expected_value_of_var), f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") + + def test_left_shift_return_expected_value(self): + params = [ + ("\"01111111\"", "0", "01111111"), + ] + var_name = "a" + var_result_name = "result" + for init_string, n_shift, expected_value_of_var in params: + with self.subTest(init_string=init_string, n_shift=n_shift, expected_value_of_var=expected_value_of_var): + code = f""" + qustring {var_name} = {init_string}; + {var_name} << {n_shift}; + string {var_result_name} = {var_name}; + """ + self.assert_operation_test(code, var_result_name, expected_value_of_var) diff --git a/src/tests/test_grover.py b/src/tests/test_grover.py index d0462f5..45107f1 100644 --- a/src/tests/test_grover.py +++ b/src/tests/test_grover.py @@ -1,8 +1,6 @@ from .qutes_base_test import QutesBaseTest class TestGrover(QutesBaseTest): - TOKEN_AST_INDEX_FOR_TESTS = 100000 - # Grover search is probabilistic, there is a little chance no solution is found even if there should be one, and vice versa. # So if we fail the first time, we try again def assert_grover_test(self, code, var_name, expected_value_of_var): diff --git a/src/tests/test_operations.py b/src/tests/test_operations.py index c46e54f..342522f 100644 --- a/src/tests/test_operations.py +++ b/src/tests/test_operations.py @@ -1,8 +1,6 @@ from .qutes_base_test import QutesBaseTest class TestOperation(QutesBaseTest): - TOKEN_AST_INDEX_FOR_TESTS = 100000 - def assert_operation_test(self, code, var_name, expected_value_of_var): result = self.parse_qutes_code(code) actual_value_of_var = str(result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value) From e1f66a54e41b441a0ce43fbf7e2f1b6d5a009b83 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Fri, 12 Jul 2024 20:35:33 +0000 Subject: [PATCH 03/34] Implemented Array Access --- playground/examples/arrays.qut | 3 +- src/grammar_frontend/expression.py | 13 +------- src/grammar_frontend/literal.py | 22 +++++++------ src/grammar_frontend/operation.py | 19 ++++++----- src/grammar_frontend/statement.py | 2 ++ .../symbols_discovery_visitor.py | 2 +- .../quantum_circuit_handler.py | 8 ++--- src/symbols/variables_handler.py | 33 +++++++++---------- 8 files changed, 48 insertions(+), 54 deletions(-) diff --git a/playground/examples/arrays.qut b/playground/examples/arrays.qut index 0cbed13..1849e08 100644 --- a/playground/examples/arrays.qut +++ b/playground/examples/arrays.qut @@ -1,3 +1,4 @@ qubit b = 1q; qubit c = 0q; -qubit[] a = [b, c, |+>]; \ No newline at end of file +qubit[] a = [b, c, |+>]; +qubit d = a[2]; \ No newline at end of file diff --git a/src/grammar_frontend/expression.py b/src/grammar_frontend/expression.py index 57b8abb..f3ba6a8 100644 --- a/src/grammar_frontend/expression.py +++ b/src/grammar_frontend/expression.py @@ -73,16 +73,5 @@ def visitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionConte array_value = self.variables_handler.get_value(array_symbol) index_value = self.variables_handler.get_value(index_symbol) - array_unit_type_size = array_symbol.get_array_unit_type() - if array_symbol.is_classical_type(): - result = array_value[index_value] - return self.variables_handler.create_anonymous_symbol(QutesDataType.type_of(result), result, ctx.start.tokenIndex) - else: - array_unit_type_size = QutesDataType.get_size_in_qubit(array_unit_type_size) - result = array_symbol.quantum_register[index_value*array_unit_type_size:array_unit_type_size] - #TODO: non posso passare un array di qubit per creare il simbolo anonimo, dovrei sfruttare il circuit handler - # Oppure devo aggiornare il metodo create_anonymous_symbol per gestire quantum register - # In questo caso dovrebbe gestirli come se fossero reference type. - return self.variables_handler.create_anonymous_symbol_from_quantum_register(array_unit_type_size, result, ctx.start.tokenIndex) - + return array_value[index_value] diff --git a/src/grammar_frontend/literal.py b/src/grammar_frontend/literal.py index 4dbb210..bb2b42b 100644 --- a/src/grammar_frontend/literal.py +++ b/src/grammar_frontend/literal.py @@ -22,7 +22,7 @@ def visitFunctionDeclarationParams(self, ctx:qutes_parser.FunctionDeclarationPar if(not isinstance(params, list)): params = [params] params.append(param) - return params[::-1] + return params def visitTermList(self, ctx:qutes_parser.TermListContext) -> list[Symbol]: term = self.visit(ctx.literal()) if ctx.literal() else self.visit(ctx.qualifiedName()) @@ -32,10 +32,12 @@ def visitTermList(self, ctx:qutes_parser.TermListContext) -> list[Symbol]: if(not isinstance(terms, list)): terms = [terms] terms.append(term) - return terms[::-1] + return terms def visitArray(self, ctx:qutes_parser.ArrayContext) -> list[Symbol]: - return self.visit(ctx.termList()) + terms = self.visit(ctx.termList()) + terms.reverse() + return terms def visitVariableType(self, ctx:qutes_parser.VariableTypeContext): value = str(ctx.getText()) @@ -69,42 +71,42 @@ def visitLiteral(self, ctx:qutes_parser.LiteralContext): def visitString(self, ctx:qutes_parser.StringContext): string_literal_enclosure = qutes_parser.literal_to_string(qutes_parser.STRING_ENCLOSURE) value = ctx.getText().removeprefix(string_literal_enclosure).removesuffix(string_literal_enclosure) - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.string, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.string, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol def visitQubit(self, ctx:qutes_parser.QubitContext): value = Qubit.from_string(ctx.getText()) - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.qubit, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.qubit, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol def visitQuint(self, ctx:qutes_parser.QuintContext): value = Quint.init_from_string(ctx.getText()) - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.quint, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.quint, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol def visitQustring(self, ctx:qutes_parser.QustringContext): value = Qustring.init_from_string(ctx.getText()) - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.qustring, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.qustring, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol def visitFloat(self, ctx:qutes_parser.FloatContext): value = float(ctx.getText()) - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.float, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.float, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol def visitInteger(self, ctx:qutes_parser.IntegerContext): value = int(ctx.getText()) - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.int, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.int, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol def visitBoolean(self, ctx:qutes_parser.BooleanContext): value = ctx.getText().lower() == "true" or ctx.getText() == "1" - symbol = self.variables_handler.create_anonymous_symbol(QutesDataType.bool, value, ctx.start.tokenIndex) + symbol = self.variables_handler.declare_anonymous_variable(QutesDataType.bool, value, ctx.start.tokenIndex) if(self.log_code_structure): print(value, end=None) return symbol diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index ba535f3..b12121d 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -113,7 +113,7 @@ def __visit_binary_operator(self, ctx:qutes_parser.SumOperatorContext | qutes_pa pass result = first_term_value % second_term_value - return self.variables_handler.create_anonymous_symbol(QutesDataType.type_of(result), result, ctx.start.tokenIndex) + return self.variables_handler.declare_anonymous_variable(QutesDataType.type_of(result), result, ctx.start.tokenIndex) def __visit_boolean_operation(self, ctx:qutes_parser.RelationalOperatorContext | qutes_parser.EqualityOperatorContext | qutes_parser.LogicAndOperatorContext | qutes_parser.LogicOrOperatorContext): result = None @@ -149,10 +149,11 @@ def __visit_boolean_operation(self, ctx:qutes_parser.RelationalOperatorContext | elif(isinstance(ctx, qutes_parser.LogicOrOperatorContext)): if(ctx.OR()): result = first_term_value or second_term_value - return self.variables_handler.create_anonymous_symbol(QutesDataType.bool, result, ctx.start.tokenIndex) + return self.variables_handler.declare_anonymous_variable(QutesDataType.bool, result, ctx.start.tokenIndex) def __visitMultipleUnaryOperator(self, ctx:qutes_parser.MultipleUnaryOperatorContext): terms:list[Symbol] = self.visit(ctx.termList()) + terms.reverse() registers = [register.quantum_register for register in terms] if(self.log_code_structure): print(f"{ctx.op.text} {registers}", end=None) if(ctx.MCZ()): @@ -167,6 +168,7 @@ def __visitMultipleUnaryOperator(self, ctx:qutes_parser.MultipleUnaryOperatorCon def __visitMultipleUnaryPhaseOperator(self, ctx:qutes_parser.MultipleUnaryPhaseOperatorContext): terms:list[Symbol] = self.visit(ctx.termList()) + terms.reverse() registers = [register.quantum_register for register in terms] theta:Symbol = self.visit(ctx.expr()) if(self.log_code_structure): print(f"{ctx.op.text} {registers} by {theta}", end=None) @@ -246,15 +248,15 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p if(isinstance(ctx, qutes_parser.PostfixOperatorContext)): #TODO: handle quantum if(ctx.AUTO_INCREMENT()): - result = self.variables_handler.create_anonymous_symbol(QutesDataType.type_of(first_term_symbol), first_term_value, ctx.start.tokenIndex) + result = self.variables_handler.declare_anonymous_variable(QutesDataType.type_of(first_term_symbol), first_term_value, ctx.start.tokenIndex) first_term_symbol.value = first_term_symbol.value + 1 return result if(ctx.AUTO_DECREMENT()): - result = self.variables_handler.create_anonymous_symbol(QutesDataType.type_of(first_term_symbol), first_term_value, ctx.start.tokenIndex) + result = self.variables_handler.declare_anonymous_variable(QutesDataType.type_of(first_term_symbol), first_term_value, ctx.start.tokenIndex) first_term_symbol.value = first_term_symbol.value - 1 return result - return self.variables_handler.create_anonymous_symbol(QutesDataType.type_of(result), result, ctx.start.tokenIndex) + return self.variables_handler.declare_anonymous_variable(QutesDataType.type_of(result), result, ctx.start.tokenIndex) grover_count = iter(range(1, 1000)) def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): @@ -274,7 +276,8 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): n_element_to_rotate = array_size/block_size self.quantum_circuit_handler.start_quantum_function() - termList:list[Symbol] = self.visit(ctx.termList()) + termList:list[Symbol] = self.visit(ctx.termList()) + termList.reverse() grover_result = self.quantum_circuit_handler.declare_quantum_register("grover_phase_ancilla", Qubit()) oracle_registers = [array_register] @@ -336,6 +339,6 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): for result in positive_results: print(f"Solution found with {int(rotation_register.measured_classical_register.measured_values[result[0]], 2)} left rotations") # print(f"Solution found with rotation {int(rotation_register.measured_classical_register.measured_values[result[0]], 2) % (n_element_to_rotate)}") - return self.variables_handler.create_anonymous_symbol(QutesDataType.bool, True, ctx.start.tokenIndex) + return self.variables_handler.declare_anonymous_variable(QutesDataType.bool, True, ctx.start.tokenIndex) registers_to_measure.remove(oracle_result) - return self.variables_handler.create_anonymous_symbol(QutesDataType.bool, False, ctx.start.tokenIndex) + return self.variables_handler.declare_anonymous_variable(QutesDataType.bool, False, ctx.start.tokenIndex) diff --git a/src/grammar_frontend/statement.py b/src/grammar_frontend/statement.py index 51b5d58..467c970 100644 --- a/src/grammar_frontend/statement.py +++ b/src/grammar_frontend/statement.py @@ -90,8 +90,10 @@ def visitBlockStatement(self, ctx:qutes_parser.BlockStatementContext): def visitFunctionStatement(self, ctx:qutes_parser.FunctionStatementContext): self.scope_handler.push_scope() function_name = self.visit(ctx.functionName()) + function_params = [] if(ctx.functionDeclarationParams()): function_params = self.visit(ctx.functionDeclarationParams()) + function_params.reverse() #do not call a visit on the statement here, or on all the context, the statement is being saved by the discovery and should be traversed only on function execution self.scope_handler.pop_scope() return None diff --git a/src/grammar_frontend/symbols_discovery_visitor.py b/src/grammar_frontend/symbols_discovery_visitor.py index 947ee10..466c671 100644 --- a/src/grammar_frontend/symbols_discovery_visitor.py +++ b/src/grammar_frontend/symbols_discovery_visitor.py @@ -87,7 +87,7 @@ def visitFunctionStatement(self, ctx:qutesParser.FunctionStatementContext): function_body = ctx.statement() token_index = ctx.start.tokenIndex - funtion_symbol = self.variables_handler.create_anonymous_symbol(qutes_type, QutesDataType.get_default_value(qutes_type), token_index) + funtion_symbol = self.variables_handler.declare_anonymous_variable(qutes_type, QutesDataType.get_default_value(qutes_type), token_index) funtion_symbol = self.variables_handler.declare_function(funtion_symbol, function_name, [], function_body) self.scope_handler.push_inner_scope(ScopeClass.FunctionScope, f"Function{self.function_scope_count}", funtion_symbol) diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 00cd897..407f756 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -35,13 +35,13 @@ def declare_classical_register(self, variable_name : str, bits_number : int) -> self._classic_registers.append(new_register) return new_register - def delete_classical_register(self, variable_name : str) -> None: + def delete_variable(self, variable_name : str) -> None: register = self._varname_to_register[variable_name] - self._classic_registers.remove(register) + if(self._varname_to_register.values().count(register) == 0): + self._classic_registers.remove(register) def declare_quantum_register(self, variable_name : str, quantum_variable : any) -> QuantumRegister: new_register = None - new_register = QuantumRegister(quantum_variable.size, variable_name) if(new_register is None): @@ -67,8 +67,8 @@ def replace_quantum_register(self, variable_name : str, quantum_variable : any) #Add new quantum register register_to_update = self._varname_to_register[variable_name] = QuantumRegister(quantum_variable.size, variable_name) self._quantum_registers.append(register_to_update) + self._registers_states[register_to_update] = quantum_variable.get_quantum_state() - self._registers_states[register_to_update] = quantum_variable.get_quantum_state() return register_to_update def assign_quantum_register_to_variable(self, variable_name : str, quantum_register : QuantumRegister) -> QuantumRegister: diff --git a/src/symbols/variables_handler.py b/src/symbols/variables_handler.py index bf8cf77..ac9d0fb 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -1,3 +1,4 @@ +from uuid import uuid4 from symbols.types.qutes_data_type import QutesDataType, TypeCastingHandler from symbols.scope_handler import ScopeHandler from symbols.symbol import Symbol, SymbolClass @@ -43,15 +44,19 @@ def update_variable_state(self, variable_name : str, new_state) -> Symbol: #Handle quantum circuit update if(QutesDataType.is_quantum_type(symbol_to_update.symbol_declaration_static_type)): - if(isinstance(new_state, Symbol) and not new_state.is_anonymous): - symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.assign_quantum_register_to_variable(variable_name, new_state.quantum_register) + if(isinstance(new_state, Symbol)): + if(new_state.is_anonymous): + symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.replace_quantum_register(variable_name, new_state.value) + self.quantum_cirtcuit_handler.delete_variable(new_state.name) + else: + symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.assign_quantum_register_to_variable(variable_name, new_state.quantum_register) else: symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.replace_quantum_register(variable_name, symbol_to_update.value) return symbol_to_update else: raise SyntaxError(f"No variable declared with name '{variable_name}'.") - def declare_variable(self, declaration_type : QutesDataType, variable_name : str, ast_token_index:int, value = None) -> Symbol: + def declare_variable(self, declaration_type : QutesDataType, variable_name : str, ast_token_index:int, value = None, declare_as_anonymous = False) -> Symbol: already_taken_symbol_in_this_scope = [symbol for symbol in self.scope_handler.current_symbols_scope.symbols if symbol.name == variable_name and symbol.parent_scope == self.scope_handler.current_symbols_scope] if(len(already_taken_symbol_in_this_scope) == 0): if(value is None): @@ -59,9 +64,9 @@ def declare_variable(self, declaration_type : QutesDataType, variable_name : str else: value = self.get_value(value) - new_symbol = self.create_anonymous_symbol(declaration_type, value, ast_token_index) + new_symbol = self.create_symbol(declaration_type, value, ast_token_index) new_symbol.name = variable_name - new_symbol.is_anonymous = False + new_symbol.is_anonymous = declare_as_anonymous self.scope_handler.current_symbols_scope.symbols.append(new_symbol) #Handle quantum circuit update if(QutesDataType.is_quantum_type(declaration_type)): @@ -71,7 +76,11 @@ def declare_variable(self, declaration_type : QutesDataType, variable_name : str else: raise SyntaxError(f"Symbol with name '{variable_name}' already declared.") - def create_anonymous_symbol(self, qutes_type : QutesDataType, value, ast_token_index:int) -> Symbol: + + def declare_anonymous_variable(self, declaration_type : QutesDataType, value, ast_token_index:int) -> Symbol: + return self.declare_variable(declaration_type, f"anon_{uuid4().hex[:6]}", ast_token_index, value, True) + + def create_symbol(self, qutes_type : QutesDataType, value, ast_token_index:int) -> Symbol: if(value is None): value = QutesDataType.get_default_value(qutes_type) @@ -95,19 +104,7 @@ def create_anonymous_symbol(self, qutes_type : QutesDataType, value, ast_token_i raise TypeError(f"Cannot convert type '{definition_type}' to '{value_qutes_type}' for '{variable_name}'.") new_symbol = Symbol(variable_name, SymbolClass.VariableSymbol, qutes_type, final_type, value, self.scope_handler.current_symbols_scope, ast_token_index) - new_symbol.is_anonymous = True return new_symbol - - def create_anonymous_symbol_from_quantum_register(self, qutes_type : QutesDataType, quantum_register, ast_token_index:int) -> Symbol: - variable_name = None - symbol_value = None - definition_type = qutes_type - final_type = definition_type - - new_symbol = Symbol(variable_name, SymbolClass.VariableSymbol, qutes_type, final_type, symbol_value, self.scope_handler.current_symbols_scope, ast_token_index, quantum_register) - new_symbol.is_anonymous = True - return new_symbol - def declare_function(self, anonymous_symbol : Symbol, function_name : str, input_params_definition:list[Symbol] = list(), value = None) -> Symbol: already_taken_symbol_in_this_scope = [symbol for symbol in self.scope_handler.current_symbols_scope.symbols if symbol.name == function_name and symbol.parent_scope == self.scope_handler.current_symbols_scope] From 4d8dcdd3cdddb427f6efb9cd67abfc53e030f57d Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Fri, 12 Jul 2024 20:38:46 +0000 Subject: [PATCH 04/34] Fix quantum circuit variable deallocation only when no variable is referencing --- playground/examples/arrays.qut | 6 +++++- src/quantum_circuit/quantum_circuit_handler.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/playground/examples/arrays.qut b/playground/examples/arrays.qut index 1849e08..5d879e8 100644 --- a/playground/examples/arrays.qut +++ b/playground/examples/arrays.qut @@ -1,4 +1,8 @@ qubit b = 1q; qubit c = 0q; qubit[] a = [b, c, |+>]; -qubit d = a[2]; \ No newline at end of file +qubit d = a[2]; + +print d; +print a; +print c; \ No newline at end of file diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 407f756..ae7a183 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -37,7 +37,7 @@ def declare_classical_register(self, variable_name : str, bits_number : int) -> def delete_variable(self, variable_name : str) -> None: register = self._varname_to_register[variable_name] - if(self._varname_to_register.values().count(register) == 0): + if(register not in self._varname_to_register.values()): self._classic_registers.remove(register) def declare_quantum_register(self, variable_name : str, quantum_variable : any) -> QuantumRegister: From bd0d5ab148e54ae6b96bdd5d0ab08e358e97ac71 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Fri, 12 Jul 2024 20:48:35 +0000 Subject: [PATCH 05/34] Fix while loops condition update --- playground/examples/arrays.qut | 6 ++++++ src/grammar_frontend/statement.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/playground/examples/arrays.qut b/playground/examples/arrays.qut index 5d879e8..05bfba1 100644 --- a/playground/examples/arrays.qut +++ b/playground/examples/arrays.qut @@ -3,6 +3,12 @@ qubit c = 0q; qubit[] a = [b, c, |+>]; qubit d = a[2]; +int i = 0; +while(i<3){ + print a[i]; + i = i + 1; +} + print d; print a; print c; \ No newline at end of file diff --git a/src/grammar_frontend/statement.py b/src/grammar_frontend/statement.py index 467c970..d5fc35b 100644 --- a/src/grammar_frontend/statement.py +++ b/src/grammar_frontend/statement.py @@ -56,7 +56,7 @@ def __visit_while_statement(self, ctx:qutes_parser.IfStatementContext): self.scope_handler.start_loop() #avoid block statement to change the scope - while(condition): + while(self.variables_handler.get_value(condition)): self.visit(ctx.statement()) condition = self.visit(ctx.expr()) From 13cbbbd6b95d4aed72d64430bf5295185db4d7d6 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Fri, 12 Jul 2024 21:10:49 +0000 Subject: [PATCH 06/34] Improved language print and verbose output --- src/grammar_frontend/operation.py | 2 -- src/grammar_frontend/qutes_base_visitor.py | 8 +++++--- src/symbols/symbol.py | 13 ++++++++++--- src/symbols/types/qubit.py | 5 +++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index b12121d..8197dd9 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -196,10 +196,8 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p bin_char = bytes_str[index:Qustring.default_size_in_qubit + index] string_value = string_value + Qustring.get_char_from_int(int(bin_char, 2)) index = index + Qustring.default_size_in_qubit - print(string_value) else: new_value = int(bytes_str, 2) - print(new_value) #TODO: handle the conversion from a string of binadry digits to the current quantum variable type #TODO: adding the next line cause a crash in the circuit # self.variables_handler.update_variable_state(first_term_symbol.name, new_value) diff --git a/src/grammar_frontend/qutes_base_visitor.py b/src/grammar_frontend/qutes_base_visitor.py index 8710eb9..d39a404 100644 --- a/src/grammar_frontend/qutes_base_visitor.py +++ b/src/grammar_frontend/qutes_base_visitor.py @@ -5,6 +5,7 @@ from quantum_circuit import QuantumCircuitHandler from quantum_circuit.qutes_gates import QutesGates from qutes_antlr.qutes_parserVisitor import qutes_parserVisitor as qutesVisitor +from symbols.symbol import Symbol import inspect class QutesBaseVisitor(qutesVisitor): @@ -19,10 +20,11 @@ def __init__(self, symbols_tree:ScopeTreeNode, quantum_circuit_handler : Quantum self.qutes_gates = QutesGates(self.quantum_circuit_handler, self.variables_handler) # Debug flags + Symbol.verbose_print = verbose self.allow_program_print = True - self.log_code_structure = verbose - self.log_trace_enabled = verbose - self.log_step_by_step_results_enabled = verbose + self.log_code_structure = False + self.log_trace_enabled = False + self.log_step_by_step_results_enabled = False self.log_grover_verbose = verbose self.log_grover_esm_rotation = True diff --git a/src/symbols/symbol.py b/src/symbols/symbol.py index 437608c..a3637e8 100644 --- a/src/symbols/symbol.py +++ b/src/symbols/symbol.py @@ -9,6 +9,7 @@ class SymbolClass(Enum): VariableSymbol = auto() class Symbol(): + verbose_print = False def __init__(self, name:str, symbol_class:SymbolClass, @@ -58,10 +59,16 @@ def get_array_unit_type(self) -> bool: pass #TODO: handle def __to_printable__(self) -> str: - if self.symbol_class is SymbolClass.FunctionSymbol: - return f"{self.parent_scope.scope_type_detail}.{self.name}({self.function_input_params_definition}) -> {self.symbol_declaration_static_type.name}/{self.ast_token_index}" + if(Symbol.verbose_print): + if self.symbol_class is SymbolClass.FunctionSymbol: + return f"{self.parent_scope.scope_type_detail}.{self.name}({self.function_input_params_definition}) -> {self.symbol_declaration_static_type.name}" + else: + return f"{self.symbol_declaration_static_type.name} {self.parent_scope.scope_type_detail}.{self.name} = {self.value}" else: - return f"{self.parent_scope.scope_type_detail}.{self.name}={self.value}({self.symbol_declaration_static_type.name}/{self.casted_static_type.name}/{self.ast_token_index})" + if self.symbol_class is SymbolClass.FunctionSymbol: + return f"{self.parent_scope.scope_type_detail}.{self.name}({self.function_input_params_definition}) -> {self.symbol_declaration_static_type.name}" + else: + return f"{self.value}" def __str__(self) -> str: return self.__to_printable__() diff --git a/src/symbols/types/qubit.py b/src/symbols/types/qubit.py index 25b2d76..b90d727 100644 --- a/src/symbols/types/qubit.py +++ b/src/symbols/types/qubit.py @@ -78,5 +78,6 @@ def __to_printable__(self) -> str: spin_str = '+' if self.phase == Phase.Positive else '-' if(self.is_superposition): return f"|{spin_str}>" - else: - return f"[(\u03B1:{self.alpha})|0> {spin_str} (\u03B2:{self.beta})|1>]" \ No newline at end of file + if(self.alpha.real == 1.0 or self.beta.real == 1.0): + return f"|{int(self.beta.real)}>" + return f"[(\u03B1:{self.alpha})|0> {spin_str} (\u03B2:{self.beta})|1>]" \ No newline at end of file From 63746c39b97752736135f9eab63ad69fa7e24535 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 15:14:18 +0000 Subject: [PATCH 07/34] Fix functionCallExpression now using termList --- src/grammar_frontend/expression.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/grammar_frontend/expression.py b/src/grammar_frontend/expression.py index f3ba6a8..42bec33 100644 --- a/src/grammar_frontend/expression.py +++ b/src/grammar_frontend/expression.py @@ -29,8 +29,8 @@ def visitArrayExpression(self, ctx:qutes_parser.ArrayExpressionContext): def visitFunctionCallExpression(self, ctx:qutes_parser.FunctionCallExpressionContext): function_name = self.visit(ctx.functionName()) function_params:list[Symbol] = [] - if(ctx.functionCallParams()): - function_params = self.visit(ctx.functionCallParams()) + if(ctx.termList()): + function_params = self.visit(ctx.termList()) result:Symbol = self.__visitFunctionCall(function_name, function_params, ctx.start.tokenIndex) #TODO: staff commented for make return value work for quantum variable, do some tests to assure the behaviour is correct # function_symbol = self.variables_handler.get_function_symbol(function_name, ctx.start.tokenIndex, function_params) From 54cadc0b38ff625986c7428a7ec6cf18a117448b Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 15:14:42 +0000 Subject: [PATCH 08/34] Handled block size in shift operations --- src/grammar_frontend/operation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index 8197dd9..e8b7fbc 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -83,7 +83,7 @@ def __visit_binary_operator(self, ctx:qutes_parser.SumOperatorContext | qutes_pa if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): if(second_term_symbol and not QutesDataType.is_quantum_type(second_term_symbol.symbol_declaration_static_type)): from quantum_circuit.qutes_gates import QutesGates - self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.left_rot(len(first_term_symbol.quantum_register), second_term_value, 1), [first_term_symbol.quantum_register]) #TODO: handle block size + self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.left_rot(len(first_term_symbol.quantum_register), second_term_value, first_term_symbol.value.get_default_size_in_qubit()), [first_term_symbol.quantum_register]) result = first_term_symbol else: raise NotImplementedError("Left shift operator doesn't support second term to be a quantum variable.") @@ -93,7 +93,7 @@ def __visit_binary_operator(self, ctx:qutes_parser.SumOperatorContext | qutes_pa if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): if(second_term_symbol and not QutesDataType.is_quantum_type(second_term_symbol.symbol_declaration_static_type)): from quantum_circuit.qutes_gates import QutesGates - self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.right_rot(len(first_term_symbol.quantum_register), second_term_value, 1), [first_term_symbol.quantum_register]) #TODO: handle block size + self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.right_rot(len(first_term_symbol.quantum_register), second_term_value, first_term_symbol.value.get_default_size_in_qubit()), [first_term_symbol.quantum_register]) result = first_term_symbol else: raise NotImplementedError("Right shift operator doesn't support second term to be a quantum variable.") @@ -192,10 +192,10 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p if(first_term_symbol.symbol_declaration_static_type == QutesDataType.qustring): index = 0 string_value = "" - while index < first_term_symbol.value.number_of_chars * Qustring.default_size_in_qubit: - bin_char = bytes_str[index:Qustring.default_size_in_qubit + index] + while index < first_term_symbol.value.number_of_chars * Qustring.get_default_size_in_qubit(): + bin_char = bytes_str[index:Qustring.get_default_size_in_qubit() + index] string_value = string_value + Qustring.get_char_from_int(int(bin_char, 2)) - index = index + Qustring.default_size_in_qubit + index = index + Qustring.get_default_size_in_qubit() else: new_value = int(bytes_str, 2) #TODO: handle the conversion from a string of binadry digits to the current quantum variable type @@ -267,7 +267,7 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): array_register = target_symbol.quantum_register block_size = 1 try: - block_size = target_symbol.value.default_size_in_qubit + block_size = target_symbol.value.get_default_size_in_qubit() except: pass array_size = int(len(target_symbol.quantum_register)/block_size) From cb49e11860b270efd3c930c2a6c80eeb2d19631d Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 15:15:53 +0000 Subject: [PATCH 09/34] Fix variable update when new_state is a literal --- src/symbols/variables_handler.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/symbols/variables_handler.py b/src/symbols/variables_handler.py index ac9d0fb..6261b63 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -11,15 +11,19 @@ def __init__(self, scope_handler : ScopeHandler, quantum_cirtcuit_handler : Quan self.quantum_cirtcuit_handler = quantum_cirtcuit_handler self.type_casting_handler = TypeCastingHandler(quantum_cirtcuit_handler) - def update_variable_state(self, variable_name : str, new_state) -> Symbol: - value_to_assign = self.get_value(new_state) + def update_variable_state(self, variable_name : str, new_state) -> Symbol: eligible_symbols_to_update = [symbol for symbol in self.scope_handler.current_symbols_scope.symbols if symbol.name == variable_name] if len(eligible_symbols_to_update) > 0: # In case multiple scopes declare a varialble with the same name we take the last one, that is the one from the nearest scope. symbol_index_in_scope = self.scope_handler.current_symbols_scope.symbols.index(eligible_symbols_to_update[-1]) symbol_to_update = self.scope_handler.current_symbols_scope.symbols[symbol_index_in_scope] - # check if the type of the varible match the type of the value we are trying to assign. + # If new_state is a literal, we create an anonymous symbol to handle only this case from now on. + if(not isinstance(new_state, Symbol)): + new_state:Symbol = self.declare_anonymous_variable(QutesDataType.type_of(new_state), new_state, symbol_to_update.ast_token_index) + value_to_assign = self.get_value(new_state) + + # check if the type of the variable match the type of the value we are trying to assign. value_to_assign_qutes_type = QutesDataType.type_of(value_to_assign) definition_qutes_type = symbol_to_update.symbol_declaration_static_type promoted_type = value_to_assign_qutes_type.promote_type(definition_qutes_type) @@ -44,14 +48,14 @@ def update_variable_state(self, variable_name : str, new_state) -> Symbol: #Handle quantum circuit update if(QutesDataType.is_quantum_type(symbol_to_update.symbol_declaration_static_type)): - if(isinstance(new_state, Symbol)): - if(new_state.is_anonymous): - symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.replace_quantum_register(variable_name, new_state.value) + if(new_state.is_anonymous): + symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.replace_quantum_register(variable_name, value_to_assign) + if(new_state.is_quantum()): self.quantum_cirtcuit_handler.delete_variable(new_state.name) else: - symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.assign_quantum_register_to_variable(variable_name, new_state.quantum_register) + pass #being classic it was not added to circuit handler and there is no need to delete it. else: - symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.replace_quantum_register(variable_name, symbol_to_update.value) + symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.assign_quantum_register_to_variable(variable_name, new_state.quantum_register) return symbol_to_update else: raise SyntaxError(f"No variable declared with name '{variable_name}'.") From 470f39637df13d741f702c458938f1504f81678f Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 15:16:26 +0000 Subject: [PATCH 10/34] Add user program name as prefix to generated circuit images --- src/qutes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qutes.py b/src/qutes.py index 6cb7ff2..73db791 100644 --- a/src/qutes.py +++ b/src/qutes.py @@ -1,6 +1,6 @@ """A compiler for Qutes Lang source file""" -import sys +import sys, os import argparse from antlr4 import FileStream, CommonTokenStream from anytree import RenderTree @@ -26,6 +26,7 @@ def main(argv): parser.add_argument('file_path', metavar='file_path', help='The file path of the Qutes source code.') args = parser.parse_args() + user_qutes_program_name = os.path.basename(args.file_path) input_stream = FileStream(args.file_path) lexer = QutesLexer(input_stream) lexer.removeErrorListeners() @@ -73,7 +74,7 @@ def main(argv): print() print("----Quantum Circuit----") circuit = quantum_circuit_handler.create_circuit() - quantum_circuit_handler.print_circuit(circuit, args.save_circuit_as_image, args.log_quantum_circuit) + quantum_circuit_handler.print_circuit(circuit, args.save_circuit_as_image, args.log_quantum_circuit, user_qutes_program_name) quantum_circuit_handler.run_circuit(circuit, args.number_of_iterations, print_count=True) print() From 5a7ee7474e557176879a99162466f2a96eea91fe Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 15:17:53 +0000 Subject: [PATCH 11/34] Removed some done TODOs, fix some field usage in quantum types that now are accessed through methods --- qutes-vscode/grammar_tests.qut | 2 +- specification/grammar/grammar_tests.qut | 51 +++++-------------- .../quantum_circuit_handler.py | 8 +-- src/symbols/types/quint.py | 8 +-- src/symbols/types/qustring.py | 8 +-- src/symbols/types/qutes_data_type.py | 8 +-- src/tests/test_grammar.py | 2 +- 7 files changed, 33 insertions(+), 54 deletions(-) diff --git a/qutes-vscode/grammar_tests.qut b/qutes-vscode/grammar_tests.qut index 0d58425..6b37499 100644 --- a/qutes-vscode/grammar_tests.qut +++ b/qutes-vscode/grammar_tests.qut @@ -104,7 +104,7 @@ bool A (int c = 10){ bool a = false; return a; - print a; //TODO: gray out unreachable code + print a; } bool z = A(); diff --git a/specification/grammar/grammar_tests.qut b/specification/grammar/grammar_tests.qut index dfd39b1..b0b45b3 100644 --- a/specification/grammar/grammar_tests.qut +++ b/specification/grammar/grammar_tests.qut @@ -1,6 +1,6 @@ //basic boolean /*{ - //a = 10; //TODO: this should not be possible if 'a' not declared before usage. + //a = 10; //'a' declared before usage. bool a = true; bool b = FALSE; bool c = 1; @@ -11,8 +11,6 @@ /*{ int a=2+3; int i=1; - int x=0xa1;//TODO:handle - int h=0b01;//TODO:handle a; i=i+i; //2+"a"; //this gives an error and that it's as intended, it's how the lower level language handle this kind of operation between two types. @@ -60,7 +58,7 @@ int i=0; qubit qu = 0q; quint num = 1q; - //quint num = 10q; //TODO: fix circuit register size + //quint num = 10q; //print num; while (i<3){ i=i+1; @@ -70,7 +68,7 @@ // print num; int number = num; bool test = qu; - //if(num > 0){ // TODO: implement operator on quntum types + //if(num > 0){ print number; if(number > 0){ print "positive"; @@ -91,7 +89,7 @@ qubit ad = 0q; bool bo = true; - // qubit qbo = bo; //TODO: handle + // qubit qbo = bo; // qubit ae = 1q; // qubit bd = -0q; @@ -106,7 +104,7 @@ pauliz f; hadamard g; f + g; - // qubit hx = f + g; //TODO: handle assignment after expression + qubit hx = f + g; }*/ //quints tests @@ -126,13 +124,13 @@ //quint c = 10q; //quint d = 4q; //quint re = c + d; - //c + d + ax; //TODO: handle multiple quantum variable sum + //c + d + ax; //quint aa = [0q, 0q, 1q]; //quint representing the number 1 //quint bb = [[0, 1]q, 0q, 1q]; //quint with a superposition state where the most significant bit can be 0(50%) or 1(50%) //quint cc = [0.7,0.3q, 0q, 1q]; //quint with a superposition state where the most significant bit can be 0(70%) or 1(30%) //quint dd = [1, 3]q; //quint with a superposition state that can be both 1(50%) or 3(50%) - //quint d = -12q; //TODO: handle negative numbers (two's complement?) + //quint d = -12q; }*/ //measures tests @@ -149,7 +147,7 @@ //measure re; }*/ -//Circuit scope tests //TODO: handle quantum circuit and variable scopes +//Circuit scope tests /*{ //This two blocks can be two different circuits. // { @@ -190,10 +188,9 @@ // qubit b = [1]q; // quint x = a + b; // print x; - // int classical = x; //TODO: this triggers two measures + // int classical = x; // print classical; - // //TODO: this prints too many times because a measure gate it's permanently added to the circuit // // measure x; // // print x; // } @@ -208,23 +205,19 @@ // { // qubit a = [true]q; // qubit b = [true]q; - // int classical = a + 1; //TODO: handle operation between different types + // int classical = a + 1; // } // { // int a = 12; // qubit b = [true]q; - // //TODO: 'a' should be casted to quint. - // //We can measure 'b' and then sum classically to 'a' but that would not be a smart choice because 'c' cannot take advantage from the quantum state of 'b' // quint c = a + b; // } // { // quint a = 12; - // //TODO: this should be handle as an aliasing of 'b' -> 'a' - // //or should be handle as a correlation between 'a' and 'b' with cnot(s)? // quint b = a; - // qubit c = a; //TODO: downcast? + // qubit c = a; // } }*/ @@ -257,7 +250,7 @@ //Functions tests II /*{ - // bool A (int c = 10, bool aa){ //TODO: right now everything should has a default value, so we can handle params with no default value after those with default values, but we should think about it because this could be problematic. + // bool A (int c = 10, bool aa){ // bool a = true; // print a; // print c; @@ -276,7 +269,8 @@ B(aa); } } - //print A(); //TODO: invali, A() is expression while print works on term. + //print A(); + //print A; }*/ //Functions tests III with quantum types @@ -340,24 +334,8 @@ //Grover II /*{ - //TODO: in the current implementation the parser counts for each bit the times it's equal to 1, - // but this means we could have a 5 from measuring 'a' below. - // there is a way of initialize the qubits so that they cannot reach unwanted values? //quint a = [1,4,6]q; - //TODO: we need to implement arrays, because we cannot assume to execute a query on a quint/qubit in superposition. - // in the case of string (but the same is true for quint) "abaa" is actually an array of quchar, - // we need to search for a char in this array, - // while currently we are just checking that the qustring is equal to the pattern we provide to the search operartion. - // - // seeing that a qustring is already some sort of array, we can use the current implementation of the search, - // we just need to execute the search in parallel upon all chars in qustring. - // The same approch could be used for quint. - // - // In the future, we could handle the substring matching procedure, - // so that we can choose to search for a single element in the sequence or - // or a sequence in the sequence. - //quint a = [[0,1]q, [0,1]q, [0,1]q, [0,1]q]; //search 4 in a; @@ -366,7 +344,6 @@ qustring a = "ab"; search "a" in a; - //TODO: even number of solutions cause a fail, we need to add ancillas to avoid this. // qustring a = "abb"; // search "b" in a; }*/ diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index ae7a183..3fcac0f 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -40,7 +40,7 @@ def delete_variable(self, variable_name : str) -> None: if(register not in self._varname_to_register.values()): self._classic_registers.remove(register) - def declare_quantum_register(self, variable_name : str, quantum_variable : any) -> QuantumRegister: + def declare_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring) -> QuantumRegister: new_register = None new_register = QuantumRegister(quantum_variable.size, variable_name) @@ -54,12 +54,12 @@ def declare_quantum_register(self, variable_name : str, quantum_variable : any) # TODO: this should be a correlation operation, or a measure and then update. # We cannot rely on quantum_variable.get_quantum_state() - def replace_quantum_register(self, variable_name : str, quantum_variable : any) -> QuantumRegister: + def replace_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring) -> QuantumRegister: register_to_update = self._varname_to_register[variable_name] if(register_to_update is None): raise SystemError("Error trying to update an undeclared quantum register") - if(isinstance(quantum_variable, Qubit) or isinstance(quantum_variable, Quint) or isinstance(quantum_variable, Qustring)): + if(QutesDataType.is_quantum_type(QutesDataType.type_of(quantum_variable))): #TODO-CRITICAL: this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value and changing the name from update to replace. #Delete old quantum register and reference del self._registers_states[register_to_update] @@ -68,6 +68,8 @@ def replace_quantum_register(self, variable_name : str, quantum_variable : any) register_to_update = self._varname_to_register[variable_name] = QuantumRegister(quantum_variable.size, variable_name) self._quantum_registers.append(register_to_update) self._registers_states[register_to_update] = quantum_variable.get_quantum_state() + else: + raise SystemError("Error trying to update a quantum register with an unsupported type") return register_to_update diff --git a/src/symbols/types/quint.py b/src/symbols/types/quint.py index af3feca..14f85d2 100644 --- a/src/symbols/types/quint.py +++ b/src/symbols/types/quint.py @@ -62,13 +62,13 @@ def init_from_integer(literal : int | bool, initial_size:int = -1, init_in_super if(initial_size != -1 and (len(temp_state) % initial_size != 0)): to_add = initial_size - len(temp_state) % initial_size if(init_in_superposition): - temp_state.extend(Quint.default_superposition_value * to_add) + temp_state.extend(Quint.get_default_superposition_value() * to_add) else: - temp_state.extend(Quint.default_value * to_add) + temp_state.extend(Quint.get_default_value() * to_add) return Quint(temp_state) def init_from_size(number_of_bits : int) -> 'Quint': - return Quint(Quint.default_value*number_of_bits) + return Quint(Quint.get_default_value()*number_of_bits) def fromValue(var_value : any) -> 'Quint': try: @@ -98,7 +98,7 @@ def get_quantum_state(self) -> list[complex] : def update_size_with_padding(self, new_size : int) -> 'Quint': #TODO: qubit state is not reliable, we should add the qubit needed to expend the quint directly into the circuit. - self.qubit_state = (Quint.default_value*(new_size - self.size) + self.qubit_state) if self.size <= new_size else self.qubit_state[:new_size-1] + self.qubit_state = (Quint.get_default_value*(new_size - self.size) + self.qubit_state) if self.size <= new_size else self.qubit_state[:new_size-1] self.size = len(self.qubit_state) return self diff --git a/src/symbols/types/qustring.py b/src/symbols/types/qustring.py index 50ed683..93d5375 100644 --- a/src/symbols/types/qustring.py +++ b/src/symbols/types/qustring.py @@ -15,7 +15,7 @@ def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): super().__init__() self.qubit_state:list[Qubit] = qubits self.size:int = len(self.qubit_state) - self.number_of_chars:int = int(self.size / Qustring.default_size_in_qubit) + self.number_of_chars:int = int(self.size / Qustring.get_default_size_in_qubit()) def get_default_value(): return [Qubit(complex(1),complex(0))] * Qubit.get_default_size_in_qubit() @@ -24,7 +24,7 @@ def get_default_superposition_value(): return [Qubit(complex(0.5),complex(0.5))] * Qubit.get_default_size_in_qubit() def get_default_size_in_qubit(): - return math.ceil(math.log2(len(Qubit.allowed_chars))) + return math.ceil(math.log2(len(Qustring.allowed_chars))) def get_char_from_int(int_value:int): if(int_value > len(Qustring.allowed_chars)): @@ -46,9 +46,9 @@ def init_from_string(literal : str) -> 'Qustring': for char in literal: if(char == Qustring.superposition_char): - qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.default_size_in_qubit, True) + qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.get_default_size_in_qubit(), True) else: - qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.default_size_in_qubit) + qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.get_default_size_in_qubit()) qubits.extend(qubyte.qubit_state) return Qustring(qubits) diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index e216246..f1e8508 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -190,13 +190,13 @@ def get_size_in_qubit(var_type : 'QutesDataType'): case QutesDataType.qubit: return 1 case QutesDataType.int: - return Quint.default_size_in_qubit + return Quint.get_default_size_in_qubit() case QutesDataType.quint: - return Quint.default_size_in_qubit + return Quint.get_default_size_in_qubit() case QutesDataType.string: - return Qustring.default_size_in_qubit + return Qustring.get_default_size_in_qubit() case QutesDataType.qustring: - return Qustring.default_size_in_qubit + return Qustring.get_default_size_in_qubit() case QutesDataType.void: return 0 case QutesDataType.float: diff --git a/src/tests/test_grammar.py b/src/tests/test_grammar.py index fa44358..cb0c273 100644 --- a/src/tests/test_grammar.py +++ b/src/tests/test_grammar.py @@ -77,7 +77,7 @@ def test_classic_type_declaration_succeed(self): ("bool", "0", False), ("bool", "TRUE", True), ("bool", "1", True), - ("bool", "1q", True), #TODO: handle, the quantum var should be declared even when anonymous, so we can measure and assign the value to bool. + ("bool", "1q", True), ("bool", "0q", False), ("int", "10", 10), ("int", "9", 9), From 7fbff5ea4e7e1d812def2dfa7dac2916364d816e Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 16:16:41 +0000 Subject: [PATCH 12/34] Fix quantum types get_unit_size_in_qubit method --- src/grammar_frontend/operation.py | 13 +++++++------ src/symbols/types/qustring.py | 24 ++++++++++++------------ src/symbols/types/qutes_data_type.py | 2 +- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index e8b7fbc..738fd85 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -83,7 +83,7 @@ def __visit_binary_operator(self, ctx:qutes_parser.SumOperatorContext | qutes_pa if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): if(second_term_symbol and not QutesDataType.is_quantum_type(second_term_symbol.symbol_declaration_static_type)): from quantum_circuit.qutes_gates import QutesGates - self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.left_rot(len(first_term_symbol.quantum_register), second_term_value, first_term_symbol.value.get_default_size_in_qubit()), [first_term_symbol.quantum_register]) + self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.left_rot(len(first_term_symbol.quantum_register), second_term_value, first_term_symbol.casted_static_type.get_unit_size_in_qubit()), [first_term_symbol.quantum_register]) result = first_term_symbol else: raise NotImplementedError("Left shift operator doesn't support second term to be a quantum variable.") @@ -93,7 +93,7 @@ def __visit_binary_operator(self, ctx:qutes_parser.SumOperatorContext | qutes_pa if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): if(second_term_symbol and not QutesDataType.is_quantum_type(second_term_symbol.symbol_declaration_static_type)): from quantum_circuit.qutes_gates import QutesGates - self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.right_rot(len(first_term_symbol.quantum_register), second_term_value, first_term_symbol.value.get_default_size_in_qubit()), [first_term_symbol.quantum_register]) + self.quantum_circuit_handler.push_compose_circuit_operation(QutesGates.right_rot(len(first_term_symbol.quantum_register), second_term_value, first_term_symbol.casted_static_type.get_unit_size_in_qubit()), [first_term_symbol.quantum_register]) result = first_term_symbol else: raise NotImplementedError("Right shift operator doesn't support second term to be a quantum variable.") @@ -187,15 +187,16 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p if(ctx.PRINT()): if(first_term_symbol): if(QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): + #TODO: we don't use any of this computed values, why? classical_register = self.quantum_circuit_handler.run_and_measure([first_term_symbol.quantum_register]) bytes_str = [reg.measured_values[0] for reg in classical_register if first_term_symbol.quantum_register.name in reg.name][0] if(first_term_symbol.symbol_declaration_static_type == QutesDataType.qustring): index = 0 string_value = "" - while index < first_term_symbol.value.number_of_chars * Qustring.get_default_size_in_qubit(): - bin_char = bytes_str[index:Qustring.get_default_size_in_qubit() + index] + while index < first_term_symbol.value.number_of_chars * first_term_symbol.symbol_declaration_static_type.get_unit_size_in_qubit(): + bin_char = bytes_str[index:first_term_symbol.symbol_declaration_static_type.get_unit_size_in_qubit() + index] string_value = string_value + Qustring.get_char_from_int(int(bin_char, 2)) - index = index + Qustring.get_default_size_in_qubit() + index = index + first_term_symbol.symbol_declaration_static_type.get_unit_size_in_qubit() else: new_value = int(bytes_str, 2) #TODO: handle the conversion from a string of binadry digits to the current quantum variable type @@ -267,7 +268,7 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): array_register = target_symbol.quantum_register block_size = 1 try: - block_size = target_symbol.value.get_default_size_in_qubit() + block_size = target_symbol.symbol_declaration_static_type.get_unit_size_in_qubit() except: pass array_size = int(len(target_symbol.quantum_register)/block_size) diff --git a/src/symbols/types/qustring.py b/src/symbols/types/qustring.py index 93d5375..544a9ce 100644 --- a/src/symbols/types/qustring.py +++ b/src/symbols/types/qustring.py @@ -5,11 +5,11 @@ class Qustring(QuantumType['Qustring']): # note: chr and ord, parse int and char in ASCII for char of size 7 bits - # allowed_chars = ['a', 'b', 'c', 'd', superposition_char, not_valid_char] - # allowed_chars = ['0', '1', superposition_char, not_valid_char] - superposition_char = '*' - not_valid_char = 'X' - allowed_chars = ['0', '1'] + # allowed_chars = ['a', 'b', 'c', 'd', superposition_char, __not_valid_char] + # allowed_chars = ['0', '1', superposition_char, __not_valid_char] + __superposition_char = '*' + __not_valid_char = 'X' + __allowed_chars = ['0', '1'] def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): super().__init__() @@ -24,18 +24,18 @@ def get_default_superposition_value(): return [Qubit(complex(0.5),complex(0.5))] * Qubit.get_default_size_in_qubit() def get_default_size_in_qubit(): - return math.ceil(math.log2(len(Qustring.allowed_chars))) + return math.ceil(math.log2(len(Qustring.__allowed_chars))) def get_char_from_int(int_value:int): - if(int_value > len(Qustring.allowed_chars)): - return Qustring.allowed_chars[-1] - return Qustring.allowed_chars[int_value] + if(int_value > len(Qustring.__allowed_chars)): + return Qustring.__allowed_chars[-1] + return Qustring.__allowed_chars[int_value] def get_int_from_char(char_value:str): try: - return Qustring.allowed_chars.index(char_value) + return Qustring.__allowed_chars.index(char_value) except: - return len(Qustring.allowed_chars)-1 + return len(Qustring.__allowed_chars)-1 def init_from_string(literal : str) -> 'Qustring': qubits = [] @@ -45,7 +45,7 @@ def init_from_string(literal : str) -> 'Qustring': literal = literal.removeprefix('"') for char in literal: - if(char == Qustring.superposition_char): + if(char == Qustring.__superposition_char): qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.get_default_size_in_qubit(), True) else: qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.get_default_size_in_qubit()) diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index f1e8508..0f31774 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -183,7 +183,7 @@ def get_default_value(var_type : 'QutesDataType'): case _: return None - def get_size_in_qubit(var_type : 'QutesDataType'): + def get_unit_size_in_qubit(var_type : 'QutesDataType'): match var_type: case QutesDataType.bool: return 1 From b265959cdcf7941e6120be8293035d76fe5144ec Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 13 Jul 2024 16:26:22 +0000 Subject: [PATCH 13/34] Moved TypeCastingHandler to own file --- src/symbols/types/__init__.py | 3 +- src/symbols/types/qutes_data_type.py | 99 +---------------------- src/symbols/types/type_casting_handler.py | 99 +++++++++++++++++++++++ src/symbols/variables_handler.py | 3 +- 4 files changed, 106 insertions(+), 98 deletions(-) create mode 100644 src/symbols/types/type_casting_handler.py diff --git a/src/symbols/types/__init__.py b/src/symbols/types/__init__.py index f81a2df..4059240 100644 --- a/src/symbols/types/__init__.py +++ b/src/symbols/types/__init__.py @@ -4,4 +4,5 @@ from symbols.types.qubit import Qubit from symbols.types.quint import Quint from symbols.types.qustring import Qustring -from symbols.types.qutes_data_type import QutesDataType \ No newline at end of file +from symbols.types.qutes_data_type import QutesDataType +from symbols.types.type_casting_handler import TypeCastingHandler \ No newline at end of file diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index 0f31774..a0ad74d 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -205,108 +205,15 @@ def get_unit_size_in_qubit(var_type : 'QutesDataType'): return 1 def promote_type(self : 'QutesDataType', to_type : 'QutesDataType') -> 'QutesDataType': + from symbols.types.type_casting_handler import TypeCastingHandler if(self in TypeCastingHandler.type_promotable_to[to_type]): return to_type else: return QutesDataType.undefined def down_cast_type(self : 'QutesDataType', to_type : 'QutesDataType') -> 'QutesDataType': + from symbols.types.type_casting_handler import TypeCastingHandler if(self in TypeCastingHandler.type_down_castable_to[to_type]): return to_type else: - return QutesDataType.undefined - - -class TypeCastingHandler(): - def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): - self.quantum_cirtcuit_handler = quantum_cirtcuit_handler - - type_promotable_to : dict[Enum, list[QutesDataType]] = { - #TODO: handle nested casting, like (quint a = true) bool->qubit->quint - #..to this types <- this types can be converted to.. - QutesDataType.bool: [QutesDataType.bool], - QutesDataType.int: [QutesDataType.int, QutesDataType.bool], - QutesDataType.float: [QutesDataType.float, QutesDataType.int, QutesDataType.bool], - QutesDataType.string: [QutesDataType.string, QutesDataType.float, QutesDataType.int, QutesDataType.bool], - QutesDataType.qubit: [QutesDataType.qubit, QutesDataType.string, QutesDataType.bool], - QutesDataType.quint: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], - QutesDataType.qustring: [QutesDataType.qustring, QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], - QutesDataType.void: [], - QutesDataType.bool_array: [], - QutesDataType.int_array: [], - QutesDataType.float_array: [], - QutesDataType.string_array: [], - QutesDataType.qubit_array: [], - QutesDataType.quint_array: [], - QutesDataType.qustring_array: [], - } - type_down_castable_to : dict[Enum, list[QutesDataType]] = { - #..to this types <- this types can be converted(loosing information) to.. - QutesDataType.bool: [QutesDataType.qubit, QutesDataType.bool], - QutesDataType.int: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.int], - QutesDataType.float: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.float, QutesDataType.int], - QutesDataType.string: [QutesDataType.qustring, QutesDataType.string], - QutesDataType.qubit: [QutesDataType.qubit], - QutesDataType.quint: [QutesDataType.quint], - QutesDataType.qustring: [QutesDataType.qustring], - QutesDataType.void: [], - QutesDataType.bool_array: [], - QutesDataType.int_array: [], - QutesDataType.float_array: [], - QutesDataType.string_array: [], - QutesDataType.qubit_array: [], - QutesDataType.quint_array: [], - QutesDataType.qustring_array: [], - } - - def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: - match to_type: - case QutesDataType.bool: - return bool(int(var_value)) - case QutesDataType.int: - return int(var_value) - case QutesDataType.float: - return float(var_value) - case QutesDataType.string: - return str(var_value) - case QutesDataType.qubit: - return Qubit.fromValue(var_value) - case QutesDataType.quint: - return Quint.fromValue(var_value) - case QutesDataType.qustring: - return Qustring.fromValue(var_value) - case _: - return QutesDataType.undefined - - def down_cast_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: - from symbols import Symbol - from_type_value = None - if QutesDataType.is_quantum_type(from_type): - if(isinstance(symbol_or_literal, Symbol) and symbol_or_literal.is_anonymous): - from_type_value = symbol_or_literal.value.to_classical_type() - else: - from_type_value, _ = self.quantum_cirtcuit_handler.get_run_and_measure_result_for_quantum_var(symbol_or_literal.quantum_register) - - if from_type_value == None and isinstance(symbol_or_literal, Symbol): - from_type_value = symbol_or_literal.value.to_classical_type() - - if(from_type_value == None): - from_type_value = var_value - - match to_type: - case QutesDataType.bool: - return bool(int(from_type_value)) - case QutesDataType.int: - return int(from_type_value) - case QutesDataType.float: - return float(from_type_value) - case QutesDataType.string: - return str(from_type_value) - case QutesDataType.qubit: - return Qubit.fromValue(var_value) - case QutesDataType.quint: - return Quint.fromValue(var_value) - case QutesDataType.qustring: - return Qustring.fromValue(var_value) - case _: - return QutesDataType.undefined \ No newline at end of file + return QutesDataType.undefined \ No newline at end of file diff --git a/src/symbols/types/type_casting_handler.py b/src/symbols/types/type_casting_handler.py new file mode 100644 index 0000000..64678dd --- /dev/null +++ b/src/symbols/types/type_casting_handler.py @@ -0,0 +1,99 @@ +from symbols.types.qubit import Qubit +from symbols.types.quint import Quint +from symbols.types.qustring import Qustring +from symbols.types.qutes_data_type import QutesDataType +from enum import Enum + +class TypeCastingHandler(): + def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): + self.quantum_cirtcuit_handler = quantum_cirtcuit_handler + + type_promotable_to : dict[Enum, list[QutesDataType]] = { + #TODO: handle nested casting, like (quint a = true) bool->qubit->quint + #..to this types <- this types can be converted to.. + QutesDataType.bool: [QutesDataType.bool], + QutesDataType.int: [QutesDataType.int, QutesDataType.bool], + QutesDataType.float: [QutesDataType.float, QutesDataType.int, QutesDataType.bool], + QutesDataType.string: [QutesDataType.string, QutesDataType.float, QutesDataType.int, QutesDataType.bool], + QutesDataType.qubit: [QutesDataType.qubit, QutesDataType.string, QutesDataType.bool], + QutesDataType.quint: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], + QutesDataType.qustring: [QutesDataType.qustring, QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], + QutesDataType.void: [], + QutesDataType.bool_array: [], + QutesDataType.int_array: [], + QutesDataType.float_array: [], + QutesDataType.string_array: [], + QutesDataType.qubit_array: [], + QutesDataType.quint_array: [], + QutesDataType.qustring_array: [], + } + type_down_castable_to : dict[Enum, list[QutesDataType]] = { + #..to this types <- this types can be converted(loosing information) to.. + QutesDataType.bool: [QutesDataType.qubit, QutesDataType.bool], + QutesDataType.int: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.int], + QutesDataType.float: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.float, QutesDataType.int], + QutesDataType.string: [QutesDataType.qustring, QutesDataType.string], + QutesDataType.qubit: [QutesDataType.qubit], + QutesDataType.quint: [QutesDataType.quint], + QutesDataType.qustring: [QutesDataType.qustring], + QutesDataType.void: [], + QutesDataType.bool_array: [], + QutesDataType.int_array: [], + QutesDataType.float_array: [], + QutesDataType.string_array: [], + QutesDataType.qubit_array: [], + QutesDataType.quint_array: [], + QutesDataType.qustring_array: [], + } + + def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: + match to_type: + case QutesDataType.bool: + return bool(int(var_value)) + case QutesDataType.int: + return int(var_value) + case QutesDataType.float: + return float(var_value) + case QutesDataType.string: + return str(var_value) + case QutesDataType.qubit: + return Qubit.fromValue(var_value) + case QutesDataType.quint: + return Quint.fromValue(var_value) + case QutesDataType.qustring: + return Qustring.fromValue(var_value) + case _: + return QutesDataType.undefined + + def down_cast_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: + from symbols import Symbol + from_type_value = None + if QutesDataType.is_quantum_type(from_type): + if(isinstance(symbol_or_literal, Symbol) and symbol_or_literal.is_anonymous): + from_type_value = symbol_or_literal.value.to_classical_type() + else: + from_type_value, _ = self.quantum_cirtcuit_handler.get_run_and_measure_result_for_quantum_var(symbol_or_literal.quantum_register) + + if from_type_value == None and isinstance(symbol_or_literal, Symbol): + from_type_value = symbol_or_literal.value.to_classical_type() + + if(from_type_value == None): + from_type_value = var_value + + match to_type: + case QutesDataType.bool: + return bool(int(from_type_value)) + case QutesDataType.int: + return int(from_type_value) + case QutesDataType.float: + return float(from_type_value) + case QutesDataType.string: + return str(from_type_value) + case QutesDataType.qubit: + return Qubit.fromValue(var_value) + case QutesDataType.quint: + return Quint.fromValue(var_value) + case QutesDataType.qustring: + return Qustring.fromValue(var_value) + case _: + return QutesDataType.undefined \ No newline at end of file diff --git a/src/symbols/variables_handler.py b/src/symbols/variables_handler.py index 6261b63..519bb8c 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -1,5 +1,6 @@ from uuid import uuid4 -from symbols.types.qutes_data_type import QutesDataType, TypeCastingHandler +from symbols.types.type_casting_handler import TypeCastingHandler +from symbols.types.qutes_data_type import QutesDataType from symbols.scope_handler import ScopeHandler from symbols.symbol import Symbol, SymbolClass from quantum_circuit import QuantumCircuitHandler From 9470006997292de0dba72255b634296fb18341d9 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 17 Aug 2024 17:19:40 +0000 Subject: [PATCH 14/34] Fix quint and array literal ambiguity --- specification/grammar/qutes_lexer.g4 | 2 +- src/qutes_antlr/qutes_lexer.py | 256 +++++++++++++-------------- src/tests/test_grammar.py | 2 +- 3 files changed, 130 insertions(+), 130 deletions(-) diff --git a/specification/grammar/qutes_lexer.g4 b/specification/grammar/qutes_lexer.g4 index 3f13a04..7697304 100644 --- a/specification/grammar/qutes_lexer.g4 +++ b/specification/grammar/qutes_lexer.g4 @@ -136,7 +136,7 @@ QUBIT_LITERAL QUINT_LITERAL : QUBIT_LITERAL - | SQUARE_PARENTHESIS_OPEN QUBIT_LITERAL (COMMA (' ')* QUBIT_LITERAL)* SQUARE_PARENTHESIS_CLOSE + | SQUARE_PARENTHESIS_OPEN QUBIT_LITERAL (COMMA (' ')* QUBIT_LITERAL)* SQUARE_PARENTHESIS_CLOSE [q] | SQUARE_PARENTHESIS_OPEN INT_LITERAL (COMMA (' ')* INT_LITERAL)* SQUARE_PARENTHESIS_CLOSE [q] | MATH_SIGN? DIGIT+ [q] ; diff --git a/src/qutes_antlr/qutes_lexer.py b/src/qutes_antlr/qutes_lexer.py index a1650d4..9475ae9 100644 --- a/src/qutes_antlr/qutes_lexer.py +++ b/src/qutes_antlr/qutes_lexer.py @@ -10,7 +10,7 @@ def serializedATN(): return [ - 4,0,77,655,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, + 4,0,77,656,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, 2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2, 13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7, 19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2, @@ -57,107 +57,107 @@ def serializedATN(): 76,3,76,559,8,76,1,76,1,76,3,76,563,8,76,1,76,3,76,566,8,76,1,77, 1,77,1,77,1,77,1,77,5,77,573,8,77,10,77,12,77,576,9,77,1,77,1,77, 5,77,580,8,77,10,77,12,77,583,9,77,1,77,1,77,1,77,1,77,1,77,1,77, - 5,77,591,8,77,10,77,12,77,594,9,77,1,77,1,77,5,77,598,8,77,10,77, - 12,77,601,9,77,1,77,1,77,1,77,1,77,3,77,607,8,77,1,77,4,77,610,8, - 77,11,77,12,77,611,1,77,1,77,3,77,616,8,77,1,78,1,78,1,78,1,79,1, - 79,5,79,623,8,79,10,79,12,79,626,9,79,1,80,1,80,1,80,1,80,1,80,1, - 80,5,80,634,8,80,10,80,12,80,637,9,80,1,80,1,80,1,81,4,81,642,8, - 81,11,81,12,81,643,1,81,3,81,647,8,81,1,81,1,81,1,82,3,82,652,8, - 82,1,82,1,82,1,431,0,83,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9, - 19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20, - 41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31, - 63,32,65,33,67,34,69,35,71,36,73,37,75,38,77,39,79,40,81,41,83,42, - 85,43,87,44,89,45,91,46,93,47,95,48,97,49,99,50,101,51,103,52,105, - 53,107,54,109,55,111,56,113,57,115,58,117,59,119,60,121,61,123,62, - 125,63,127,64,129,65,131,0,133,0,135,0,137,0,139,0,141,0,143,66, - 145,67,147,68,149,69,151,70,153,71,155,72,157,73,159,74,161,75,163, - 76,165,77,1,0,33,2,0,73,73,105,105,2,0,78,78,110,110,2,0,84,84,116, - 116,2,0,66,66,98,98,2,0,79,79,111,111,2,0,76,76,108,108,2,0,83,83, - 115,115,2,0,82,82,114,114,2,0,71,71,103,103,2,0,81,81,113,113,2, - 0,85,85,117,117,2,0,70,70,102,102,2,0,65,65,97,97,2,0,86,86,118, - 118,2,0,68,68,100,100,2,0,69,69,101,101,2,0,89,89,121,121,2,0,87, - 87,119,119,2,0,80,80,112,112,2,0,90,90,122,122,2,0,77,77,109,109, - 2,0,67,67,99,99,2,0,88,88,120,120,2,0,72,72,104,104,2,0,10,10,13, - 13,1,0,48,57,2,0,43,43,45,45,2,0,65,70,97,102,1,0,48,49,3,0,65,90, - 95,95,97,122,4,0,48,57,65,90,95,95,97,122,2,0,34,34,92,92,3,0,9, - 10,13,13,32,32,692,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0, - 0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0, - 0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0, - 0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0, - 0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0, - 0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0, - 0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0, - 0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0, - 0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0, - 0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0, - 0,0,99,1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107,1, - 0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0, - 117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1,0, - 0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,143,1,0,0,0,0,145,1,0,0,0,0,147, - 1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0,155,1,0,0,0, - 0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,0,165,1, - 0,0,0,1,167,1,0,0,0,3,171,1,0,0,0,5,176,1,0,0,0,7,183,1,0,0,0,9, - 189,1,0,0,0,11,195,1,0,0,0,13,204,1,0,0,0,15,210,1,0,0,0,17,215, - 1,0,0,0,19,222,1,0,0,0,21,224,1,0,0,0,23,226,1,0,0,0,25,228,1,0, - 0,0,27,230,1,0,0,0,29,232,1,0,0,0,31,236,1,0,0,0,33,240,1,0,0,0, - 35,243,1,0,0,0,37,246,1,0,0,0,39,251,1,0,0,0,41,258,1,0,0,0,43,265, - 1,0,0,0,45,272,1,0,0,0,47,276,1,0,0,0,49,280,1,0,0,0,51,284,1,0, - 0,0,53,288,1,0,0,0,55,297,1,0,0,0,57,305,1,0,0,0,59,311,1,0,0,0, - 61,319,1,0,0,0,63,322,1,0,0,0,65,325,1,0,0,0,67,327,1,0,0,0,69,330, - 1,0,0,0,71,332,1,0,0,0,73,335,1,0,0,0,75,338,1,0,0,0,77,341,1,0, - 0,0,79,343,1,0,0,0,81,346,1,0,0,0,83,349,1,0,0,0,85,352,1,0,0,0, - 87,355,1,0,0,0,89,358,1,0,0,0,91,361,1,0,0,0,93,364,1,0,0,0,95,366, - 1,0,0,0,97,370,1,0,0,0,99,374,1,0,0,0,101,381,1,0,0,0,103,384,1, - 0,0,0,105,390,1,0,0,0,107,393,1,0,0,0,109,398,1,0,0,0,111,404,1, - 0,0,0,113,407,1,0,0,0,115,409,1,0,0,0,117,411,1,0,0,0,119,413,1, - 0,0,0,121,415,1,0,0,0,123,417,1,0,0,0,125,419,1,0,0,0,127,421,1, - 0,0,0,129,423,1,0,0,0,131,445,1,0,0,0,133,447,1,0,0,0,135,452,1, - 0,0,0,137,458,1,0,0,0,139,460,1,0,0,0,141,474,1,0,0,0,143,479,1, - 0,0,0,145,482,1,0,0,0,147,513,1,0,0,0,149,515,1,0,0,0,151,523,1, - 0,0,0,153,565,1,0,0,0,155,615,1,0,0,0,157,617,1,0,0,0,159,620,1, - 0,0,0,161,627,1,0,0,0,163,646,1,0,0,0,165,651,1,0,0,0,167,168,7, - 0,0,0,168,169,7,1,0,0,169,170,7,2,0,0,170,2,1,0,0,0,171,172,7,3, - 0,0,172,173,7,4,0,0,173,174,7,4,0,0,174,175,7,5,0,0,175,4,1,0,0, - 0,176,177,7,6,0,0,177,178,7,2,0,0,178,179,7,7,0,0,179,180,7,0,0, - 0,180,181,7,1,0,0,181,182,7,8,0,0,182,6,1,0,0,0,183,184,7,9,0,0, - 184,185,7,10,0,0,185,186,7,3,0,0,186,187,7,0,0,0,187,188,7,2,0,0, - 188,8,1,0,0,0,189,190,7,9,0,0,190,191,7,10,0,0,191,192,7,0,0,0,192, - 193,7,1,0,0,193,194,7,2,0,0,194,10,1,0,0,0,195,196,7,9,0,0,196,197, - 7,10,0,0,197,198,7,6,0,0,198,199,7,2,0,0,199,200,7,7,0,0,200,201, - 7,0,0,0,201,202,7,1,0,0,202,203,7,8,0,0,203,12,1,0,0,0,204,205,7, - 11,0,0,205,206,7,5,0,0,206,207,7,4,0,0,207,208,7,12,0,0,208,209, - 7,2,0,0,209,14,1,0,0,0,210,211,7,13,0,0,211,212,7,4,0,0,212,213, - 7,0,0,0,213,214,7,14,0,0,214,16,1,0,0,0,215,216,7,7,0,0,216,217, - 7,15,0,0,217,218,7,2,0,0,218,219,7,10,0,0,219,220,7,7,0,0,220,221, - 7,1,0,0,221,18,1,0,0,0,222,223,5,42,0,0,223,20,1,0,0,0,224,225,5, - 47,0,0,225,22,1,0,0,0,226,227,5,37,0,0,227,24,1,0,0,0,228,229,5, - 43,0,0,229,26,1,0,0,0,230,231,5,45,0,0,231,28,1,0,0,0,232,233,7, - 1,0,0,233,234,7,4,0,0,234,235,7,2,0,0,235,30,1,0,0,0,236,237,7,12, - 0,0,237,238,7,1,0,0,238,239,7,14,0,0,239,32,1,0,0,0,240,241,7,4, - 0,0,241,242,7,7,0,0,242,34,1,0,0,0,243,244,7,3,0,0,244,245,7,16, - 0,0,245,36,1,0,0,0,246,247,7,6,0,0,247,248,7,17,0,0,248,249,7,12, - 0,0,249,250,7,18,0,0,250,38,1,0,0,0,251,252,7,18,0,0,252,253,7,12, - 0,0,253,254,7,10,0,0,254,255,7,5,0,0,255,256,7,0,0,0,256,257,7,16, - 0,0,257,40,1,0,0,0,258,259,7,18,0,0,259,260,7,12,0,0,260,261,7,10, - 0,0,261,262,7,5,0,0,262,263,7,0,0,0,263,264,7,19,0,0,264,42,1,0, - 0,0,265,266,7,8,0,0,266,267,7,7,0,0,267,268,7,4,0,0,268,269,7,13, - 0,0,269,270,7,15,0,0,270,271,7,7,0,0,271,44,1,0,0,0,272,273,7,20, - 0,0,273,274,7,21,0,0,274,275,7,19,0,0,275,46,1,0,0,0,276,277,7,20, - 0,0,277,278,7,21,0,0,278,279,7,22,0,0,279,48,1,0,0,0,280,281,7,20, - 0,0,281,282,7,21,0,0,282,283,7,16,0,0,283,50,1,0,0,0,284,285,7,20, - 0,0,285,286,7,21,0,0,286,287,7,18,0,0,287,52,1,0,0,0,288,289,7,23, - 0,0,289,290,7,12,0,0,290,291,7,14,0,0,291,292,7,12,0,0,292,293,7, - 20,0,0,293,294,7,12,0,0,294,295,7,7,0,0,295,296,7,14,0,0,296,54, - 1,0,0,0,297,298,7,20,0,0,298,299,7,15,0,0,299,300,7,12,0,0,300,301, - 7,6,0,0,301,302,7,10,0,0,302,303,7,7,0,0,303,304,7,15,0,0,304,56, - 1,0,0,0,305,306,7,18,0,0,306,307,7,7,0,0,307,308,7,0,0,0,308,309, - 7,1,0,0,309,310,7,2,0,0,310,58,1,0,0,0,311,312,7,3,0,0,312,313,7, - 12,0,0,313,314,7,7,0,0,314,315,7,7,0,0,315,316,7,0,0,0,316,317,7, - 15,0,0,317,318,7,7,0,0,318,60,1,0,0,0,319,320,5,61,0,0,320,321,5, - 61,0,0,321,62,1,0,0,0,322,323,5,33,0,0,323,324,5,61,0,0,324,64,1, - 0,0,0,325,326,5,62,0,0,326,66,1,0,0,0,327,328,5,62,0,0,328,329,5, - 61,0,0,329,68,1,0,0,0,330,331,5,60,0,0,331,70,1,0,0,0,332,333,5, - 60,0,0,333,334,5,61,0,0,334,72,1,0,0,0,335,336,5,60,0,0,336,337, + 1,77,5,77,592,8,77,10,77,12,77,595,9,77,1,77,1,77,5,77,599,8,77, + 10,77,12,77,602,9,77,1,77,1,77,1,77,1,77,3,77,608,8,77,1,77,4,77, + 611,8,77,11,77,12,77,612,1,77,1,77,3,77,617,8,77,1,78,1,78,1,78, + 1,79,1,79,5,79,624,8,79,10,79,12,79,627,9,79,1,80,1,80,1,80,1,80, + 1,80,1,80,5,80,635,8,80,10,80,12,80,638,9,80,1,80,1,80,1,81,4,81, + 643,8,81,11,81,12,81,644,1,81,3,81,648,8,81,1,81,1,81,1,82,3,82, + 653,8,82,1,82,1,82,1,431,0,83,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8, + 17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19, + 39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30, + 61,31,63,32,65,33,67,34,69,35,71,36,73,37,75,38,77,39,79,40,81,41, + 83,42,85,43,87,44,89,45,91,46,93,47,95,48,97,49,99,50,101,51,103, + 52,105,53,107,54,109,55,111,56,113,57,115,58,117,59,119,60,121,61, + 123,62,125,63,127,64,129,65,131,0,133,0,135,0,137,0,139,0,141,0, + 143,66,145,67,147,68,149,69,151,70,153,71,155,72,157,73,159,74,161, + 75,163,76,165,77,1,0,33,2,0,73,73,105,105,2,0,78,78,110,110,2,0, + 84,84,116,116,2,0,66,66,98,98,2,0,79,79,111,111,2,0,76,76,108,108, + 2,0,83,83,115,115,2,0,82,82,114,114,2,0,71,71,103,103,2,0,81,81, + 113,113,2,0,85,85,117,117,2,0,70,70,102,102,2,0,65,65,97,97,2,0, + 86,86,118,118,2,0,68,68,100,100,2,0,69,69,101,101,2,0,89,89,121, + 121,2,0,87,87,119,119,2,0,80,80,112,112,2,0,90,90,122,122,2,0,77, + 77,109,109,2,0,67,67,99,99,2,0,88,88,120,120,2,0,72,72,104,104,2, + 0,10,10,13,13,1,0,48,57,2,0,43,43,45,45,2,0,65,70,97,102,1,0,48, + 49,3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,2,0,34,34, + 92,92,3,0,9,10,13,13,32,32,693,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0, + 0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0, + 0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0, + 0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0, + 0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0, + 0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0, + 0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0, + 0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0, + 0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0, + 0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0, + 0,97,1,0,0,0,0,99,1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0, + 0,0,0,107,1,0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115, + 1,0,0,0,0,117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0, + 0,125,1,0,0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,143,1,0,0,0,0,145,1, + 0,0,0,0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0, + 155,1,0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0, + 0,0,0,165,1,0,0,0,1,167,1,0,0,0,3,171,1,0,0,0,5,176,1,0,0,0,7,183, + 1,0,0,0,9,189,1,0,0,0,11,195,1,0,0,0,13,204,1,0,0,0,15,210,1,0,0, + 0,17,215,1,0,0,0,19,222,1,0,0,0,21,224,1,0,0,0,23,226,1,0,0,0,25, + 228,1,0,0,0,27,230,1,0,0,0,29,232,1,0,0,0,31,236,1,0,0,0,33,240, + 1,0,0,0,35,243,1,0,0,0,37,246,1,0,0,0,39,251,1,0,0,0,41,258,1,0, + 0,0,43,265,1,0,0,0,45,272,1,0,0,0,47,276,1,0,0,0,49,280,1,0,0,0, + 51,284,1,0,0,0,53,288,1,0,0,0,55,297,1,0,0,0,57,305,1,0,0,0,59,311, + 1,0,0,0,61,319,1,0,0,0,63,322,1,0,0,0,65,325,1,0,0,0,67,327,1,0, + 0,0,69,330,1,0,0,0,71,332,1,0,0,0,73,335,1,0,0,0,75,338,1,0,0,0, + 77,341,1,0,0,0,79,343,1,0,0,0,81,346,1,0,0,0,83,349,1,0,0,0,85,352, + 1,0,0,0,87,355,1,0,0,0,89,358,1,0,0,0,91,361,1,0,0,0,93,364,1,0, + 0,0,95,366,1,0,0,0,97,370,1,0,0,0,99,374,1,0,0,0,101,381,1,0,0,0, + 103,384,1,0,0,0,105,390,1,0,0,0,107,393,1,0,0,0,109,398,1,0,0,0, + 111,404,1,0,0,0,113,407,1,0,0,0,115,409,1,0,0,0,117,411,1,0,0,0, + 119,413,1,0,0,0,121,415,1,0,0,0,123,417,1,0,0,0,125,419,1,0,0,0, + 127,421,1,0,0,0,129,423,1,0,0,0,131,445,1,0,0,0,133,447,1,0,0,0, + 135,452,1,0,0,0,137,458,1,0,0,0,139,460,1,0,0,0,141,474,1,0,0,0, + 143,479,1,0,0,0,145,482,1,0,0,0,147,513,1,0,0,0,149,515,1,0,0,0, + 151,523,1,0,0,0,153,565,1,0,0,0,155,616,1,0,0,0,157,618,1,0,0,0, + 159,621,1,0,0,0,161,628,1,0,0,0,163,647,1,0,0,0,165,652,1,0,0,0, + 167,168,7,0,0,0,168,169,7,1,0,0,169,170,7,2,0,0,170,2,1,0,0,0,171, + 172,7,3,0,0,172,173,7,4,0,0,173,174,7,4,0,0,174,175,7,5,0,0,175, + 4,1,0,0,0,176,177,7,6,0,0,177,178,7,2,0,0,178,179,7,7,0,0,179,180, + 7,0,0,0,180,181,7,1,0,0,181,182,7,8,0,0,182,6,1,0,0,0,183,184,7, + 9,0,0,184,185,7,10,0,0,185,186,7,3,0,0,186,187,7,0,0,0,187,188,7, + 2,0,0,188,8,1,0,0,0,189,190,7,9,0,0,190,191,7,10,0,0,191,192,7,0, + 0,0,192,193,7,1,0,0,193,194,7,2,0,0,194,10,1,0,0,0,195,196,7,9,0, + 0,196,197,7,10,0,0,197,198,7,6,0,0,198,199,7,2,0,0,199,200,7,7,0, + 0,200,201,7,0,0,0,201,202,7,1,0,0,202,203,7,8,0,0,203,12,1,0,0,0, + 204,205,7,11,0,0,205,206,7,5,0,0,206,207,7,4,0,0,207,208,7,12,0, + 0,208,209,7,2,0,0,209,14,1,0,0,0,210,211,7,13,0,0,211,212,7,4,0, + 0,212,213,7,0,0,0,213,214,7,14,0,0,214,16,1,0,0,0,215,216,7,7,0, + 0,216,217,7,15,0,0,217,218,7,2,0,0,218,219,7,10,0,0,219,220,7,7, + 0,0,220,221,7,1,0,0,221,18,1,0,0,0,222,223,5,42,0,0,223,20,1,0,0, + 0,224,225,5,47,0,0,225,22,1,0,0,0,226,227,5,37,0,0,227,24,1,0,0, + 0,228,229,5,43,0,0,229,26,1,0,0,0,230,231,5,45,0,0,231,28,1,0,0, + 0,232,233,7,1,0,0,233,234,7,4,0,0,234,235,7,2,0,0,235,30,1,0,0,0, + 236,237,7,12,0,0,237,238,7,1,0,0,238,239,7,14,0,0,239,32,1,0,0,0, + 240,241,7,4,0,0,241,242,7,7,0,0,242,34,1,0,0,0,243,244,7,3,0,0,244, + 245,7,16,0,0,245,36,1,0,0,0,246,247,7,6,0,0,247,248,7,17,0,0,248, + 249,7,12,0,0,249,250,7,18,0,0,250,38,1,0,0,0,251,252,7,18,0,0,252, + 253,7,12,0,0,253,254,7,10,0,0,254,255,7,5,0,0,255,256,7,0,0,0,256, + 257,7,16,0,0,257,40,1,0,0,0,258,259,7,18,0,0,259,260,7,12,0,0,260, + 261,7,10,0,0,261,262,7,5,0,0,262,263,7,0,0,0,263,264,7,19,0,0,264, + 42,1,0,0,0,265,266,7,8,0,0,266,267,7,7,0,0,267,268,7,4,0,0,268,269, + 7,13,0,0,269,270,7,15,0,0,270,271,7,7,0,0,271,44,1,0,0,0,272,273, + 7,20,0,0,273,274,7,21,0,0,274,275,7,19,0,0,275,46,1,0,0,0,276,277, + 7,20,0,0,277,278,7,21,0,0,278,279,7,22,0,0,279,48,1,0,0,0,280,281, + 7,20,0,0,281,282,7,21,0,0,282,283,7,16,0,0,283,50,1,0,0,0,284,285, + 7,20,0,0,285,286,7,21,0,0,286,287,7,18,0,0,287,52,1,0,0,0,288,289, + 7,23,0,0,289,290,7,12,0,0,290,291,7,14,0,0,291,292,7,12,0,0,292, + 293,7,20,0,0,293,294,7,12,0,0,294,295,7,7,0,0,295,296,7,14,0,0,296, + 54,1,0,0,0,297,298,7,20,0,0,298,299,7,15,0,0,299,300,7,12,0,0,300, + 301,7,6,0,0,301,302,7,10,0,0,302,303,7,7,0,0,303,304,7,15,0,0,304, + 56,1,0,0,0,305,306,7,18,0,0,306,307,7,7,0,0,307,308,7,0,0,0,308, + 309,7,1,0,0,309,310,7,2,0,0,310,58,1,0,0,0,311,312,7,3,0,0,312,313, + 7,12,0,0,313,314,7,7,0,0,314,315,7,7,0,0,315,316,7,0,0,0,316,317, + 7,15,0,0,317,318,7,7,0,0,318,60,1,0,0,0,319,320,5,61,0,0,320,321, + 5,61,0,0,321,62,1,0,0,0,322,323,5,33,0,0,323,324,5,61,0,0,324,64, + 1,0,0,0,325,326,5,62,0,0,326,66,1,0,0,0,327,328,5,62,0,0,328,329, + 5,61,0,0,329,68,1,0,0,0,330,331,5,60,0,0,331,70,1,0,0,0,332,333, + 5,60,0,0,333,334,5,61,0,0,334,72,1,0,0,0,335,336,5,60,0,0,336,337, 5,60,0,0,337,74,1,0,0,0,338,339,5,62,0,0,339,340,5,62,0,0,340,76, 1,0,0,0,341,342,5,61,0,0,342,78,1,0,0,0,343,344,5,43,0,0,344,345, 5,43,0,0,345,80,1,0,0,0,346,347,5,45,0,0,347,348,5,45,0,0,348,82, @@ -223,36 +223,36 @@ def serializedATN(): 0,558,557,1,0,0,0,558,559,1,0,0,0,559,562,1,0,0,0,560,563,3,143, 71,0,561,563,2,48,49,0,562,560,1,0,0,0,562,561,1,0,0,0,563,564,1, 0,0,0,564,566,7,9,0,0,565,530,1,0,0,0,565,551,1,0,0,0,565,556,1, - 0,0,0,565,558,1,0,0,0,566,154,1,0,0,0,567,616,3,153,76,0,568,569, + 0,0,0,565,558,1,0,0,0,566,154,1,0,0,0,567,617,3,153,76,0,568,569, 3,121,60,0,569,581,3,153,76,0,570,574,3,129,64,0,571,573,5,32,0, 0,572,571,1,0,0,0,573,576,1,0,0,0,574,572,1,0,0,0,574,575,1,0,0, 0,575,577,1,0,0,0,576,574,1,0,0,0,577,578,3,153,76,0,578,580,1,0, 0,0,579,570,1,0,0,0,580,583,1,0,0,0,581,579,1,0,0,0,581,582,1,0, - 0,0,582,584,1,0,0,0,583,581,1,0,0,0,584,585,3,123,61,0,585,616,1, - 0,0,0,586,587,3,121,60,0,587,599,3,145,72,0,588,592,3,129,64,0,589, - 591,5,32,0,0,590,589,1,0,0,0,591,594,1,0,0,0,592,590,1,0,0,0,592, - 593,1,0,0,0,593,595,1,0,0,0,594,592,1,0,0,0,595,596,3,145,72,0,596, - 598,1,0,0,0,597,588,1,0,0,0,598,601,1,0,0,0,599,597,1,0,0,0,599, - 600,1,0,0,0,600,602,1,0,0,0,601,599,1,0,0,0,602,603,3,123,61,0,603, - 604,7,9,0,0,604,616,1,0,0,0,605,607,3,139,69,0,606,605,1,0,0,0,606, - 607,1,0,0,0,607,609,1,0,0,0,608,610,3,137,68,0,609,608,1,0,0,0,610, - 611,1,0,0,0,611,609,1,0,0,0,611,612,1,0,0,0,612,613,1,0,0,0,613, - 614,7,9,0,0,614,616,1,0,0,0,615,567,1,0,0,0,615,568,1,0,0,0,615, - 586,1,0,0,0,615,606,1,0,0,0,616,156,1,0,0,0,617,618,3,161,80,0,618, - 619,7,9,0,0,619,158,1,0,0,0,620,624,7,29,0,0,621,623,7,30,0,0,622, - 621,1,0,0,0,623,626,1,0,0,0,624,622,1,0,0,0,624,625,1,0,0,0,625, - 160,1,0,0,0,626,624,1,0,0,0,627,635,5,34,0,0,628,629,5,92,0,0,629, - 634,9,0,0,0,630,631,5,34,0,0,631,634,5,34,0,0,632,634,8,31,0,0,633, - 628,1,0,0,0,633,630,1,0,0,0,633,632,1,0,0,0,634,637,1,0,0,0,635, - 633,1,0,0,0,635,636,1,0,0,0,636,638,1,0,0,0,637,635,1,0,0,0,638, - 639,5,34,0,0,639,162,1,0,0,0,640,642,7,32,0,0,641,640,1,0,0,0,642, - 643,1,0,0,0,643,641,1,0,0,0,643,644,1,0,0,0,644,647,1,0,0,0,645, - 647,3,131,65,0,646,641,1,0,0,0,646,645,1,0,0,0,647,648,1,0,0,0,648, - 649,6,81,0,0,649,164,1,0,0,0,650,652,5,13,0,0,651,650,1,0,0,0,651, - 652,1,0,0,0,652,653,1,0,0,0,653,654,5,10,0,0,654,166,1,0,0,0,37, - 0,431,442,445,474,479,482,487,490,495,501,505,511,513,519,521,528, - 533,539,544,546,558,562,565,574,581,592,599,606,611,615,624,633, - 635,643,646,651,1,6,0,0 + 0,0,582,584,1,0,0,0,583,581,1,0,0,0,584,585,3,123,61,0,585,586,7, + 9,0,0,586,617,1,0,0,0,587,588,3,121,60,0,588,600,3,145,72,0,589, + 593,3,129,64,0,590,592,5,32,0,0,591,590,1,0,0,0,592,595,1,0,0,0, + 593,591,1,0,0,0,593,594,1,0,0,0,594,596,1,0,0,0,595,593,1,0,0,0, + 596,597,3,145,72,0,597,599,1,0,0,0,598,589,1,0,0,0,599,602,1,0,0, + 0,600,598,1,0,0,0,600,601,1,0,0,0,601,603,1,0,0,0,602,600,1,0,0, + 0,603,604,3,123,61,0,604,605,7,9,0,0,605,617,1,0,0,0,606,608,3,139, + 69,0,607,606,1,0,0,0,607,608,1,0,0,0,608,610,1,0,0,0,609,611,3,137, + 68,0,610,609,1,0,0,0,611,612,1,0,0,0,612,610,1,0,0,0,612,613,1,0, + 0,0,613,614,1,0,0,0,614,615,7,9,0,0,615,617,1,0,0,0,616,567,1,0, + 0,0,616,568,1,0,0,0,616,587,1,0,0,0,616,607,1,0,0,0,617,156,1,0, + 0,0,618,619,3,161,80,0,619,620,7,9,0,0,620,158,1,0,0,0,621,625,7, + 29,0,0,622,624,7,30,0,0,623,622,1,0,0,0,624,627,1,0,0,0,625,623, + 1,0,0,0,625,626,1,0,0,0,626,160,1,0,0,0,627,625,1,0,0,0,628,636, + 5,34,0,0,629,630,5,92,0,0,630,635,9,0,0,0,631,632,5,34,0,0,632,635, + 5,34,0,0,633,635,8,31,0,0,634,629,1,0,0,0,634,631,1,0,0,0,634,633, + 1,0,0,0,635,638,1,0,0,0,636,634,1,0,0,0,636,637,1,0,0,0,637,639, + 1,0,0,0,638,636,1,0,0,0,639,640,5,34,0,0,640,162,1,0,0,0,641,643, + 7,32,0,0,642,641,1,0,0,0,643,644,1,0,0,0,644,642,1,0,0,0,644,645, + 1,0,0,0,645,648,1,0,0,0,646,648,3,131,65,0,647,642,1,0,0,0,647,646, + 1,0,0,0,648,649,1,0,0,0,649,650,6,81,0,0,650,164,1,0,0,0,651,653, + 5,13,0,0,652,651,1,0,0,0,652,653,1,0,0,0,653,654,1,0,0,0,654,655, + 5,10,0,0,655,166,1,0,0,0,37,0,431,442,445,474,479,482,487,490,495, + 501,505,511,513,519,521,528,533,539,544,546,558,562,565,574,581, + 593,600,607,612,616,625,634,636,644,647,652,1,6,0,0 ] class qutes_lexer(Lexer): diff --git a/src/tests/test_grammar.py b/src/tests/test_grammar.py index cb0c273..eb17b9a 100644 --- a/src/tests/test_grammar.py +++ b/src/tests/test_grammar.py @@ -151,7 +151,7 @@ def test_quantum_type_declaration_throws(self): ("qubit", "\"test\""), ("quint", "\"test\""), ("qustring", "10q"), - ("qustring", "[[0,1]q, 1q]"), + ("qustring", "[[0,1]q, 1q]q"), ("qustring", "false"), ] for var_type, declaration_value in params: From 23eaa432d72fc47e1789fc909833e771d8e1526b Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 17 Aug 2024 17:24:14 +0000 Subject: [PATCH 15/34] Refactor quantum types qubit state handling with state preparation --- src/grammar_frontend/operation.py | 2 +- .../quantum_circuit_handler.py | 31 +++--- src/quantum_circuit/state_preparation.py | 26 +++++ src/symbols/symbol.py | 2 +- src/symbols/types/quantum_array_type.py | 7 +- src/symbols/types/quantum_type.py | 13 ++- src/symbols/types/qubit.py | 7 +- src/symbols/types/quint.py | 100 ++++++++---------- src/symbols/types/qustring.py | 47 ++++---- src/symbols/types/qutes_data_type.py | 20 ++-- src/symbols/variables_handler.py | 3 +- src/tests/test_grammar.py | 7 +- 12 files changed, 136 insertions(+), 129 deletions(-) create mode 100644 src/quantum_circuit/state_preparation.py diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index 738fd85..a2252f4 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -312,7 +312,7 @@ def visitGroverOperator(self, ctx:qutes_parser.GroverOperatorContext): phase_kickback_ancilla = self.quantum_circuit_handler.declare_quantum_register(f"phase_kickback_ancilla_{current_grover_count}", Qubit(0,1)) oracle_registers.append(phase_kickback_ancilla) if(rotation_register == None): - rotation_register = self.quantum_circuit_handler.declare_quantum_register(f"rotation(grover:{current_grover_count})", Quint.init_from_integer(0,logn,True)) + rotation_register = self.quantum_circuit_handler.declare_quantum_register(f"rotation(grover:{current_grover_count})", Quint.init_from_size(logn,True)) oracle_registers.append(rotation_register) if(self.log_grover_esm_rotation): registers_to_measure.append(rotation_register) diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 3fcac0f..44cdda2 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -6,6 +6,7 @@ from quantum_circuit.quantum_register import QuantumRegister, QiskitQubit from symbols.types import Qubit, Quint, Qustring, QutesDataType from qiskit import IBMQ, Aer, QiskitError, transpile +from quantum_circuit.state_preparation import StatePreparation from qiskit.primitives import Sampler from qiskit.circuit.quantumcircuit import QubitSpecifier, CircuitInstruction from qiskit.circuit.library import GroverOperator, MCMT, ZGate, QFT, XGate, YGate, HGate, CXGate, MCXGate, PhaseGate @@ -23,7 +24,7 @@ def unwrap(l:list[QuantumRegister|ClassicalRegister]) -> list: class QuantumCircuitHandler(): def __init__(self): self._quantum_registers : list[QuantumRegister] = [] - self._registers_states : dict[QuantumRegister | ClassicalRegister, list[complex] | str | None] = {} + self._registers_states : dict[QuantumRegister | ClassicalRegister, StatePreparation] = {} self._classic_registers : list[ClassicalRegister] = [] self._operation_stacks : list[list[Callable[[QuantumCircuit], None]]] = [[]] self._current_operation_stack : list[Callable[[QuantumCircuit], None]] = self._operation_stacks[-1] @@ -49,11 +50,11 @@ def declare_quantum_register(self, variable_name : str, quantum_variable : Qubit self._varname_to_register[variable_name] = new_register self._quantum_registers.append(new_register) - self._registers_states[new_register] = quantum_variable.get_quantum_state() + self._registers_states[new_register] = quantum_variable.qubit_state return new_register # TODO: this should be a correlation operation, or a measure and then update. - # We cannot rely on quantum_variable.get_quantum_state() + # We cannot rely on quantum_variable.qubit_state def replace_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring) -> QuantumRegister: register_to_update = self._varname_to_register[variable_name] if(register_to_update is None): @@ -67,7 +68,7 @@ def replace_quantum_register(self, variable_name : str, quantum_variable : Qubi #Add new quantum register register_to_update = self._varname_to_register[variable_name] = QuantumRegister(quantum_variable.size, variable_name) self._quantum_registers.append(register_to_update) - self._registers_states[register_to_update] = quantum_variable.get_quantum_state() + self._registers_states[register_to_update] = quantum_variable.qubit_state else: raise SystemError("Error trying to update a quantum register with an unsupported type") @@ -110,11 +111,11 @@ def create_circuit(self, *regs, do_initialization:bool = True) -> QuantumCircuit circuit = QuantumCircuit(*regs) for register in self._quantum_registers: - # circuit.initialize('01', register, True) - # circuit.initialize([0, 1/np.sqrt(2), -1.j/np.sqrt(2), 0], register, True) - # TODO: the following should be pushed as an operation because we don't want this to execute while creating gates. if(do_initialization): - circuit.prepare_state(self._registers_states[register], register, "|0⟩-|1⟩/√2 ",normalize=True) + if(isinstance(self._registers_states[register], Gate)): + circuit.compose(self._registers_states[register], register, inplace=True) + else: + raise SystemError("Error trying to initialize a quantum register with an unsupported type") for operation in self._current_operation_stack: operation(circuit) return circuit @@ -262,12 +263,10 @@ def push_swap_operation(self, quantum_register_a : QuantumRegister, quantum_regi def push_equals_operation(self, quantum_register_a : QuantumRegister, classical_value : Any) -> None: quantum_value : Qubit | Quint | Qustring = QutesDataType.promote_classical_to_quantum_value(classical_value) - for index in range(len(quantum_register_a)): - if(len(quantum_value.qubit_state) > index): - qubit = quantum_value.qubit_state[-1-index] - if(qubit.alpha == 1 and qubit.beta == 0): - self.push_not_operation(quantum_register_a[index]) - else: + #find the only element in the statevector with prob == 1, and take its binary representation + state_to_match = utils.binary(quantum_value.qubit_state.params.index(complex(1)), len(quantum_register_a)) + for index, state in enumerate(state_to_match): + if(state == "0"): self.push_not_operation(quantum_register_a[index]) def push_reset_operation(self, quantum_register : QuantumRegister) -> None: @@ -297,9 +296,9 @@ def push_measure_operation(self, quantum_registers : list[QuantumRegister] = Non self._current_operation_stack.append(lambda circuit : cast(QuantumCircuit, circuit).measure(unwrap(quantum_registers), unwrap(classical_registers))) return classical_registers - def push_ESM_operation(self, input:QuantumRegister, rotation_register:QuantumRegister, to_match, block_size, phase_kickback_ancilla = None) -> None: + def push_ESM_operation(self, input:QuantumRegister, rotation_register:QuantumRegister, to_match:Qustring|Quint|Qubit, block_size, phase_kickback_ancilla = None) -> None: array_len = len(input) - to_match_len = len(to_match.qubit_state) + to_match_len = to_match.size # rotate input array from quantum_circuit.qutes_gates import QutesGates diff --git a/src/quantum_circuit/state_preparation.py b/src/quantum_circuit/state_preparation.py new file mode 100644 index 0000000..8be9c3e --- /dev/null +++ b/src/quantum_circuit/state_preparation.py @@ -0,0 +1,26 @@ +from typing import Union, Optional +from qiskit.circuit.library import StatePreparation as QiskitStatePreparation +from qiskit.quantum_info import Statevector + +class StatePreparation(QiskitStatePreparation): + def __init__( + self, + params: Union[str, list, int, Statevector], + num_qubits: Optional[int] = None, + inverse: bool = False, + label: Optional[str] = None, + normalize: bool = True, + ): + super().__init__(params, num_qubits, inverse, label, normalize) + + def __len__(self): + return self.num_qubits + + def __to_printable__(self) -> str: + return f"{self.params}" + + def __str__(self) -> str: + return self.__to_printable__() + + def __repr__(self) -> str: + return self.__to_printable__() \ No newline at end of file diff --git a/src/symbols/symbol.py b/src/symbols/symbol.py index a3637e8..07a2919 100644 --- a/src/symbols/symbol.py +++ b/src/symbols/symbol.py @@ -24,7 +24,7 @@ def __init__(self, self.symbol_class:SymbolClass = symbol_class self.symbol_declaration_static_type:QutesDataType = symbol_declaration_static_type self.casted_static_type:QutesDataType = casted_static_type #Promoted or Down Casted - self.value = value #value is not reliable on quantum types + self.value = value #value is not reliable on quantum types, in case of arrays it contains an array of symbols. self.parent_scope:ScopeTreeNode = parent_scope self.inner_scope:ScopeTreeNode = None self.ast_token_index:int = ast_token_index diff --git a/src/symbols/types/quantum_array_type.py b/src/symbols/types/quantum_array_type.py index 654f907..99a1841 100644 --- a/src/symbols/types/quantum_array_type.py +++ b/src/symbols/types/quantum_array_type.py @@ -1,8 +1,9 @@ -from typing import TypeVar +from typing import TypeVar, Type from symbols.types import QuantumType T = TypeVar("T") class QuantumArrayType(QuantumType[T]): - def __init__(self) -> None: - pass \ No newline at end of file + def __init__(self, unit_type: Type[T]): + super().__init__(unit_type) + self.unit_type = unit_type \ No newline at end of file diff --git a/src/symbols/types/quantum_type.py b/src/symbols/types/quantum_type.py index 79f9a4a..c7ac398 100644 --- a/src/symbols/types/quantum_type.py +++ b/src/symbols/types/quantum_type.py @@ -1,10 +1,12 @@ -from typing import Generic, TypeVar +from typing import Generic, TypeVar, Type +from quantum_circuit.state_preparation import StatePreparation T = TypeVar("T") class QuantumType(Generic[T]): - def __init__(self): - pass + def __init__(self, t_type: Type[T]): + self.t_type = t_type + self.qubit_state = StatePreparation("") def get_default_value(): raise NotImplementedError("get_default_value method must be implemented in derived class") @@ -14,6 +16,11 @@ def get_default_superposition_value(): def get_default_size_in_qubit(): raise NotImplementedError("get_default_size_in_qubit method must be implemented in derived class") + + def __eq__(self, other): + if isinstance(other, QuantumType): + return self.qubit_state == other.qubit_state + return False def __to_printable__(self) -> str: raise NotImplementedError("__to_printable__ method must be implemented in derived class") diff --git a/src/symbols/types/qubit.py b/src/symbols/types/qubit.py index b90d727..d11f4ea 100644 --- a/src/symbols/types/qubit.py +++ b/src/symbols/types/qubit.py @@ -1,16 +1,18 @@ from grammar_frontend.qutes_parser import QutesParser from symbols.types import QuantumType from utils.phase import Phase +from quantum_circuit.state_preparation import StatePreparation import cmath class Qubit(QuantumType['Qubit']): def __init__(self, alpha : complex = complex(1), beta : complex = complex(0)): + super().__init__(Qubit) self.size:int = 1 self.alpha = complex(alpha) self.beta = complex(beta) self.phase = Phase.Positive if (alpha * beta).real >= 0 else Phase.Negative self.is_superposition = cmath.isclose(abs(alpha), abs(beta)) - self.qubit_state:list[Qubit] = [self] + self.qubit_state = StatePreparation([self.alpha, self.beta]) def get_default_value(): return Qubit(complex(1),complex(0)) @@ -64,9 +66,6 @@ def fromValue(var_value : any) -> 'Qubit': return Qubit(complex(1), complex(0)) raise TypeError(f"Cannot convert {type(var_value)} to qubit.") - def get_quantum_state(self) -> list[complex]: - return [self.alpha, self.beta] - def update_size_with_padding(self, new_size : int) -> 'Quint': from symbols.types import Quint return Quint([self]).update_size_with_padding(new_size) diff --git a/src/symbols/types/quint.py b/src/symbols/types/quint.py index 14f85d2..ed88087 100644 --- a/src/symbols/types/quint.py +++ b/src/symbols/types/quint.py @@ -1,24 +1,26 @@ from grammar_frontend.qutes_parser import QutesParser from symbols.types import Qubit, QuantumType +from qiskit.quantum_info import Statevector +from quantum_circuit.state_preparation import StatePreparation import utils class Quint(QuantumType['Quint']): - def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): - super().__init__() - self.qubit_state:list[Qubit] = qubits + def __init__(self, qubits:StatePreparation = StatePreparation("0")): + super().__init__(Quint) + self.qubit_state:StatePreparation = qubits self.size:int = len(self.qubit_state) def get_default_value(): - return [Qubit(complex(1),complex(0))] * Qubit.get_default_size_in_qubit() + return "0" def get_default_superposition_value(): - return [Qubit(complex(0.5),complex(0.5))] * Qubit.get_default_size_in_qubit() + return "+" def get_default_size_in_qubit(): return 1 def init_from_string(literal : str) -> 'Quint': - qubits = [] + init_state = StatePreparation("0") qubit_literal_postfix = QutesParser.literal_to_string(QutesParser.QUBIT_LITERAL_POSTFIX) literal = literal.removesuffix(qubit_literal_postfix) if(literal.startswith(QutesParser.literal_to_string(QutesParser.SQUARE_PARENTHESIS_OPEN))): @@ -30,50 +32,46 @@ def init_from_string(literal : str) -> 'Quint': int_literals = [int(i) for i in quint_literals[0].replace(' ', '').split(',')] max_value_to_represent = max(int_literals) number_of_qubits = len(utils.binary(max_value_to_represent)) - counts = [0] * number_of_qubits - for number in int_literals: - binary_number = utils.binary(number, number_of_qubits) - for index in range(number_of_qubits): - counts[index] += int(binary_number[index]) + counts = [0] * (2**number_of_qubits) + + for integer in int_literals: + counts[integer] += 1 + + #Create a binary string from counts + counts_str = "" for count in counts: - number_of_values = 2**number_of_qubits - prob_of_being_true = (count/number_of_values) - qubits.append(Qubit(complex(1-prob_of_being_true), complex(prob_of_being_true))) + counts_str += str(count) + init_state = StatePreparation(counts_str) #we have an array of qubits that indicates the single qubits state the quint can take on - else: + else: + init_state = None for qubit_literal in quint_literals: if(len(qubit_literal)>0): - qubits.append(Qubit.from_string(qubit_literal.removeprefix(',') + qubit_literal_postfix)) + bit_init_state = Statevector(Qubit.from_string(qubit_literal.removeprefix(',') + qubit_literal_postfix).qubit_state) + if(init_state == None): + init_state = bit_init_state + else: + init_state = init_state.tensor(bit_init_state) + init_state = StatePreparation(init_state) #we have a simple integer that the quint can take on else: return Quint.init_from_integer(int(literal)) - return Quint(qubits) + return Quint(init_state) - def init_from_integer(literal : int | bool, initial_size:int = -1, init_in_superposition:bool = False) -> 'Quint': + def init_from_integer(literal : int | bool, initial_size:int = -1) -> 'Quint': binary_rapresentation = utils.binary(literal) - temp_state = [] - for digit in binary_rapresentation: - if(init_in_superposition): - temp_state.append(Qubit(complex(0.5),complex(0.5))) - elif(digit == '0'): - temp_state.append(Qubit(complex(1),complex(0))) - else: - temp_state.append(Qubit(complex(0),complex(1))) - if(initial_size != -1 and (len(temp_state) % initial_size != 0)): - to_add = initial_size - len(temp_state) % initial_size - if(init_in_superposition): - temp_state.extend(Quint.get_default_superposition_value() * to_add) - else: - temp_state.extend(Quint.get_default_value() * to_add) - return Quint(temp_state) + if(initial_size != -1 and len(binary_rapresentation) < initial_size): + binary_rapresentation += "0"*(initial_size - len(binary_rapresentation)) + return Quint(StatePreparation(binary_rapresentation)) - def init_from_size(number_of_bits : int) -> 'Quint': - return Quint(Quint.get_default_value()*number_of_bits) + def init_from_size(number_of_bits : int, init_in_superposition:bool = False) -> 'Quint': + template = Quint.get_default_superposition_value() if init_in_superposition else Quint.get_default_value() + return Quint(StatePreparation(template*number_of_bits)) def fromValue(var_value : any) -> 'Quint': try: if(isinstance(var_value, Qubit)): - return Quint([var_value]) + return Quint(var_value.qubit_state) if(isinstance(var_value, str)): return Quint.init_from_string(var_value) if(isinstance(var_value, int)): @@ -83,32 +81,18 @@ def fromValue(var_value : any) -> 'Quint': raise TypeError(f"Cannot convert {type(var_value)} to quint.") except: raise TypeError(f"Cannot convert {type(var_value)} to quint.") - - def get_quantum_state(self) -> list[complex] : - #TODO: this doesn't make any sense, outside of the initialization phase we should not rely on the quantum state. - quantum_state = [complex(1)] * (2**(self.size)) - for quantum_integer_state in range(2**self.size): - quantum_binary_state = utils.binary(quantum_integer_state, self.size) - for index in range(len(self.qubit_state)): - if quantum_binary_state[index] == '0': - quantum_state[quantum_integer_state] *= self.qubit_state[index].alpha - else: - quantum_state[quantum_integer_state] *= self.qubit_state[index].beta - return quantum_state - + def update_size_with_padding(self, new_size : int) -> 'Quint': - #TODO: qubit state is not reliable, we should add the qubit needed to expend the quint directly into the circuit. - self.qubit_state = (Quint.get_default_value*(new_size - self.size) + self.qubit_state) if self.size <= new_size else self.qubit_state[:new_size-1] - self.size = len(self.qubit_state) + #TODO: qubit state is not reliable, we should add the qubit needed to expand the quint directly into the circuit. + if (self.size < new_size): + old_state = self.qubit_state + new_state = Statevector(old_state).expand(Statevector(Quint.get_default_value()*(new_size - self.size))) + return Quint(new_state) return self def to_classical_type(self) -> int: - bin_number = str.join("", [str(int(qubit.beta.real)) for qubit in self.qubit_state]) + bin_number = str.join("", [str(value) for value in self.qubit_state.params]) return int(bin_number, 2) def __to_printable__(self) -> str: - str = '[' - for qubit in self.qubit_state: - str += f"{qubit}, " - str += ']' - return str \ No newline at end of file + return f"{self.qubit_state}" \ No newline at end of file diff --git a/src/symbols/types/qustring.py b/src/symbols/types/qustring.py index 544a9ce..0d6ade6 100644 --- a/src/symbols/types/qustring.py +++ b/src/symbols/types/qustring.py @@ -1,6 +1,7 @@ from grammar_frontend.qutes_parser import QutesParser from symbols.types import Qubit, Quint from symbols.types import QuantumType +from quantum_circuit.state_preparation import StatePreparation, Statevector import utils, math class Qustring(QuantumType['Qustring']): @@ -11,17 +12,17 @@ class Qustring(QuantumType['Qustring']): __not_valid_char = 'X' __allowed_chars = ['0', '1'] - def __init__(self, qubits:list[Qubit] = [Qubit(complex(1),complex(0))]): - super().__init__() - self.qubit_state:list[Qubit] = qubits + def __init__(self, qubits:StatePreparation = StatePreparation("0")): + super().__init__(Qustring) + self.qubit_state:StatePreparation = qubits self.size:int = len(self.qubit_state) self.number_of_chars:int = int(self.size / Qustring.get_default_size_in_qubit()) def get_default_value(): - return [Qubit(complex(1),complex(0))] * Qubit.get_default_size_in_qubit() + return [complex(1),complex(0)] * Qustring.get_default_size_in_qubit() def get_default_superposition_value(): - return [Qubit(complex(0.5),complex(0.5))] * Qubit.get_default_size_in_qubit() + return [complex(0.5),complex(0.5)] * Qustring.get_default_size_in_qubit() def get_default_size_in_qubit(): return math.ceil(math.log2(len(Qustring.__allowed_chars))) @@ -38,7 +39,7 @@ def get_int_from_char(char_value:str): return len(Qustring.__allowed_chars)-1 def init_from_string(literal : str) -> 'Qustring': - qubits = [] + init_state = None qubit_literal_postfix = QutesParser.literal_to_string(QutesParser.QUBIT_LITERAL_POSTFIX) literal = literal.removesuffix(qubit_literal_postfix) literal = literal.removesuffix('"') @@ -46,38 +47,28 @@ def init_from_string(literal : str) -> 'Qustring': for char in literal: if(char == Qustring.__superposition_char): - qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.get_default_size_in_qubit(), True) + qubyte:Quint = Quint.init_from_size(Qustring.get_default_size_in_qubit(), True) else: qubyte:Quint = Quint.init_from_integer(Qustring.get_int_from_char(char), Qustring.get_default_size_in_qubit()) - qubits.extend(qubyte.qubit_state) - return Qustring(qubits) + char_init_state = Statevector(qubyte.qubit_state) + if(init_state == None): + init_state = char_init_state + else: + init_state = init_state.tensor(char_init_state) + + init_state = StatePreparation(init_state) + return Qustring(init_state) def fromValue(var_value : any) -> 'Qustring': if(isinstance(var_value, Qubit)): - return Qustring([var_value]) + return Qustring(var_value.qubit_state) if(isinstance(var_value, str)): return Qustring.init_from_string(var_value) raise TypeError(f"Cannot convert {type(var_value)} to quint.") - - def get_quantum_state(self) -> list[complex] : - #TODO: this doesn't make any sense, outside of the initialization phase we should not rely on the quantum state. - quantum_state = [complex(1)] * (2**(self.size)) - for quantum_integer_state in range(2**self.size): - quantum_binary_state = utils.binary(quantum_integer_state, self.size) - for index in range(len(self.qubit_state)): - if quantum_binary_state[index] == '0': - quantum_state[quantum_integer_state] *= self.qubit_state[index].alpha - else: - quantum_state[quantum_integer_state] *= self.qubit_state[index].beta - return quantum_state def to_classical_type(self) -> int: - bin_number = str.join("", [str(int(qubit.beta.real)) for qubit in self.qubit_state]) + bin_number = str.join("", [str(value) for value in self.qubit_state.params]) return int(bin_number, 2) #TODO: this is not the correct way to convert a qustring to a classical type. def __to_printable__(self) -> str: - str = '[' - for qubit in self.qubit_state: - str += f"{qubit}, " - str += ']' - return str \ No newline at end of file + return f"{self.qubit_state}" \ No newline at end of file diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index a0ad74d..2db4e1e 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -68,14 +68,12 @@ def type_of(var_value : any) -> 'QutesDataType': return QutesDataType.bool_array return QutesDataType.promote_unit_to_array_type(QutesDataType.type_of(var_value[0])) if isinstance(var_value, QuantumArrayType): - return QutesDataType.qubit_array - # TODO: Subscripted generics cannot be used with class and instance checks - # if isinstance(var_value, QuantumArrayType[Qubit]): - # return QutesDataType.qubit_array - # if isinstance(var_value, QuantumArrayType[Quint]): - # return QutesDataType.quint_array - # if isinstance(var_value, QuantumArrayType[Qustring]): - # return QutesDataType.qustring_array + if var_value.unit_type == Qubit: + return QutesDataType.qubit_array + if var_value.unit_type == Quint: + return QutesDataType.quint_array + if var_value.unit_type == Qustring: + return QutesDataType.qustring_array if isinstance(var_value, Symbol): return var_value.symbol_declaration_static_type return QutesDataType.undefined @@ -173,11 +171,11 @@ def get_default_value(var_type : 'QutesDataType'): case QutesDataType.string_array: return [] case QutesDataType.qubit_array: - return QuantumArrayType[Qubit]() + return QuantumArrayType(Qubit) case QutesDataType.quint_array: - return QuantumArrayType[Quint]() + return QuantumArrayType(Quint) case QutesDataType.qustring_array: - return QuantumArrayType[Qustring]() + return QuantumArrayType(Qustring) case QutesDataType.void: return None case _: diff --git a/src/symbols/variables_handler.py b/src/symbols/variables_handler.py index 519bb8c..970c3cc 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -44,7 +44,7 @@ def update_variable_state(self, variable_name : str, new_state) -> Symbol: raise TypeError(f"Cannot convert type '{definition_qutes_type}' to '{value_to_assign_qutes_type}' for '{variable_name}'.") # Update the variable value if everything is ok. - symbol_to_update.value = value_to_assign + symbol_to_update.value = value_to_assign #TODO: in case of arrays, we need to check whether the elements are of the same type, and if any type cast is needed. symbol_to_update.promoted_static_type = final_type #Handle quantum circuit update @@ -89,6 +89,7 @@ def create_symbol(self, qutes_type : QutesDataType, value, ast_token_index:int) if(value is None): value = QutesDataType.get_default_value(qutes_type) + #TODO: in case of arrays, we need to check whether the elements are of the same type, and if any type cast is needed. variable_name = None value_qutes_type = QutesDataType.type_of(value) definition_type = qutes_type diff --git a/src/tests/test_grammar.py b/src/tests/test_grammar.py index eb17b9a..74068cf 100644 --- a/src/tests/test_grammar.py +++ b/src/tests/test_grammar.py @@ -2,6 +2,7 @@ from .qutes_base_test import QutesBaseTest from grammar_frontend.qutes_grammar_visitor import QutesGrammarVisitor from qutes_antlr.qutes_parserVisitor import __name__ as qutes_parserVisitor_class_name +from quantum_circuit.state_preparation import StatePreparation import inspect def sanitizeForVariableDeclarationUsage(value:any) -> str: @@ -127,7 +128,7 @@ def test_quantum_type_declaration_succeed(self): ("qubit", "|->", Qubit(0.5, -0.5)), ("quint", "10q", Quint.fromValue(10)), ("quint", "false", Quint.fromValue(0)), - ("quint", "[[0,1]q, 1q]", Quint([Qubit(0.5, 0.5), Qubit(0, 1)])), + ("quint", "[[0,1]q, 1q]q", Quint(StatePreparation([complex(0), complex(1), complex(0), complex(1)]))), ("qustring", "\"test\"", Qustring.fromValue("test")), ("qustring", "\"t*st\"", Qustring.fromValue("t*st")), ("qustring", "1q", Qustring.fromValue(Qubit(0,1))), @@ -141,8 +142,8 @@ def test_quantum_type_declaration_succeed(self): """ result = self.parse_qutes_code(code) - actual_value_of_var = str(result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value) - self.assertEqual(actual_value_of_var, str(expected_value_of_var), f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") + actual_value_of_var = result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value.qubit_state + self.assertEqual(actual_value_of_var, expected_value_of_var.qubit_state, f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") def test_quantum_type_declaration_throws(self): params = [ From d5fcc313bc2cacaca4cc0c737452242389378405 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sat, 17 Aug 2024 17:26:23 +0000 Subject: [PATCH 16/34] Add array syntax tests --- src/tests/test_array_access.py | 22 -------------- src/tests/test_arrays.py | 54 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 22 deletions(-) delete mode 100644 src/tests/test_array_access.py create mode 100644 src/tests/test_arrays.py diff --git a/src/tests/test_array_access.py b/src/tests/test_array_access.py deleted file mode 100644 index 6001ab5..0000000 --- a/src/tests/test_array_access.py +++ /dev/null @@ -1,22 +0,0 @@ -from .qutes_base_test import QutesBaseTest - -class TestArrayAccess(QutesBaseTest): - def assert_operation_test(self, code, var_name, expected_value_of_var): - result = self.parse_qutes_code(code) - actual_value_of_var = str(result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value) - self.assertEqual(actual_value_of_var, str(expected_value_of_var), f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") - - def test_left_shift_return_expected_value(self): - params = [ - ("\"01111111\"", "0", "01111111"), - ] - var_name = "a" - var_result_name = "result" - for init_string, n_shift, expected_value_of_var in params: - with self.subTest(init_string=init_string, n_shift=n_shift, expected_value_of_var=expected_value_of_var): - code = f""" - qustring {var_name} = {init_string}; - {var_name} << {n_shift}; - string {var_result_name} = {var_name}; - """ - self.assert_operation_test(code, var_result_name, expected_value_of_var) diff --git a/src/tests/test_arrays.py b/src/tests/test_arrays.py new file mode 100644 index 0000000..02cb01d --- /dev/null +++ b/src/tests/test_arrays.py @@ -0,0 +1,54 @@ +from .qutes_base_test import QutesBaseTest +from symbols.types import Qubit, Quint, Qustring, QuantumArrayType +from quantum_circuit.state_preparation import StatePreparation + +class TestArrays(QutesBaseTest): + def assert_arrays_test(self, code, var_name, expected_value_of_var): + result = self.parse_qutes_code(code) + actual_value_of_var = result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value + if isinstance(actual_value_of_var, list): + actual_value_of_var = [symbol.value for symbol in actual_value_of_var] + self.assertListEqual(actual_value_of_var, expected_value_of_var, f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") + + def test_quantum_type_declaration_succeed(self): + params = [ + ("qubit[]", "[|+>, |->]", [Qubit(0.5, 0.5), Qubit(0.5, -0.5)]), + ("qubit[]", "[1q, |->]", [Qubit(0, 1), Qubit(0.5, -0.5)]), + ("quint[]", "[2q, 3q]", [Quint.fromValue(2), Quint.fromValue(3)]), + ("quint[]", "[[[0,1]q, 1q]q, 3q]", [Quint(StatePreparation([complex(0), complex(1), complex(0), complex(1)])), Quint.fromValue(3)]), + ("qustring[]", "[\"101\"q, \"001\"q]", [Qustring.fromValue("101"), Qustring.fromValue("001")]), + ] + var_name:str = "foo" + for var_type, declaration_value, expected_values_of_array in params: + with self.subTest(var_type=var_type, declaration_value=declaration_value, expected_values_of_array=expected_values_of_array): + code = f""" + {var_type} {var_name} = {declaration_value}; + """ + self.assert_arrays_test(code, var_name, expected_values_of_array) + + def test_quantum_type_declaration_throws(self): + params = [ + ("qubit[]", "[2q]"), + ("qubit[]", "[2q, |->]"), + ("qubit[]", "[|->, 2q]"), + ("quint[]", "[\"11\"q]"), + ("quint[]", "[\"11\"q, 3q]"), + ("quint[]", "[3q, \"11\"q]"), + ("qustring[]", "[1q]"), + ("qustring[]", "[1q, \"11\"q]"), + ("qustring[]", "[\"11\"q, 1q]"), + ("qustring[]", "[3q]"), + ("qustring[]", "[3q, \"11\"q]"), + ("qustring[]", "[\"11\"q, 3q]"), + ("qustring[]", "[|->]"), + ("qustring[]", "[|->, \"11\"q]"), + ("qustring[]", "[\"11\"q, |->]"), + ] + var_name:str = "foo" + for var_type, declaration_value in params: + with self.subTest(var_type=var_type, declaration_value=declaration_value): + code = f""" + {var_type} {var_name} = {declaration_value}; + """ + with self.assertRaises((SyntaxError, TypeError)): + self.parse_qutes_code(code) From 3da64cd551e71e9aecff61eda885c4d4d62fb109 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 13:17:37 +0000 Subject: [PATCH 17/34] Add arrays access tests --- src/tests/test_arrays.py | 60 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/tests/test_arrays.py b/src/tests/test_arrays.py index 02cb01d..4d4d824 100644 --- a/src/tests/test_arrays.py +++ b/src/tests/test_arrays.py @@ -8,7 +8,9 @@ def assert_arrays_test(self, code, var_name, expected_value_of_var): actual_value_of_var = result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value if isinstance(actual_value_of_var, list): actual_value_of_var = [symbol.value for symbol in actual_value_of_var] - self.assertListEqual(actual_value_of_var, expected_value_of_var, f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") + self.assertListEqual(actual_value_of_var, expected_value_of_var, f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") + else: + self.assertEqual(actual_value_of_var, expected_value_of_var, f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") def test_quantum_type_declaration_succeed(self): params = [ @@ -52,3 +54,59 @@ def test_quantum_type_declaration_throws(self): """ with self.assertRaises((SyntaxError, TypeError)): self.parse_qutes_code(code) + + def test_quantum_type_access_succeed(self): + params = [ + ("qubit[]", "[|+>, |->]", [Qubit(0.5, 0.5), Qubit(0.5, -0.5)]), + ("qubit[]", "[1q, |->]", [Qubit(0, 1), Qubit(0.5, -0.5)]), + ("quint[]", "[2q, 3q]", [Quint.fromValue(2), Quint.fromValue(3)]), + ("quint[]", "[[[0,1]q, 1q]q, 3q]", [Quint(StatePreparation([complex(0), complex(1), complex(0), complex(1)])), Quint.fromValue(3)]), + ("qustring[]", "[\"101\"q, \"001\"q]", [Qustring.fromValue("101"), Qustring.fromValue("001")]), + ] + var_name:str = "foo" + for var_type, declaration_value, expected_values_of_array in params: + with self.subTest(var_type=var_type, declaration_value=declaration_value, expected_values_of_array=expected_values_of_array): + code = f""" + {var_type} {var_name} = {declaration_value}; + """ + for i in range(len(expected_values_of_array)): + code += f"{var_type[:-2]} {var_name}_{i} = {var_name}[{i}];" + for i in range(len(expected_values_of_array)): + self.assert_arrays_test(code, f"{var_name}_{i}", expected_values_of_array[i]) + + def test_quantum_type_access_reverse_succeed(self): + params = [ + ("qubit[]", "[|+>, |->]", [Qubit(0.5, 0.5), Qubit(0.5, -0.5)]), + ("qubit[]", "[1q, |->]", [Qubit(0, 1), Qubit(0.5, -0.5)]), + ("quint[]", "[2q, 3q]", [Quint.fromValue(2), Quint.fromValue(3)]), + ("quint[]", "[[[0,1]q, 1q]q, 3q]", [Quint(StatePreparation([complex(0), complex(1), complex(0), complex(1)])), Quint.fromValue(3)]), + ("qustring[]", "[\"101\"q, \"001\"q]", [Qustring.fromValue("101"), Qustring.fromValue("001")]), + ] + var_name:str = "foo" + for var_type, declaration_value, expected_values_of_array in params: + with self.subTest(var_type=var_type, declaration_value=declaration_value, expected_values_of_array=expected_values_of_array): + code = f""" + {var_type} {var_name} = {declaration_value}; + """ + for i in range(len(expected_values_of_array)): + code += f"{var_type[:-2]} {var_name}_{i} = {var_name}[-{i}];" + for i in range(len(expected_values_of_array)): + self.assert_arrays_test(code, f"{var_name}_{i}", expected_values_of_array[-i]) + + def test_quantum_type_access_out_of_range_sup_throws(self): + var_name:str = "foo" + code = f""" + qubit[] {var_name} = [|+>, |->]; + qubit {var_name}_3 = {var_name}[3]; + """ + with self.assertRaises(IndexError): + self.parse_qutes_code(code) + + def test_quantum_type_access_out_of_range_sub_throws(self): + var_name:str = "foo" + code = f""" + qubit[] {var_name} = [|+>, |->]; + qubit {var_name}_3 = {var_name}[-3]; + """ + with self.assertRaises(IndexError): + self.parse_qutes_code(code) \ No newline at end of file From 8733230bc692cceb10755af95a5b2138750c4e0b Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 13:18:06 +0000 Subject: [PATCH 18/34] Add classical array types promotion --- src/symbols/types/type_casting_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/symbols/types/type_casting_handler.py b/src/symbols/types/type_casting_handler.py index 64678dd..76e2376 100644 --- a/src/symbols/types/type_casting_handler.py +++ b/src/symbols/types/type_casting_handler.py @@ -20,9 +20,9 @@ def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): QutesDataType.qustring: [QutesDataType.qustring, QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], QutesDataType.void: [], QutesDataType.bool_array: [], - QutesDataType.int_array: [], - QutesDataType.float_array: [], - QutesDataType.string_array: [], + QutesDataType.int_array: [QutesDataType.bool_array], + QutesDataType.float_array: [QutesDataType.bool_array, QutesDataType.int_array], + QutesDataType.string_array: [QutesDataType.bool_array, QutesDataType.int_array, QutesDataType.float_array], QutesDataType.qubit_array: [], QutesDataType.quint_array: [], QutesDataType.qustring_array: [], From eecb2ffe1b2fb36a5b623742557f346465d881ed Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 13:18:30 +0000 Subject: [PATCH 19/34] Add type compatibility check for array values --- src/symbols/types/qutes_data_type.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index 2db4e1e..665f716 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -65,8 +65,9 @@ def type_of(var_value : any) -> 'QutesDataType': return QutesDataType.qustring if isinstance(var_value, list): if(len(var_value) == 0): - return QutesDataType.bool_array - return QutesDataType.promote_unit_to_array_type(QutesDataType.type_of(var_value[0])) + return QutesDataType.bool_array + bigger_type = QutesDataType.types_are_compatible([QutesDataType.type_of(item) for item in var_value]) + return QutesDataType.promote_unit_to_array_type(bigger_type) if isinstance(var_value, QuantumArrayType): if var_value.unit_type == Qubit: return QutesDataType.qubit_array @@ -77,6 +78,16 @@ def type_of(var_value : any) -> 'QutesDataType': if isinstance(var_value, Symbol): return var_value.symbol_declaration_static_type return QutesDataType.undefined + + def types_are_compatible(types: list['QutesDataType']) -> 'QutesDataType': + if len(types) == 0: + return QutesDataType.bool + if len(types) == 1: + return types[0] + if all(type == types[0] for type in types): + return types[0] + # TODO: if not all types are the same, check if they can be promoted to a common type + raise TypeError(f"Types {types} are not compatible.") def from_string_type(var_definition_type : str) -> 'QutesDataType': to_match = var_definition_type.lower() From 95b22c89a152a536390f7920b63b2c0c52a96553 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:23:13 +0000 Subject: [PATCH 20/34] fix test_variable_shadowing_succeed to manually check the scope instead of pushing it again --- src/tests/test_grammar.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tests/test_grammar.py b/src/tests/test_grammar.py index 74068cf..6bdbef0 100644 --- a/src/tests/test_grammar.py +++ b/src/tests/test_grammar.py @@ -181,6 +181,5 @@ def test_variable_shadowing_succeed(self): {{ string {var_name} = {declaration_value_of_var}; }} """ result = self.parse_qutes_code(code) - result.scope_handler.push_scope() - actual_value_of_var = str(result.variables_handler.get_variable_symbol(var_name, self.TOKEN_AST_INDEX_FOR_TESTS).value) - self.assertEqual(actual_value_of_var, str(expected_value_of_var), f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") + actual_value_of_var = [symbol.value for symbol in result.scope_handler.symbols_tree.children[0].symbols if symbol.name == var_name][-1] + self.assertEqual(str(actual_value_of_var), str(expected_value_of_var), f"Expected value: {expected_value_of_var}, actual value: {actual_value_of_var}") From 851b5abf0e65d7d9e00879ade8680d734ccfef35 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:23:38 +0000 Subject: [PATCH 21/34] Add print methods to ScopeTreeNode --- src/symbols/scope_tree_node.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/symbols/scope_tree_node.py b/src/symbols/scope_tree_node.py index 6f1dec5..3e5121a 100644 --- a/src/symbols/scope_tree_node.py +++ b/src/symbols/scope_tree_node.py @@ -22,4 +22,13 @@ def __init__(self, scope_class:ScopeClass, scope_type_detail:str, parent=None, c self.scope_type_detail = scope_type_detail self.parent = parent if children: - self.children = children \ No newline at end of file + self.children = children + + def __to_printable__(self) -> str: + return f"{self.scope_class}/{self.scope_type_detail}: {self.symbols}" + + def __str__(self) -> str: + return self.__to_printable__() + + def __repr__(self) -> str: + return self.__to_printable__() \ No newline at end of file From 79b78e915892cb7af3c80ed2d63303e255dbbec1 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:25:11 +0000 Subject: [PATCH 22/34] Fix loope scope handling --- src/symbols/scope_handler.py | 37 +++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/symbols/scope_handler.py b/src/symbols/scope_handler.py index 7e70c24..0841a11 100644 --- a/src/symbols/scope_handler.py +++ b/src/symbols/scope_handler.py @@ -1,8 +1,9 @@ from symbols.scope_tree_node import ScopeTreeNode, ScopeClass from symbols.symbol import Symbol -from anytree import PreOrderIter +from anytree import PreOrderIter, RenderTree class ScopeHandler(): + print_trace = False def __init__(self): self.symbols_tree:ScopeTreeNode = None self.current_symbols_scope:ScopeTreeNode = self.symbols_tree @@ -12,7 +13,6 @@ class ScopeHandlerForSymbolsDiscovery(ScopeHandler): def __init__(self): super().__init__() - def push_scope(self, scope:ScopeClass, scope_detail:str, symbols:list[Symbol] = []) -> ScopeTreeNode: _symbols:list[Symbol] = symbols.copy() if(self.current_symbols_scope): @@ -28,6 +28,10 @@ def push_scope(self, scope:ScopeClass, scope_detail:str, symbols:list[Symbol] = self.symbols_tree = new_scope self.current_symbols_scope = new_scope + + if(ScopeHandler.print_trace and self.current_symbols_scope != None): + print (f"push_scope: \n{RenderTree(self.current_symbols_scope)}") + return self.current_symbols_scope def push_inner_scope(self, scope:ScopeClass, scope_detail:str, symbol_owner:Symbol, symbols:list[Symbol] = []) -> ScopeTreeNode: @@ -37,6 +41,10 @@ def push_inner_scope(self, scope:ScopeClass, scope_detail:str, symbol_owner:Symb def pop_scope(self) -> ScopeTreeNode: self.current_symbols_scope = self.current_symbols_scope.parent + + if(ScopeHandler.print_trace and self.current_symbols_scope != None): + print (f"pop_scope: \n{RenderTree(self.current_symbols_scope)}") + return self.current_symbols_scope @@ -54,13 +62,23 @@ def __init__(self, symbols_tree:ScopeTreeNode): self.current_symbols_scope:ScopeTreeNode = self.symbols_tree self.tree_preorder_iterator = PreOrderIter(self.symbols_tree) self.is_inside_loop = False + self.loop_inner_scope = None self.is_inside_function = False def start_loop(self) -> None: self.is_inside_loop = True + self.loop_inner_scope = self.current_symbols_scope + + def handle_loop_cycle(self) -> None: + temp_iterator = PreOrderIter(self.symbols_tree) + temp_node = None + while temp_node != self.current_symbols_scope: + temp_node = next(temp_iterator) + self.tree_preorder_iterator = temp_iterator def end_loop(self) -> None: self.is_inside_loop = False + self.loop_inner_scope = None def start_function(self) -> None: self.is_inside_function = True @@ -69,18 +87,23 @@ def end_function(self) -> None: self.is_inside_function = False #Start visiting scope - def push_scope(self) -> ScopeTreeNode: - if(self.is_inside_loop == False and self.is_inside_function == False): + def push_scope(self, tree_iterator = None) -> ScopeTreeNode: + if tree_iterator != None: + self.tree_preorder_iterator = tree_iterator + if(self.is_inside_function == False): nextNode = next(self.tree_preorder_iterator) + if(ScopeHandler.print_trace and nextNode != None): + print (f"push_scope: \n{RenderTree(nextNode)}") if(nextNode != None): self.current_symbols_scope = nextNode return self.current_symbols_scope #End visiting scope, return to parent and never(almost, see loops) visit this scope again def pop_scope(self) -> ScopeTreeNode: - if(self.is_inside_loop == False and self.is_inside_function == False): + if(self.is_inside_function == False): parentNode = self.current_symbols_scope.parent if(parentNode != None): - self.tree_preorder_iterator = PreOrderIter(parentNode) - self.current_symbols_scope = next(self.tree_preorder_iterator) + self.current_symbols_scope = parentNode + if(ScopeHandler.print_trace and self.current_symbols_scope != None): + print (f"pop_scope: \n{RenderTree(self.current_symbols_scope)}") return self.current_symbols_scope \ No newline at end of file From eb520cf5a69dd2993434cae9946c6383332d2d3f Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:26:56 +0000 Subject: [PATCH 23/34] Add print method to QuantumArrayType --- src/symbols/types/quantum_array_type.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/symbols/types/quantum_array_type.py b/src/symbols/types/quantum_array_type.py index 99a1841..346f78a 100644 --- a/src/symbols/types/quantum_array_type.py +++ b/src/symbols/types/quantum_array_type.py @@ -6,4 +6,7 @@ class QuantumArrayType(QuantumType[T]): def __init__(self, unit_type: Type[T]): super().__init__(unit_type) - self.unit_type = unit_type \ No newline at end of file + self.unit_type = unit_type + + def __to_printable__(self) -> str: + return f"{self.unit_type.__name__}[]" \ No newline at end of file From 4ad6205cdf8812a8da9115f9742720799050ee3b Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:28:08 +0000 Subject: [PATCH 24/34] Add foreach statement to grammar --- specification/grammar/qutes_lexer.g4 | 2 + specification/grammar/qutes_parser.g4 | 5 +- src/grammar_frontend/statement.py | 36 +- .../symbols_discovery_visitor.py | 14 +- src/qutes_antlr/qutes_lexer.py | 623 +++++----- src/qutes_antlr/qutes_lexer.tokens | 172 +-- src/qutes_antlr/qutes_parser.py | 1007 +++++++++-------- src/qutes_antlr/qutes_parser.tokens | 172 +-- src/qutes_antlr/qutes_parserListener.py | 9 + src/qutes_antlr/qutes_parserVisitor.py | 5 + 10 files changed, 1093 insertions(+), 952 deletions(-) diff --git a/specification/grammar/qutes_lexer.g4 b/specification/grammar/qutes_lexer.g4 index 7697304..b32e203 100644 --- a/specification/grammar/qutes_lexer.g4 +++ b/specification/grammar/qutes_lexer.g4 @@ -34,6 +34,7 @@ MCP : 'mcp' ; HADAMARD : 'hadamard' ; MEASURE : 'measure' ; PRINT : 'print' ; +PRINT_LN : 'println' ; BARRIER : 'barrier' ; EQUAL : '==' ; NOT_EQUAL : '!=' ; @@ -54,6 +55,7 @@ AUTO_MODULE : '%=' ; END_OF_STATEMENT : ';' ; VAR_STATEMENT : 'var' ; FOR_STATEMENT : 'for' ; +FOREACH_STATEMENT : 'foreach' ; SEARCH_STATEMENT : 'search' ; IN_STATEMENT : 'in' ; WHERE_STATEMENT : 'where' ; diff --git a/specification/grammar/qutes_parser.g4 b/specification/grammar/qutes_parser.g4 index 6dd5e3a..8cf7458 100644 --- a/specification/grammar/qutes_parser.g4 +++ b/specification/grammar/qutes_parser.g4 @@ -15,6 +15,7 @@ statement : IF_STATEMENT expr statement #IfStatement | IF_STATEMENT expr statement ELSE_STATEMENT statement #IfElseStatement | WHILE_STATEMENT expr statement #WhileStatement + | FOREACH_STATEMENT variableDeclaration (COMMA variableDeclaration)? IN_STATEMENT qualifiedName statement #ForeachStatement | DO_STATEMENT statement WHILE_STATEMENT expr #DoWhileStatement | CURLY_PARENTHESIS_OPEN statement* CURLY_PARENTHESIS_CLOSE #BlockStatement | variableType functionName ROUND_PARENTHESIS_OPEN functionDeclarationParams? ROUND_PARENTHESIS_CLOSE statement #FunctionStatement @@ -22,7 +23,7 @@ statement | qualifiedName ASSIGN expr END_OF_STATEMENT #AssignmentStatement | RETURN expr END_OF_STATEMENT #ReturnStatement | expr END_OF_STATEMENT #ExpressionStatement - | (MEASURE | BARRIER) #FactStatement + | (MEASURE | BARRIER | PRINT_LN) #FactStatement | END_OF_STATEMENT #EmptyStatement ; @@ -59,7 +60,7 @@ expr // Order: https://en.wikipedia.org/wiki/Order_of_operations#Programming_lan | expr op=OR expr #LogicOrOperator // Assignment and auto assignment operators | expr op=(AUTO_SUM | AUTO_DECREMENT | AUTO_MODULE | AUTO_DIVIDE | AUTO_MODULE) expr #AutoAssignmentOperator | op=(MCX | MCZ | MCY | SWAP) termList #MultipleUnaryOperator - | op=(PRINT | PAULIY | PAULIZ | HADAMARD | MEASURE) expr #UnaryOperator + | op=(PRINT | PRINT_LN | PAULIY | PAULIZ | HADAMARD | MEASURE) expr #UnaryOperator | op=MCP termList BY expr #MultipleUnaryPhaseOperator | termList op=IN_STATEMENT qualifiedName #GroverOperator ; diff --git a/src/grammar_frontend/statement.py b/src/grammar_frontend/statement.py index d5fc35b..724131e 100644 --- a/src/grammar_frontend/statement.py +++ b/src/grammar_frontend/statement.py @@ -41,7 +41,31 @@ def visitIfElseStatement(self, ctx:qutes_parser.IfElseStatementContext): self.scope_handler.pop_scope() self.visit(ctx.statement(1)) self.scope_handler.pop_scope() - return None + return None + + def visitForeachStatement(self, ctx:qutes_parser.ForeachStatementContext): + self.scope_handler.push_scope() + auxiliary:Symbol = self.visit(ctx.variableDeclaration(0)) + index:Symbol|None = None + if(ctx.variableDeclaration(1)): + index = self.visit(ctx.variableDeclaration(1)) + if(index.symbol_declaration_static_type != QutesDataType.int): + raise TypeError(f"Index variable '{index.name}' must be of type 'int'.") + array = self.visit(ctx.qualifiedName()).value + if(array != None): + self.scope_handler.start_loop() #avoid block statement to change the scope + + for i, next_value in enumerate(array): + self.scope_handler.handle_loop_cycle() + self.variables_handler.update_variable_state(auxiliary.name, next_value) + if(index != None): + self.variables_handler.update_variable_state(index.name, i) + self.visit(ctx.statement()) + + self.scope_handler.end_loop() #reset scope handling + + self.scope_handler.pop_scope() + return None def visitWhileStatement(self, ctx:qutes_parser.WhileStatementContext): return self.__visit_while_statement(ctx) @@ -50,21 +74,15 @@ def __visit_while_statement(self, ctx:qutes_parser.IfStatementContext): self.scope_handler.push_scope() condition = self.visit(ctx.expr()) if(condition != None): - if(isinstance(ctx.statement(), qutes_parser.BlockStatementContext)): - #the while statement needs to handle the scope so that the the block statement can work always on the same scope(its own scope) - self.scope_handler.push_scope() - self.scope_handler.start_loop() #avoid block statement to change the scope while(self.variables_handler.get_value(condition)): + self.scope_handler.handle_loop_cycle() self.visit(ctx.statement()) condition = self.visit(ctx.expr()) self.scope_handler.end_loop() #reset scope handling - if(isinstance(ctx.statement(), qutes_parser.BlockStatementContext)): - #the while statement needs to handle the scope so that the the block statement can work always on the same scope(its own scope) - self.scope_handler.pop_scope() self.scope_handler.pop_scope() return None @@ -151,6 +169,8 @@ def visitFactStatement(self, ctx:qutes_parser.FactStatementContext): self.quantum_circuit_handler.push_measure_operation() if(ctx.BARRIER()): self.quantum_circuit_handler.push_barrier_operation() + if(ctx.PRINT_LN()): + print() return None def visitEmptyStatement(self, ctx:qutes_parser.EmptyStatementContext): diff --git a/src/grammar_frontend/symbols_discovery_visitor.py b/src/grammar_frontend/symbols_discovery_visitor.py index 466c671..9abe9f6 100644 --- a/src/grammar_frontend/symbols_discovery_visitor.py +++ b/src/grammar_frontend/symbols_discovery_visitor.py @@ -11,14 +11,17 @@ class SymbolsDiscoveryVisitor(qutesVisitor): """An antlr visitor for the qutes grammar that discovers symbols like variable, function names etc.""" - def __init__(self, quantum_cirtcuit_handler : QuantumCircuitHandler): + def __init__(self, quantum_cirtcuit_handler : QuantumCircuitHandler, verbose:bool = False): self.quantum_cirtcuit_handler = quantum_cirtcuit_handler + self.verbose = verbose self.scope_handler = ScopeHandlerForSymbolsDiscovery() self.scope_count = 0 self.if_else_scope_count = 0 self.loop_scope_count = 0 self.function_scope_count = 0 self.variables_handler = VariablesHandler(self.scope_handler, self.quantum_cirtcuit_handler) + + ScopeHandlerForSymbolsDiscovery.print_trace = False def visitProgram(self, ctx:qutesParser.ProgramContext): self.scope_handler.push_scope(ScopeClass.GlobalScope, "GlobalScope") @@ -41,6 +44,13 @@ def visitIfElseStatement(self, ctx:qutesParser.IfElseStatementContext): self.scope_handler.pop_scope() + # visit a parse tree produced by qutesParser#ForeachStatement. + def visitForeachStatement(self, ctx:qutesParser.ForeachStatementContext): + self.loop_scope_count += 1 + self.scope_handler.push_scope(ScopeClass.LoopScope, f"Foreach{self.loop_scope_count}") + self.visitChildren(ctx) + self.scope_handler.pop_scope() + # visit a parse tree produced by qutesParser#WhileStatement. def visitWhileStatement(self, ctx:qutesParser.WhileStatementContext): self.loop_scope_count += 1 @@ -62,7 +72,7 @@ def visitBlockStatement(self, ctx:qutesParser.BlockStatementContext): if(self.scope_handler.current_symbols_scope.scope_class == ScopeClass.IfElseScope): self.scope_handler.push_scope(ScopeClass.BranchScope, f"BranchBlock{self.if_else_scope_count}") elif(self.scope_handler.current_symbols_scope.scope_class == ScopeClass.LoopScope): - self.scope_handler.push_scope(ScopeClass.BranchScope, f"BranchBlock{self.loop_scope_count}") + self.scope_handler.push_scope(ScopeClass.BranchScope, f"LoopBlock{self.loop_scope_count}") elif(self.scope_handler.current_symbols_scope.scope_class == ScopeClass.FunctionScope): #self.scope_handler.push_scope(ScopeClass.FunctionBlockScope, f"FunctionBlock{self.function_scope_count}") pass diff --git a/src/qutes_antlr/qutes_lexer.py b/src/qutes_antlr/qutes_lexer.py index 9475ae9..93e09fd 100644 --- a/src/qutes_antlr/qutes_lexer.py +++ b/src/qutes_antlr/qutes_lexer.py @@ -10,7 +10,7 @@ def serializedATN(): return [ - 4,0,77,656,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, + 4,0,79,676,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, 2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2, 13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7, 19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2, @@ -22,237 +22,244 @@ def serializedATN(): 58,2,59,7,59,2,60,7,60,2,61,7,61,2,62,7,62,2,63,7,63,2,64,7,64,2, 65,7,65,2,66,7,66,2,67,7,67,2,68,7,68,2,69,7,69,2,70,7,70,2,71,7, 71,2,72,7,72,2,73,7,73,2,74,7,74,2,75,7,75,2,76,7,76,2,77,7,77,2, - 78,7,78,2,79,7,79,2,80,7,80,2,81,7,81,2,82,7,82,1,0,1,0,1,0,1,0, - 1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3, - 1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,5, - 1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8, - 1,8,1,8,1,8,1,9,1,9,1,10,1,10,1,11,1,11,1,12,1,12,1,13,1,13,1,14, - 1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,16,1,16,1,16,1,17,1,17,1,17, - 1,18,1,18,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,19,1,19,1,20, - 1,20,1,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,21,1,21,1,21,1,21, - 1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,24,1,24,1,24,1,24,1,25, - 1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,27, - 1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,1,28,1,28, - 1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1,31,1,31, - 1,31,1,32,1,32,1,33,1,33,1,33,1,34,1,34,1,35,1,35,1,35,1,36,1,36, - 1,36,1,37,1,37,1,37,1,38,1,38,1,39,1,39,1,39,1,40,1,40,1,40,1,41, - 1,41,1,41,1,42,1,42,1,42,1,43,1,43,1,43,1,44,1,44,1,44,1,45,1,45, - 1,45,1,46,1,46,1,47,1,47,1,47,1,47,1,48,1,48,1,48,1,48,1,49,1,49, - 1,49,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,51, - 1,51,1,52,1,52,1,52,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,54, - 1,54,1,54,1,55,1,55,1,55,1,56,1,56,1,57,1,57,1,58,1,58,1,59,1,59, - 1,60,1,60,1,61,1,61,1,62,1,62,1,63,1,63,1,64,1,64,1,65,1,65,1,65, - 1,65,5,65,430,8,65,10,65,12,65,433,9,65,1,65,1,65,1,65,1,65,1,65, - 1,65,5,65,441,8,65,10,65,12,65,444,9,65,3,65,446,8,65,1,66,1,66, - 1,66,1,66,1,66,1,67,1,67,1,67,1,67,1,67,1,67,1,68,1,68,1,69,1,69, - 1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,3,70, - 475,8,70,1,71,1,71,1,71,3,71,480,8,71,1,72,3,72,483,8,72,1,72,4, - 72,486,8,72,11,72,12,72,487,1,73,3,73,491,8,73,1,73,4,73,494,8,73, - 11,73,12,73,495,1,73,1,73,5,73,500,8,73,10,73,12,73,503,9,73,1,73, - 3,73,506,8,73,1,73,1,73,4,73,510,8,73,11,73,12,73,511,3,73,514,8, - 73,1,74,1,74,1,74,1,74,4,74,520,8,74,11,74,12,74,521,1,75,1,75,1, - 75,4,75,527,8,75,11,75,12,75,528,1,76,1,76,1,76,3,76,534,8,76,1, - 76,1,76,5,76,538,8,76,10,76,12,76,541,9,76,1,76,1,76,3,76,545,8, - 76,3,76,547,8,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1, - 76,3,76,559,8,76,1,76,1,76,3,76,563,8,76,1,76,3,76,566,8,76,1,77, - 1,77,1,77,1,77,1,77,5,77,573,8,77,10,77,12,77,576,9,77,1,77,1,77, - 5,77,580,8,77,10,77,12,77,583,9,77,1,77,1,77,1,77,1,77,1,77,1,77, - 1,77,5,77,592,8,77,10,77,12,77,595,9,77,1,77,1,77,5,77,599,8,77, - 10,77,12,77,602,9,77,1,77,1,77,1,77,1,77,3,77,608,8,77,1,77,4,77, - 611,8,77,11,77,12,77,612,1,77,1,77,3,77,617,8,77,1,78,1,78,1,78, - 1,79,1,79,5,79,624,8,79,10,79,12,79,627,9,79,1,80,1,80,1,80,1,80, - 1,80,1,80,5,80,635,8,80,10,80,12,80,638,9,80,1,80,1,80,1,81,4,81, - 643,8,81,11,81,12,81,644,1,81,3,81,648,8,81,1,81,1,81,1,82,3,82, - 653,8,82,1,82,1,82,1,431,0,83,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8, - 17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19, - 39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30, - 61,31,63,32,65,33,67,34,69,35,71,36,73,37,75,38,77,39,79,40,81,41, - 83,42,85,43,87,44,89,45,91,46,93,47,95,48,97,49,99,50,101,51,103, - 52,105,53,107,54,109,55,111,56,113,57,115,58,117,59,119,60,121,61, - 123,62,125,63,127,64,129,65,131,0,133,0,135,0,137,0,139,0,141,0, - 143,66,145,67,147,68,149,69,151,70,153,71,155,72,157,73,159,74,161, - 75,163,76,165,77,1,0,33,2,0,73,73,105,105,2,0,78,78,110,110,2,0, - 84,84,116,116,2,0,66,66,98,98,2,0,79,79,111,111,2,0,76,76,108,108, - 2,0,83,83,115,115,2,0,82,82,114,114,2,0,71,71,103,103,2,0,81,81, - 113,113,2,0,85,85,117,117,2,0,70,70,102,102,2,0,65,65,97,97,2,0, - 86,86,118,118,2,0,68,68,100,100,2,0,69,69,101,101,2,0,89,89,121, - 121,2,0,87,87,119,119,2,0,80,80,112,112,2,0,90,90,122,122,2,0,77, - 77,109,109,2,0,67,67,99,99,2,0,88,88,120,120,2,0,72,72,104,104,2, - 0,10,10,13,13,1,0,48,57,2,0,43,43,45,45,2,0,65,70,97,102,1,0,48, - 49,3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,2,0,34,34, - 92,92,3,0,9,10,13,13,32,32,693,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0, - 0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0, - 0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0, - 0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0, - 0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0, - 0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0, - 0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0, - 0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0, - 0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0, - 0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0, - 0,97,1,0,0,0,0,99,1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0, - 0,0,0,107,1,0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115, - 1,0,0,0,0,117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0, - 0,125,1,0,0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,143,1,0,0,0,0,145,1, - 0,0,0,0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0, - 155,1,0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0, - 0,0,0,165,1,0,0,0,1,167,1,0,0,0,3,171,1,0,0,0,5,176,1,0,0,0,7,183, - 1,0,0,0,9,189,1,0,0,0,11,195,1,0,0,0,13,204,1,0,0,0,15,210,1,0,0, - 0,17,215,1,0,0,0,19,222,1,0,0,0,21,224,1,0,0,0,23,226,1,0,0,0,25, - 228,1,0,0,0,27,230,1,0,0,0,29,232,1,0,0,0,31,236,1,0,0,0,33,240, - 1,0,0,0,35,243,1,0,0,0,37,246,1,0,0,0,39,251,1,0,0,0,41,258,1,0, - 0,0,43,265,1,0,0,0,45,272,1,0,0,0,47,276,1,0,0,0,49,280,1,0,0,0, - 51,284,1,0,0,0,53,288,1,0,0,0,55,297,1,0,0,0,57,305,1,0,0,0,59,311, - 1,0,0,0,61,319,1,0,0,0,63,322,1,0,0,0,65,325,1,0,0,0,67,327,1,0, - 0,0,69,330,1,0,0,0,71,332,1,0,0,0,73,335,1,0,0,0,75,338,1,0,0,0, - 77,341,1,0,0,0,79,343,1,0,0,0,81,346,1,0,0,0,83,349,1,0,0,0,85,352, - 1,0,0,0,87,355,1,0,0,0,89,358,1,0,0,0,91,361,1,0,0,0,93,364,1,0, - 0,0,95,366,1,0,0,0,97,370,1,0,0,0,99,374,1,0,0,0,101,381,1,0,0,0, - 103,384,1,0,0,0,105,390,1,0,0,0,107,393,1,0,0,0,109,398,1,0,0,0, - 111,404,1,0,0,0,113,407,1,0,0,0,115,409,1,0,0,0,117,411,1,0,0,0, - 119,413,1,0,0,0,121,415,1,0,0,0,123,417,1,0,0,0,125,419,1,0,0,0, - 127,421,1,0,0,0,129,423,1,0,0,0,131,445,1,0,0,0,133,447,1,0,0,0, - 135,452,1,0,0,0,137,458,1,0,0,0,139,460,1,0,0,0,141,474,1,0,0,0, - 143,479,1,0,0,0,145,482,1,0,0,0,147,513,1,0,0,0,149,515,1,0,0,0, - 151,523,1,0,0,0,153,565,1,0,0,0,155,616,1,0,0,0,157,618,1,0,0,0, - 159,621,1,0,0,0,161,628,1,0,0,0,163,647,1,0,0,0,165,652,1,0,0,0, - 167,168,7,0,0,0,168,169,7,1,0,0,169,170,7,2,0,0,170,2,1,0,0,0,171, - 172,7,3,0,0,172,173,7,4,0,0,173,174,7,4,0,0,174,175,7,5,0,0,175, - 4,1,0,0,0,176,177,7,6,0,0,177,178,7,2,0,0,178,179,7,7,0,0,179,180, - 7,0,0,0,180,181,7,1,0,0,181,182,7,8,0,0,182,6,1,0,0,0,183,184,7, - 9,0,0,184,185,7,10,0,0,185,186,7,3,0,0,186,187,7,0,0,0,187,188,7, - 2,0,0,188,8,1,0,0,0,189,190,7,9,0,0,190,191,7,10,0,0,191,192,7,0, - 0,0,192,193,7,1,0,0,193,194,7,2,0,0,194,10,1,0,0,0,195,196,7,9,0, - 0,196,197,7,10,0,0,197,198,7,6,0,0,198,199,7,2,0,0,199,200,7,7,0, - 0,200,201,7,0,0,0,201,202,7,1,0,0,202,203,7,8,0,0,203,12,1,0,0,0, - 204,205,7,11,0,0,205,206,7,5,0,0,206,207,7,4,0,0,207,208,7,12,0, - 0,208,209,7,2,0,0,209,14,1,0,0,0,210,211,7,13,0,0,211,212,7,4,0, - 0,212,213,7,0,0,0,213,214,7,14,0,0,214,16,1,0,0,0,215,216,7,7,0, - 0,216,217,7,15,0,0,217,218,7,2,0,0,218,219,7,10,0,0,219,220,7,7, - 0,0,220,221,7,1,0,0,221,18,1,0,0,0,222,223,5,42,0,0,223,20,1,0,0, - 0,224,225,5,47,0,0,225,22,1,0,0,0,226,227,5,37,0,0,227,24,1,0,0, - 0,228,229,5,43,0,0,229,26,1,0,0,0,230,231,5,45,0,0,231,28,1,0,0, - 0,232,233,7,1,0,0,233,234,7,4,0,0,234,235,7,2,0,0,235,30,1,0,0,0, - 236,237,7,12,0,0,237,238,7,1,0,0,238,239,7,14,0,0,239,32,1,0,0,0, - 240,241,7,4,0,0,241,242,7,7,0,0,242,34,1,0,0,0,243,244,7,3,0,0,244, - 245,7,16,0,0,245,36,1,0,0,0,246,247,7,6,0,0,247,248,7,17,0,0,248, - 249,7,12,0,0,249,250,7,18,0,0,250,38,1,0,0,0,251,252,7,18,0,0,252, - 253,7,12,0,0,253,254,7,10,0,0,254,255,7,5,0,0,255,256,7,0,0,0,256, - 257,7,16,0,0,257,40,1,0,0,0,258,259,7,18,0,0,259,260,7,12,0,0,260, - 261,7,10,0,0,261,262,7,5,0,0,262,263,7,0,0,0,263,264,7,19,0,0,264, - 42,1,0,0,0,265,266,7,8,0,0,266,267,7,7,0,0,267,268,7,4,0,0,268,269, - 7,13,0,0,269,270,7,15,0,0,270,271,7,7,0,0,271,44,1,0,0,0,272,273, - 7,20,0,0,273,274,7,21,0,0,274,275,7,19,0,0,275,46,1,0,0,0,276,277, - 7,20,0,0,277,278,7,21,0,0,278,279,7,22,0,0,279,48,1,0,0,0,280,281, - 7,20,0,0,281,282,7,21,0,0,282,283,7,16,0,0,283,50,1,0,0,0,284,285, - 7,20,0,0,285,286,7,21,0,0,286,287,7,18,0,0,287,52,1,0,0,0,288,289, - 7,23,0,0,289,290,7,12,0,0,290,291,7,14,0,0,291,292,7,12,0,0,292, - 293,7,20,0,0,293,294,7,12,0,0,294,295,7,7,0,0,295,296,7,14,0,0,296, - 54,1,0,0,0,297,298,7,20,0,0,298,299,7,15,0,0,299,300,7,12,0,0,300, - 301,7,6,0,0,301,302,7,10,0,0,302,303,7,7,0,0,303,304,7,15,0,0,304, - 56,1,0,0,0,305,306,7,18,0,0,306,307,7,7,0,0,307,308,7,0,0,0,308, - 309,7,1,0,0,309,310,7,2,0,0,310,58,1,0,0,0,311,312,7,3,0,0,312,313, - 7,12,0,0,313,314,7,7,0,0,314,315,7,7,0,0,315,316,7,0,0,0,316,317, - 7,15,0,0,317,318,7,7,0,0,318,60,1,0,0,0,319,320,5,61,0,0,320,321, - 5,61,0,0,321,62,1,0,0,0,322,323,5,33,0,0,323,324,5,61,0,0,324,64, - 1,0,0,0,325,326,5,62,0,0,326,66,1,0,0,0,327,328,5,62,0,0,328,329, - 5,61,0,0,329,68,1,0,0,0,330,331,5,60,0,0,331,70,1,0,0,0,332,333, - 5,60,0,0,333,334,5,61,0,0,334,72,1,0,0,0,335,336,5,60,0,0,336,337, - 5,60,0,0,337,74,1,0,0,0,338,339,5,62,0,0,339,340,5,62,0,0,340,76, - 1,0,0,0,341,342,5,61,0,0,342,78,1,0,0,0,343,344,5,43,0,0,344,345, - 5,43,0,0,345,80,1,0,0,0,346,347,5,45,0,0,347,348,5,45,0,0,348,82, - 1,0,0,0,349,350,5,43,0,0,350,351,5,61,0,0,351,84,1,0,0,0,352,353, - 5,45,0,0,353,354,5,61,0,0,354,86,1,0,0,0,355,356,5,42,0,0,356,357, - 5,61,0,0,357,88,1,0,0,0,358,359,5,47,0,0,359,360,5,61,0,0,360,90, - 1,0,0,0,361,362,5,37,0,0,362,363,5,61,0,0,363,92,1,0,0,0,364,365, - 5,59,0,0,365,94,1,0,0,0,366,367,7,13,0,0,367,368,7,12,0,0,368,369, - 7,7,0,0,369,96,1,0,0,0,370,371,7,11,0,0,371,372,7,4,0,0,372,373, - 7,7,0,0,373,98,1,0,0,0,374,375,7,6,0,0,375,376,7,15,0,0,376,377, - 7,12,0,0,377,378,7,7,0,0,378,379,7,21,0,0,379,380,7,23,0,0,380,100, - 1,0,0,0,381,382,7,0,0,0,382,383,7,1,0,0,383,102,1,0,0,0,384,385, - 7,17,0,0,385,386,7,23,0,0,386,387,7,15,0,0,387,388,7,7,0,0,388,389, - 7,15,0,0,389,104,1,0,0,0,390,391,7,0,0,0,391,392,7,11,0,0,392,106, - 1,0,0,0,393,394,7,15,0,0,394,395,7,5,0,0,395,396,7,6,0,0,396,397, - 7,15,0,0,397,108,1,0,0,0,398,399,7,17,0,0,399,400,7,23,0,0,400,401, - 7,0,0,0,401,402,7,5,0,0,402,403,7,15,0,0,403,110,1,0,0,0,404,405, - 7,14,0,0,405,406,7,4,0,0,406,112,1,0,0,0,407,408,5,123,0,0,408,114, - 1,0,0,0,409,410,5,125,0,0,410,116,1,0,0,0,411,412,5,40,0,0,412,118, - 1,0,0,0,413,414,5,41,0,0,414,120,1,0,0,0,415,416,5,91,0,0,416,122, - 1,0,0,0,417,418,5,93,0,0,418,124,1,0,0,0,419,420,5,46,0,0,420,126, - 1,0,0,0,421,422,5,34,0,0,422,128,1,0,0,0,423,424,5,44,0,0,424,130, - 1,0,0,0,425,426,5,47,0,0,426,427,5,42,0,0,427,431,1,0,0,0,428,430, - 9,0,0,0,429,428,1,0,0,0,430,433,1,0,0,0,431,432,1,0,0,0,431,429, - 1,0,0,0,432,434,1,0,0,0,433,431,1,0,0,0,434,435,5,42,0,0,435,446, - 5,47,0,0,436,437,5,47,0,0,437,438,5,47,0,0,438,442,1,0,0,0,439,441, - 8,24,0,0,440,439,1,0,0,0,441,444,1,0,0,0,442,440,1,0,0,0,442,443, - 1,0,0,0,443,446,1,0,0,0,444,442,1,0,0,0,445,425,1,0,0,0,445,436, - 1,0,0,0,446,132,1,0,0,0,447,448,7,2,0,0,448,449,7,7,0,0,449,450, - 7,10,0,0,450,451,7,15,0,0,451,134,1,0,0,0,452,453,7,11,0,0,453,454, - 7,12,0,0,454,455,7,5,0,0,455,456,7,6,0,0,456,457,7,15,0,0,457,136, - 1,0,0,0,458,459,7,25,0,0,459,138,1,0,0,0,460,461,7,26,0,0,461,140, - 1,0,0,0,462,463,5,124,0,0,463,464,5,48,0,0,464,475,5,62,0,0,465, - 466,5,124,0,0,466,467,5,49,0,0,467,475,5,62,0,0,468,469,5,124,0, - 0,469,470,5,43,0,0,470,475,5,62,0,0,471,472,5,124,0,0,472,473,5, - 45,0,0,473,475,5,62,0,0,474,462,1,0,0,0,474,465,1,0,0,0,474,468, - 1,0,0,0,474,471,1,0,0,0,475,142,1,0,0,0,476,480,3,133,66,0,477,480, - 3,135,67,0,478,480,2,48,49,0,479,476,1,0,0,0,479,477,1,0,0,0,479, - 478,1,0,0,0,480,144,1,0,0,0,481,483,3,139,69,0,482,481,1,0,0,0,482, - 483,1,0,0,0,483,485,1,0,0,0,484,486,3,137,68,0,485,484,1,0,0,0,486, - 487,1,0,0,0,487,485,1,0,0,0,487,488,1,0,0,0,488,146,1,0,0,0,489, - 491,3,139,69,0,490,489,1,0,0,0,490,491,1,0,0,0,491,493,1,0,0,0,492, - 494,3,137,68,0,493,492,1,0,0,0,494,495,1,0,0,0,495,493,1,0,0,0,495, - 496,1,0,0,0,496,497,1,0,0,0,497,501,5,46,0,0,498,500,3,137,68,0, - 499,498,1,0,0,0,500,503,1,0,0,0,501,499,1,0,0,0,501,502,1,0,0,0, - 502,514,1,0,0,0,503,501,1,0,0,0,504,506,3,139,69,0,505,504,1,0,0, - 0,505,506,1,0,0,0,506,507,1,0,0,0,507,509,5,46,0,0,508,510,3,137, - 68,0,509,508,1,0,0,0,510,511,1,0,0,0,511,509,1,0,0,0,511,512,1,0, - 0,0,512,514,1,0,0,0,513,490,1,0,0,0,513,505,1,0,0,0,514,148,1,0, - 0,0,515,516,5,48,0,0,516,519,7,22,0,0,517,520,7,27,0,0,518,520,3, - 137,68,0,519,517,1,0,0,0,519,518,1,0,0,0,520,521,1,0,0,0,521,519, - 1,0,0,0,521,522,1,0,0,0,522,150,1,0,0,0,523,524,5,48,0,0,524,526, - 7,3,0,0,525,527,7,28,0,0,526,525,1,0,0,0,527,528,1,0,0,0,528,526, - 1,0,0,0,528,529,1,0,0,0,529,152,1,0,0,0,530,533,3,121,60,0,531,534, - 3,143,71,0,532,534,2,48,49,0,533,531,1,0,0,0,533,532,1,0,0,0,534, - 546,1,0,0,0,535,539,3,129,64,0,536,538,5,32,0,0,537,536,1,0,0,0, - 538,541,1,0,0,0,539,537,1,0,0,0,539,540,1,0,0,0,540,544,1,0,0,0, - 541,539,1,0,0,0,542,545,3,143,71,0,543,545,2,48,49,0,544,542,1,0, - 0,0,544,543,1,0,0,0,545,547,1,0,0,0,546,535,1,0,0,0,546,547,1,0, - 0,0,547,548,1,0,0,0,548,549,3,123,61,0,549,550,7,9,0,0,550,566,1, - 0,0,0,551,552,3,147,73,0,552,553,3,129,64,0,553,554,3,147,73,0,554, - 555,7,9,0,0,555,566,1,0,0,0,556,566,3,141,70,0,557,559,3,139,69, - 0,558,557,1,0,0,0,558,559,1,0,0,0,559,562,1,0,0,0,560,563,3,143, - 71,0,561,563,2,48,49,0,562,560,1,0,0,0,562,561,1,0,0,0,563,564,1, - 0,0,0,564,566,7,9,0,0,565,530,1,0,0,0,565,551,1,0,0,0,565,556,1, - 0,0,0,565,558,1,0,0,0,566,154,1,0,0,0,567,617,3,153,76,0,568,569, - 3,121,60,0,569,581,3,153,76,0,570,574,3,129,64,0,571,573,5,32,0, - 0,572,571,1,0,0,0,573,576,1,0,0,0,574,572,1,0,0,0,574,575,1,0,0, - 0,575,577,1,0,0,0,576,574,1,0,0,0,577,578,3,153,76,0,578,580,1,0, - 0,0,579,570,1,0,0,0,580,583,1,0,0,0,581,579,1,0,0,0,581,582,1,0, - 0,0,582,584,1,0,0,0,583,581,1,0,0,0,584,585,3,123,61,0,585,586,7, - 9,0,0,586,617,1,0,0,0,587,588,3,121,60,0,588,600,3,145,72,0,589, - 593,3,129,64,0,590,592,5,32,0,0,591,590,1,0,0,0,592,595,1,0,0,0, - 593,591,1,0,0,0,593,594,1,0,0,0,594,596,1,0,0,0,595,593,1,0,0,0, - 596,597,3,145,72,0,597,599,1,0,0,0,598,589,1,0,0,0,599,602,1,0,0, - 0,600,598,1,0,0,0,600,601,1,0,0,0,601,603,1,0,0,0,602,600,1,0,0, - 0,603,604,3,123,61,0,604,605,7,9,0,0,605,617,1,0,0,0,606,608,3,139, - 69,0,607,606,1,0,0,0,607,608,1,0,0,0,608,610,1,0,0,0,609,611,3,137, - 68,0,610,609,1,0,0,0,611,612,1,0,0,0,612,610,1,0,0,0,612,613,1,0, - 0,0,613,614,1,0,0,0,614,615,7,9,0,0,615,617,1,0,0,0,616,567,1,0, - 0,0,616,568,1,0,0,0,616,587,1,0,0,0,616,607,1,0,0,0,617,156,1,0, - 0,0,618,619,3,161,80,0,619,620,7,9,0,0,620,158,1,0,0,0,621,625,7, - 29,0,0,622,624,7,30,0,0,623,622,1,0,0,0,624,627,1,0,0,0,625,623, - 1,0,0,0,625,626,1,0,0,0,626,160,1,0,0,0,627,625,1,0,0,0,628,636, - 5,34,0,0,629,630,5,92,0,0,630,635,9,0,0,0,631,632,5,34,0,0,632,635, - 5,34,0,0,633,635,8,31,0,0,634,629,1,0,0,0,634,631,1,0,0,0,634,633, - 1,0,0,0,635,638,1,0,0,0,636,634,1,0,0,0,636,637,1,0,0,0,637,639, - 1,0,0,0,638,636,1,0,0,0,639,640,5,34,0,0,640,162,1,0,0,0,641,643, - 7,32,0,0,642,641,1,0,0,0,643,644,1,0,0,0,644,642,1,0,0,0,644,645, - 1,0,0,0,645,648,1,0,0,0,646,648,3,131,65,0,647,642,1,0,0,0,647,646, - 1,0,0,0,648,649,1,0,0,0,649,650,6,81,0,0,650,164,1,0,0,0,651,653, - 5,13,0,0,652,651,1,0,0,0,652,653,1,0,0,0,653,654,1,0,0,0,654,655, - 5,10,0,0,655,166,1,0,0,0,37,0,431,442,445,474,479,482,487,490,495, - 501,505,511,513,519,521,528,533,539,544,546,558,562,565,574,581, - 593,600,607,612,616,625,634,636,644,647,652,1,6,0,0 + 78,7,78,2,79,7,79,2,80,7,80,2,81,7,81,2,82,7,82,2,83,7,83,2,84,7, + 84,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,3,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1, + 5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1, + 7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,10,1,10,1,11,1,11,1,12,1, + 12,1,13,1,13,1,14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,16,1,16,1, + 16,1,17,1,17,1,17,1,18,1,18,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1, + 19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1, + 21,1,21,1,21,1,21,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,24,1, + 24,1,24,1,24,1,25,1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,26,1, + 26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1, + 28,1,28,1,28,1,28,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,30,1, + 30,1,30,1,30,1,30,1,30,1,30,1,30,1,31,1,31,1,31,1,32,1,32,1,32,1, + 33,1,33,1,34,1,34,1,34,1,35,1,35,1,36,1,36,1,36,1,37,1,37,1,37,1, + 38,1,38,1,38,1,39,1,39,1,40,1,40,1,40,1,41,1,41,1,41,1,42,1,42,1, + 42,1,43,1,43,1,43,1,44,1,44,1,44,1,45,1,45,1,45,1,46,1,46,1,46,1, + 47,1,47,1,48,1,48,1,48,1,48,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1, + 50,1,50,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,52,1, + 52,1,52,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,55,1,55,1, + 55,1,55,1,55,1,56,1,56,1,56,1,56,1,56,1,56,1,57,1,57,1,57,1,58,1, + 58,1,59,1,59,1,60,1,60,1,61,1,61,1,62,1,62,1,63,1,63,1,64,1,64,1, + 65,1,65,1,66,1,66,1,67,1,67,1,67,1,67,5,67,450,8,67,10,67,12,67, + 453,9,67,1,67,1,67,1,67,1,67,1,67,1,67,5,67,461,8,67,10,67,12,67, + 464,9,67,3,67,466,8,67,1,68,1,68,1,68,1,68,1,68,1,69,1,69,1,69,1, + 69,1,69,1,69,1,70,1,70,1,71,1,71,1,72,1,72,1,72,1,72,1,72,1,72,1, + 72,1,72,1,72,1,72,1,72,1,72,3,72,495,8,72,1,73,1,73,1,73,3,73,500, + 8,73,1,74,3,74,503,8,74,1,74,4,74,506,8,74,11,74,12,74,507,1,75, + 3,75,511,8,75,1,75,4,75,514,8,75,11,75,12,75,515,1,75,1,75,5,75, + 520,8,75,10,75,12,75,523,9,75,1,75,3,75,526,8,75,1,75,1,75,4,75, + 530,8,75,11,75,12,75,531,3,75,534,8,75,1,76,1,76,1,76,1,76,4,76, + 540,8,76,11,76,12,76,541,1,77,1,77,1,77,4,77,547,8,77,11,77,12,77, + 548,1,78,1,78,1,78,3,78,554,8,78,1,78,1,78,5,78,558,8,78,10,78,12, + 78,561,9,78,1,78,1,78,3,78,565,8,78,3,78,567,8,78,1,78,1,78,1,78, + 1,78,1,78,1,78,1,78,1,78,1,78,1,78,3,78,579,8,78,1,78,1,78,3,78, + 583,8,78,1,78,3,78,586,8,78,1,79,1,79,1,79,1,79,1,79,5,79,593,8, + 79,10,79,12,79,596,9,79,1,79,1,79,5,79,600,8,79,10,79,12,79,603, + 9,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,5,79,612,8,79,10,79,12,79, + 615,9,79,1,79,1,79,5,79,619,8,79,10,79,12,79,622,9,79,1,79,1,79, + 1,79,1,79,3,79,628,8,79,1,79,4,79,631,8,79,11,79,12,79,632,1,79, + 1,79,3,79,637,8,79,1,80,1,80,1,80,1,81,1,81,5,81,644,8,81,10,81, + 12,81,647,9,81,1,82,1,82,1,82,1,82,1,82,1,82,5,82,655,8,82,10,82, + 12,82,658,9,82,1,82,1,82,1,83,4,83,663,8,83,11,83,12,83,664,1,83, + 3,83,668,8,83,1,83,1,83,1,84,3,84,673,8,84,1,84,1,84,1,451,0,85, + 1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13, + 27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24, + 49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35, + 71,36,73,37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46, + 93,47,95,48,97,49,99,50,101,51,103,52,105,53,107,54,109,55,111,56, + 113,57,115,58,117,59,119,60,121,61,123,62,125,63,127,64,129,65,131, + 66,133,67,135,0,137,0,139,0,141,0,143,0,145,0,147,68,149,69,151, + 70,153,71,155,72,157,73,159,74,161,75,163,76,165,77,167,78,169,79, + 1,0,33,2,0,73,73,105,105,2,0,78,78,110,110,2,0,84,84,116,116,2,0, + 66,66,98,98,2,0,79,79,111,111,2,0,76,76,108,108,2,0,83,83,115,115, + 2,0,82,82,114,114,2,0,71,71,103,103,2,0,81,81,113,113,2,0,85,85, + 117,117,2,0,70,70,102,102,2,0,65,65,97,97,2,0,86,86,118,118,2,0, + 68,68,100,100,2,0,69,69,101,101,2,0,89,89,121,121,2,0,87,87,119, + 119,2,0,80,80,112,112,2,0,90,90,122,122,2,0,77,77,109,109,2,0,67, + 67,99,99,2,0,88,88,120,120,2,0,72,72,104,104,2,0,10,10,13,13,1,0, + 48,57,2,0,43,43,45,45,2,0,65,70,97,102,1,0,48,49,3,0,65,90,95,95, + 97,122,4,0,48,57,65,90,95,95,97,122,2,0,34,34,92,92,3,0,9,10,13, + 13,32,32,713,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9, + 1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19, + 1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29, + 1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39, + 1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49, + 1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59, + 1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69, + 1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79, + 1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89, + 1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0,0,0,99, + 1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107,1,0,0,0, + 0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0,117,1, + 0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1,0,0,0,0, + 127,1,0,0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0,0,0,147,1,0, + 0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0,155,1,0,0,0,0,157, + 1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,0,165,1,0,0,0, + 0,167,1,0,0,0,0,169,1,0,0,0,1,171,1,0,0,0,3,175,1,0,0,0,5,180,1, + 0,0,0,7,187,1,0,0,0,9,193,1,0,0,0,11,199,1,0,0,0,13,208,1,0,0,0, + 15,214,1,0,0,0,17,219,1,0,0,0,19,226,1,0,0,0,21,228,1,0,0,0,23,230, + 1,0,0,0,25,232,1,0,0,0,27,234,1,0,0,0,29,236,1,0,0,0,31,240,1,0, + 0,0,33,244,1,0,0,0,35,247,1,0,0,0,37,250,1,0,0,0,39,255,1,0,0,0, + 41,262,1,0,0,0,43,269,1,0,0,0,45,276,1,0,0,0,47,280,1,0,0,0,49,284, + 1,0,0,0,51,288,1,0,0,0,53,292,1,0,0,0,55,301,1,0,0,0,57,309,1,0, + 0,0,59,315,1,0,0,0,61,323,1,0,0,0,63,331,1,0,0,0,65,334,1,0,0,0, + 67,337,1,0,0,0,69,339,1,0,0,0,71,342,1,0,0,0,73,344,1,0,0,0,75,347, + 1,0,0,0,77,350,1,0,0,0,79,353,1,0,0,0,81,355,1,0,0,0,83,358,1,0, + 0,0,85,361,1,0,0,0,87,364,1,0,0,0,89,367,1,0,0,0,91,370,1,0,0,0, + 93,373,1,0,0,0,95,376,1,0,0,0,97,378,1,0,0,0,99,382,1,0,0,0,101, + 386,1,0,0,0,103,394,1,0,0,0,105,401,1,0,0,0,107,404,1,0,0,0,109, + 410,1,0,0,0,111,413,1,0,0,0,113,418,1,0,0,0,115,424,1,0,0,0,117, + 427,1,0,0,0,119,429,1,0,0,0,121,431,1,0,0,0,123,433,1,0,0,0,125, + 435,1,0,0,0,127,437,1,0,0,0,129,439,1,0,0,0,131,441,1,0,0,0,133, + 443,1,0,0,0,135,465,1,0,0,0,137,467,1,0,0,0,139,472,1,0,0,0,141, + 478,1,0,0,0,143,480,1,0,0,0,145,494,1,0,0,0,147,499,1,0,0,0,149, + 502,1,0,0,0,151,533,1,0,0,0,153,535,1,0,0,0,155,543,1,0,0,0,157, + 585,1,0,0,0,159,636,1,0,0,0,161,638,1,0,0,0,163,641,1,0,0,0,165, + 648,1,0,0,0,167,667,1,0,0,0,169,672,1,0,0,0,171,172,7,0,0,0,172, + 173,7,1,0,0,173,174,7,2,0,0,174,2,1,0,0,0,175,176,7,3,0,0,176,177, + 7,4,0,0,177,178,7,4,0,0,178,179,7,5,0,0,179,4,1,0,0,0,180,181,7, + 6,0,0,181,182,7,2,0,0,182,183,7,7,0,0,183,184,7,0,0,0,184,185,7, + 1,0,0,185,186,7,8,0,0,186,6,1,0,0,0,187,188,7,9,0,0,188,189,7,10, + 0,0,189,190,7,3,0,0,190,191,7,0,0,0,191,192,7,2,0,0,192,8,1,0,0, + 0,193,194,7,9,0,0,194,195,7,10,0,0,195,196,7,0,0,0,196,197,7,1,0, + 0,197,198,7,2,0,0,198,10,1,0,0,0,199,200,7,9,0,0,200,201,7,10,0, + 0,201,202,7,6,0,0,202,203,7,2,0,0,203,204,7,7,0,0,204,205,7,0,0, + 0,205,206,7,1,0,0,206,207,7,8,0,0,207,12,1,0,0,0,208,209,7,11,0, + 0,209,210,7,5,0,0,210,211,7,4,0,0,211,212,7,12,0,0,212,213,7,2,0, + 0,213,14,1,0,0,0,214,215,7,13,0,0,215,216,7,4,0,0,216,217,7,0,0, + 0,217,218,7,14,0,0,218,16,1,0,0,0,219,220,7,7,0,0,220,221,7,15,0, + 0,221,222,7,2,0,0,222,223,7,10,0,0,223,224,7,7,0,0,224,225,7,1,0, + 0,225,18,1,0,0,0,226,227,5,42,0,0,227,20,1,0,0,0,228,229,5,47,0, + 0,229,22,1,0,0,0,230,231,5,37,0,0,231,24,1,0,0,0,232,233,5,43,0, + 0,233,26,1,0,0,0,234,235,5,45,0,0,235,28,1,0,0,0,236,237,7,1,0,0, + 237,238,7,4,0,0,238,239,7,2,0,0,239,30,1,0,0,0,240,241,7,12,0,0, + 241,242,7,1,0,0,242,243,7,14,0,0,243,32,1,0,0,0,244,245,7,4,0,0, + 245,246,7,7,0,0,246,34,1,0,0,0,247,248,7,3,0,0,248,249,7,16,0,0, + 249,36,1,0,0,0,250,251,7,6,0,0,251,252,7,17,0,0,252,253,7,12,0,0, + 253,254,7,18,0,0,254,38,1,0,0,0,255,256,7,18,0,0,256,257,7,12,0, + 0,257,258,7,10,0,0,258,259,7,5,0,0,259,260,7,0,0,0,260,261,7,16, + 0,0,261,40,1,0,0,0,262,263,7,18,0,0,263,264,7,12,0,0,264,265,7,10, + 0,0,265,266,7,5,0,0,266,267,7,0,0,0,267,268,7,19,0,0,268,42,1,0, + 0,0,269,270,7,8,0,0,270,271,7,7,0,0,271,272,7,4,0,0,272,273,7,13, + 0,0,273,274,7,15,0,0,274,275,7,7,0,0,275,44,1,0,0,0,276,277,7,20, + 0,0,277,278,7,21,0,0,278,279,7,19,0,0,279,46,1,0,0,0,280,281,7,20, + 0,0,281,282,7,21,0,0,282,283,7,22,0,0,283,48,1,0,0,0,284,285,7,20, + 0,0,285,286,7,21,0,0,286,287,7,16,0,0,287,50,1,0,0,0,288,289,7,20, + 0,0,289,290,7,21,0,0,290,291,7,18,0,0,291,52,1,0,0,0,292,293,7,23, + 0,0,293,294,7,12,0,0,294,295,7,14,0,0,295,296,7,12,0,0,296,297,7, + 20,0,0,297,298,7,12,0,0,298,299,7,7,0,0,299,300,7,14,0,0,300,54, + 1,0,0,0,301,302,7,20,0,0,302,303,7,15,0,0,303,304,7,12,0,0,304,305, + 7,6,0,0,305,306,7,10,0,0,306,307,7,7,0,0,307,308,7,15,0,0,308,56, + 1,0,0,0,309,310,7,18,0,0,310,311,7,7,0,0,311,312,7,0,0,0,312,313, + 7,1,0,0,313,314,7,2,0,0,314,58,1,0,0,0,315,316,7,18,0,0,316,317, + 7,7,0,0,317,318,7,0,0,0,318,319,7,1,0,0,319,320,7,2,0,0,320,321, + 7,5,0,0,321,322,7,1,0,0,322,60,1,0,0,0,323,324,7,3,0,0,324,325,7, + 12,0,0,325,326,7,7,0,0,326,327,7,7,0,0,327,328,7,0,0,0,328,329,7, + 15,0,0,329,330,7,7,0,0,330,62,1,0,0,0,331,332,5,61,0,0,332,333,5, + 61,0,0,333,64,1,0,0,0,334,335,5,33,0,0,335,336,5,61,0,0,336,66,1, + 0,0,0,337,338,5,62,0,0,338,68,1,0,0,0,339,340,5,62,0,0,340,341,5, + 61,0,0,341,70,1,0,0,0,342,343,5,60,0,0,343,72,1,0,0,0,344,345,5, + 60,0,0,345,346,5,61,0,0,346,74,1,0,0,0,347,348,5,60,0,0,348,349, + 5,60,0,0,349,76,1,0,0,0,350,351,5,62,0,0,351,352,5,62,0,0,352,78, + 1,0,0,0,353,354,5,61,0,0,354,80,1,0,0,0,355,356,5,43,0,0,356,357, + 5,43,0,0,357,82,1,0,0,0,358,359,5,45,0,0,359,360,5,45,0,0,360,84, + 1,0,0,0,361,362,5,43,0,0,362,363,5,61,0,0,363,86,1,0,0,0,364,365, + 5,45,0,0,365,366,5,61,0,0,366,88,1,0,0,0,367,368,5,42,0,0,368,369, + 5,61,0,0,369,90,1,0,0,0,370,371,5,47,0,0,371,372,5,61,0,0,372,92, + 1,0,0,0,373,374,5,37,0,0,374,375,5,61,0,0,375,94,1,0,0,0,376,377, + 5,59,0,0,377,96,1,0,0,0,378,379,7,13,0,0,379,380,7,12,0,0,380,381, + 7,7,0,0,381,98,1,0,0,0,382,383,7,11,0,0,383,384,7,4,0,0,384,385, + 7,7,0,0,385,100,1,0,0,0,386,387,7,11,0,0,387,388,7,4,0,0,388,389, + 7,7,0,0,389,390,7,15,0,0,390,391,7,12,0,0,391,392,7,21,0,0,392,393, + 7,23,0,0,393,102,1,0,0,0,394,395,7,6,0,0,395,396,7,15,0,0,396,397, + 7,12,0,0,397,398,7,7,0,0,398,399,7,21,0,0,399,400,7,23,0,0,400,104, + 1,0,0,0,401,402,7,0,0,0,402,403,7,1,0,0,403,106,1,0,0,0,404,405, + 7,17,0,0,405,406,7,23,0,0,406,407,7,15,0,0,407,408,7,7,0,0,408,409, + 7,15,0,0,409,108,1,0,0,0,410,411,7,0,0,0,411,412,7,11,0,0,412,110, + 1,0,0,0,413,414,7,15,0,0,414,415,7,5,0,0,415,416,7,6,0,0,416,417, + 7,15,0,0,417,112,1,0,0,0,418,419,7,17,0,0,419,420,7,23,0,0,420,421, + 7,0,0,0,421,422,7,5,0,0,422,423,7,15,0,0,423,114,1,0,0,0,424,425, + 7,14,0,0,425,426,7,4,0,0,426,116,1,0,0,0,427,428,5,123,0,0,428,118, + 1,0,0,0,429,430,5,125,0,0,430,120,1,0,0,0,431,432,5,40,0,0,432,122, + 1,0,0,0,433,434,5,41,0,0,434,124,1,0,0,0,435,436,5,91,0,0,436,126, + 1,0,0,0,437,438,5,93,0,0,438,128,1,0,0,0,439,440,5,46,0,0,440,130, + 1,0,0,0,441,442,5,34,0,0,442,132,1,0,0,0,443,444,5,44,0,0,444,134, + 1,0,0,0,445,446,5,47,0,0,446,447,5,42,0,0,447,451,1,0,0,0,448,450, + 9,0,0,0,449,448,1,0,0,0,450,453,1,0,0,0,451,452,1,0,0,0,451,449, + 1,0,0,0,452,454,1,0,0,0,453,451,1,0,0,0,454,455,5,42,0,0,455,466, + 5,47,0,0,456,457,5,47,0,0,457,458,5,47,0,0,458,462,1,0,0,0,459,461, + 8,24,0,0,460,459,1,0,0,0,461,464,1,0,0,0,462,460,1,0,0,0,462,463, + 1,0,0,0,463,466,1,0,0,0,464,462,1,0,0,0,465,445,1,0,0,0,465,456, + 1,0,0,0,466,136,1,0,0,0,467,468,7,2,0,0,468,469,7,7,0,0,469,470, + 7,10,0,0,470,471,7,15,0,0,471,138,1,0,0,0,472,473,7,11,0,0,473,474, + 7,12,0,0,474,475,7,5,0,0,475,476,7,6,0,0,476,477,7,15,0,0,477,140, + 1,0,0,0,478,479,7,25,0,0,479,142,1,0,0,0,480,481,7,26,0,0,481,144, + 1,0,0,0,482,483,5,124,0,0,483,484,5,48,0,0,484,495,5,62,0,0,485, + 486,5,124,0,0,486,487,5,49,0,0,487,495,5,62,0,0,488,489,5,124,0, + 0,489,490,5,43,0,0,490,495,5,62,0,0,491,492,5,124,0,0,492,493,5, + 45,0,0,493,495,5,62,0,0,494,482,1,0,0,0,494,485,1,0,0,0,494,488, + 1,0,0,0,494,491,1,0,0,0,495,146,1,0,0,0,496,500,3,137,68,0,497,500, + 3,139,69,0,498,500,2,48,49,0,499,496,1,0,0,0,499,497,1,0,0,0,499, + 498,1,0,0,0,500,148,1,0,0,0,501,503,3,143,71,0,502,501,1,0,0,0,502, + 503,1,0,0,0,503,505,1,0,0,0,504,506,3,141,70,0,505,504,1,0,0,0,506, + 507,1,0,0,0,507,505,1,0,0,0,507,508,1,0,0,0,508,150,1,0,0,0,509, + 511,3,143,71,0,510,509,1,0,0,0,510,511,1,0,0,0,511,513,1,0,0,0,512, + 514,3,141,70,0,513,512,1,0,0,0,514,515,1,0,0,0,515,513,1,0,0,0,515, + 516,1,0,0,0,516,517,1,0,0,0,517,521,5,46,0,0,518,520,3,141,70,0, + 519,518,1,0,0,0,520,523,1,0,0,0,521,519,1,0,0,0,521,522,1,0,0,0, + 522,534,1,0,0,0,523,521,1,0,0,0,524,526,3,143,71,0,525,524,1,0,0, + 0,525,526,1,0,0,0,526,527,1,0,0,0,527,529,5,46,0,0,528,530,3,141, + 70,0,529,528,1,0,0,0,530,531,1,0,0,0,531,529,1,0,0,0,531,532,1,0, + 0,0,532,534,1,0,0,0,533,510,1,0,0,0,533,525,1,0,0,0,534,152,1,0, + 0,0,535,536,5,48,0,0,536,539,7,22,0,0,537,540,7,27,0,0,538,540,3, + 141,70,0,539,537,1,0,0,0,539,538,1,0,0,0,540,541,1,0,0,0,541,539, + 1,0,0,0,541,542,1,0,0,0,542,154,1,0,0,0,543,544,5,48,0,0,544,546, + 7,3,0,0,545,547,7,28,0,0,546,545,1,0,0,0,547,548,1,0,0,0,548,546, + 1,0,0,0,548,549,1,0,0,0,549,156,1,0,0,0,550,553,3,125,62,0,551,554, + 3,147,73,0,552,554,2,48,49,0,553,551,1,0,0,0,553,552,1,0,0,0,554, + 566,1,0,0,0,555,559,3,133,66,0,556,558,5,32,0,0,557,556,1,0,0,0, + 558,561,1,0,0,0,559,557,1,0,0,0,559,560,1,0,0,0,560,564,1,0,0,0, + 561,559,1,0,0,0,562,565,3,147,73,0,563,565,2,48,49,0,564,562,1,0, + 0,0,564,563,1,0,0,0,565,567,1,0,0,0,566,555,1,0,0,0,566,567,1,0, + 0,0,567,568,1,0,0,0,568,569,3,127,63,0,569,570,7,9,0,0,570,586,1, + 0,0,0,571,572,3,151,75,0,572,573,3,133,66,0,573,574,3,151,75,0,574, + 575,7,9,0,0,575,586,1,0,0,0,576,586,3,145,72,0,577,579,3,143,71, + 0,578,577,1,0,0,0,578,579,1,0,0,0,579,582,1,0,0,0,580,583,3,147, + 73,0,581,583,2,48,49,0,582,580,1,0,0,0,582,581,1,0,0,0,583,584,1, + 0,0,0,584,586,7,9,0,0,585,550,1,0,0,0,585,571,1,0,0,0,585,576,1, + 0,0,0,585,578,1,0,0,0,586,158,1,0,0,0,587,637,3,157,78,0,588,589, + 3,125,62,0,589,601,3,157,78,0,590,594,3,133,66,0,591,593,5,32,0, + 0,592,591,1,0,0,0,593,596,1,0,0,0,594,592,1,0,0,0,594,595,1,0,0, + 0,595,597,1,0,0,0,596,594,1,0,0,0,597,598,3,157,78,0,598,600,1,0, + 0,0,599,590,1,0,0,0,600,603,1,0,0,0,601,599,1,0,0,0,601,602,1,0, + 0,0,602,604,1,0,0,0,603,601,1,0,0,0,604,605,3,127,63,0,605,606,7, + 9,0,0,606,637,1,0,0,0,607,608,3,125,62,0,608,620,3,149,74,0,609, + 613,3,133,66,0,610,612,5,32,0,0,611,610,1,0,0,0,612,615,1,0,0,0, + 613,611,1,0,0,0,613,614,1,0,0,0,614,616,1,0,0,0,615,613,1,0,0,0, + 616,617,3,149,74,0,617,619,1,0,0,0,618,609,1,0,0,0,619,622,1,0,0, + 0,620,618,1,0,0,0,620,621,1,0,0,0,621,623,1,0,0,0,622,620,1,0,0, + 0,623,624,3,127,63,0,624,625,7,9,0,0,625,637,1,0,0,0,626,628,3,143, + 71,0,627,626,1,0,0,0,627,628,1,0,0,0,628,630,1,0,0,0,629,631,3,141, + 70,0,630,629,1,0,0,0,631,632,1,0,0,0,632,630,1,0,0,0,632,633,1,0, + 0,0,633,634,1,0,0,0,634,635,7,9,0,0,635,637,1,0,0,0,636,587,1,0, + 0,0,636,588,1,0,0,0,636,607,1,0,0,0,636,627,1,0,0,0,637,160,1,0, + 0,0,638,639,3,165,82,0,639,640,7,9,0,0,640,162,1,0,0,0,641,645,7, + 29,0,0,642,644,7,30,0,0,643,642,1,0,0,0,644,647,1,0,0,0,645,643, + 1,0,0,0,645,646,1,0,0,0,646,164,1,0,0,0,647,645,1,0,0,0,648,656, + 5,34,0,0,649,650,5,92,0,0,650,655,9,0,0,0,651,652,5,34,0,0,652,655, + 5,34,0,0,653,655,8,31,0,0,654,649,1,0,0,0,654,651,1,0,0,0,654,653, + 1,0,0,0,655,658,1,0,0,0,656,654,1,0,0,0,656,657,1,0,0,0,657,659, + 1,0,0,0,658,656,1,0,0,0,659,660,5,34,0,0,660,166,1,0,0,0,661,663, + 7,32,0,0,662,661,1,0,0,0,663,664,1,0,0,0,664,662,1,0,0,0,664,665, + 1,0,0,0,665,668,1,0,0,0,666,668,3,135,67,0,667,662,1,0,0,0,667,666, + 1,0,0,0,668,669,1,0,0,0,669,670,6,83,0,0,670,168,1,0,0,0,671,673, + 5,13,0,0,672,671,1,0,0,0,672,673,1,0,0,0,673,674,1,0,0,0,674,675, + 5,10,0,0,675,170,1,0,0,0,37,0,451,462,465,494,499,502,507,510,515, + 521,525,531,533,539,541,548,553,559,564,566,578,582,585,594,601, + 613,620,627,632,636,645,654,656,664,667,672,1,6,0,0 ] class qutes_lexer(Lexer): @@ -290,54 +297,56 @@ class qutes_lexer(Lexer): HADAMARD = 27 MEASURE = 28 PRINT = 29 - BARRIER = 30 - EQUAL = 31 - NOT_EQUAL = 32 - GREATER = 33 - GREATEREQUAL = 34 - LOWER = 35 - LOWEREQUAL = 36 - LSHIFT = 37 - RSHIFT = 38 - ASSIGN = 39 - AUTO_INCREMENT = 40 - AUTO_DECREMENT = 41 - AUTO_SUM = 42 - AUTO_SUB = 43 - AUTO_MULTIPLY = 44 - AUTO_DIVIDE = 45 - AUTO_MODULE = 46 - END_OF_STATEMENT = 47 - VAR_STATEMENT = 48 - FOR_STATEMENT = 49 - SEARCH_STATEMENT = 50 - IN_STATEMENT = 51 - WHERE_STATEMENT = 52 - IF_STATEMENT = 53 - ELSE_STATEMENT = 54 - WHILE_STATEMENT = 55 - DO_STATEMENT = 56 - CURLY_PARENTHESIS_OPEN = 57 - CURLY_PARENTHESIS_CLOSE = 58 - ROUND_PARENTHESIS_OPEN = 59 - ROUND_PARENTHESIS_CLOSE = 60 - SQUARE_PARENTHESIS_OPEN = 61 - SQUARE_PARENTHESIS_CLOSE = 62 - DOT = 63 - STRING_ENCLOSURE = 64 - COMMA = 65 - BOOL_LITERAL = 66 - INT_LITERAL = 67 - FLOAT_LITERAL = 68 - HEX_LITERAL = 69 - BIN_LITERAL = 70 - QUBIT_LITERAL = 71 - QUINT_LITERAL = 72 - QUSTRING_LITERAL = 73 - SYMBOL_LITERAL = 74 - STRING_LITERAL = 75 - WS = 76 - NEWLINE = 77 + PRINT_LN = 30 + BARRIER = 31 + EQUAL = 32 + NOT_EQUAL = 33 + GREATER = 34 + GREATEREQUAL = 35 + LOWER = 36 + LOWEREQUAL = 37 + LSHIFT = 38 + RSHIFT = 39 + ASSIGN = 40 + AUTO_INCREMENT = 41 + AUTO_DECREMENT = 42 + AUTO_SUM = 43 + AUTO_SUB = 44 + AUTO_MULTIPLY = 45 + AUTO_DIVIDE = 46 + AUTO_MODULE = 47 + END_OF_STATEMENT = 48 + VAR_STATEMENT = 49 + FOR_STATEMENT = 50 + FOREACH_STATEMENT = 51 + SEARCH_STATEMENT = 52 + IN_STATEMENT = 53 + WHERE_STATEMENT = 54 + IF_STATEMENT = 55 + ELSE_STATEMENT = 56 + WHILE_STATEMENT = 57 + DO_STATEMENT = 58 + CURLY_PARENTHESIS_OPEN = 59 + CURLY_PARENTHESIS_CLOSE = 60 + ROUND_PARENTHESIS_OPEN = 61 + ROUND_PARENTHESIS_CLOSE = 62 + SQUARE_PARENTHESIS_OPEN = 63 + SQUARE_PARENTHESIS_CLOSE = 64 + DOT = 65 + STRING_ENCLOSURE = 66 + COMMA = 67 + BOOL_LITERAL = 68 + INT_LITERAL = 69 + FLOAT_LITERAL = 70 + HEX_LITERAL = 71 + BIN_LITERAL = 72 + QUBIT_LITERAL = 73 + QUINT_LITERAL = 74 + QUSTRING_LITERAL = 75 + SYMBOL_LITERAL = 76 + STRING_LITERAL = 77 + WS = 78 + NEWLINE = 79 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] @@ -348,44 +357,46 @@ class qutes_lexer(Lexer): "'float'", "'void'", "'return'", "'*'", "'/'", "'%'", "'+'", "'-'", "'not'", "'and'", "'or'", "'by'", "'swap'", "'pauliy'", "'pauliz'", "'grover'", "'mcz'", "'mcx'", "'mcy'", "'mcp'", - "'hadamard'", "'measure'", "'print'", "'barrier'", "'=='", "'!='", - "'>'", "'>='", "'<'", "'<='", "'<<'", "'>>'", "'='", "'++'", - "'--'", "'+='", "'-='", "'*='", "'/='", "'%='", "';'", "'var'", - "'for'", "'search'", "'in'", "'where'", "'if'", "'else'", "'while'", - "'do'", "'{'", "'}'", "'('", "')'", "'['", "']'", "'.'", "'\"'", - "','" ] + "'hadamard'", "'measure'", "'print'", "'println'", "'barrier'", + "'=='", "'!='", "'>'", "'>='", "'<'", "'<='", "'<<'", "'>>'", + "'='", "'++'", "'--'", "'+='", "'-='", "'*='", "'/='", "'%='", + "';'", "'var'", "'for'", "'foreach'", "'search'", "'in'", "'where'", + "'if'", "'else'", "'while'", "'do'", "'{'", "'}'", "'('", "')'", + "'['", "']'", "'.'", "'\"'", "','" ] symbolicNames = [ "", "INT_TYPE", "BOOL_TYPE", "STRING_TYPE", "QUBIT_TYPE", "QUINT_TYPE", "QUSTRING_TYPE", "FLOAT_TYPE", "VOID_TYPE", "RETURN", "MULTIPLY", "DIVIDE", "MODULE", "ADD", "SUB", "NOT", "AND", "OR", "BY", "SWAP", "PAULIY", "PAULIZ", "GROVER", "MCZ", "MCX", "MCY", "MCP", - "HADAMARD", "MEASURE", "PRINT", "BARRIER", "EQUAL", "NOT_EQUAL", - "GREATER", "GREATEREQUAL", "LOWER", "LOWEREQUAL", "LSHIFT", - "RSHIFT", "ASSIGN", "AUTO_INCREMENT", "AUTO_DECREMENT", "AUTO_SUM", - "AUTO_SUB", "AUTO_MULTIPLY", "AUTO_DIVIDE", "AUTO_MODULE", "END_OF_STATEMENT", - "VAR_STATEMENT", "FOR_STATEMENT", "SEARCH_STATEMENT", "IN_STATEMENT", - "WHERE_STATEMENT", "IF_STATEMENT", "ELSE_STATEMENT", "WHILE_STATEMENT", - "DO_STATEMENT", "CURLY_PARENTHESIS_OPEN", "CURLY_PARENTHESIS_CLOSE", - "ROUND_PARENTHESIS_OPEN", "ROUND_PARENTHESIS_CLOSE", "SQUARE_PARENTHESIS_OPEN", - "SQUARE_PARENTHESIS_CLOSE", "DOT", "STRING_ENCLOSURE", "COMMA", - "BOOL_LITERAL", "INT_LITERAL", "FLOAT_LITERAL", "HEX_LITERAL", - "BIN_LITERAL", "QUBIT_LITERAL", "QUINT_LITERAL", "QUSTRING_LITERAL", - "SYMBOL_LITERAL", "STRING_LITERAL", "WS", "NEWLINE" ] + "HADAMARD", "MEASURE", "PRINT", "PRINT_LN", "BARRIER", "EQUAL", + "NOT_EQUAL", "GREATER", "GREATEREQUAL", "LOWER", "LOWEREQUAL", + "LSHIFT", "RSHIFT", "ASSIGN", "AUTO_INCREMENT", "AUTO_DECREMENT", + "AUTO_SUM", "AUTO_SUB", "AUTO_MULTIPLY", "AUTO_DIVIDE", "AUTO_MODULE", + "END_OF_STATEMENT", "VAR_STATEMENT", "FOR_STATEMENT", "FOREACH_STATEMENT", + "SEARCH_STATEMENT", "IN_STATEMENT", "WHERE_STATEMENT", "IF_STATEMENT", + "ELSE_STATEMENT", "WHILE_STATEMENT", "DO_STATEMENT", "CURLY_PARENTHESIS_OPEN", + "CURLY_PARENTHESIS_CLOSE", "ROUND_PARENTHESIS_OPEN", "ROUND_PARENTHESIS_CLOSE", + "SQUARE_PARENTHESIS_OPEN", "SQUARE_PARENTHESIS_CLOSE", "DOT", + "STRING_ENCLOSURE", "COMMA", "BOOL_LITERAL", "INT_LITERAL", + "FLOAT_LITERAL", "HEX_LITERAL", "BIN_LITERAL", "QUBIT_LITERAL", + "QUINT_LITERAL", "QUSTRING_LITERAL", "SYMBOL_LITERAL", "STRING_LITERAL", + "WS", "NEWLINE" ] ruleNames = [ "INT_TYPE", "BOOL_TYPE", "STRING_TYPE", "QUBIT_TYPE", "QUINT_TYPE", "QUSTRING_TYPE", "FLOAT_TYPE", "VOID_TYPE", "RETURN", "MULTIPLY", "DIVIDE", "MODULE", "ADD", "SUB", "NOT", "AND", "OR", "BY", "SWAP", "PAULIY", "PAULIZ", "GROVER", "MCZ", "MCX", "MCY", "MCP", "HADAMARD", "MEASURE", - "PRINT", "BARRIER", "EQUAL", "NOT_EQUAL", "GREATER", "GREATEREQUAL", - "LOWER", "LOWEREQUAL", "LSHIFT", "RSHIFT", "ASSIGN", "AUTO_INCREMENT", - "AUTO_DECREMENT", "AUTO_SUM", "AUTO_SUB", "AUTO_MULTIPLY", - "AUTO_DIVIDE", "AUTO_MODULE", "END_OF_STATEMENT", "VAR_STATEMENT", - "FOR_STATEMENT", "SEARCH_STATEMENT", "IN_STATEMENT", "WHERE_STATEMENT", - "IF_STATEMENT", "ELSE_STATEMENT", "WHILE_STATEMENT", "DO_STATEMENT", - "CURLY_PARENTHESIS_OPEN", "CURLY_PARENTHESIS_CLOSE", "ROUND_PARENTHESIS_OPEN", - "ROUND_PARENTHESIS_CLOSE", "SQUARE_PARENTHESIS_OPEN", + "PRINT", "PRINT_LN", "BARRIER", "EQUAL", "NOT_EQUAL", + "GREATER", "GREATEREQUAL", "LOWER", "LOWEREQUAL", "LSHIFT", + "RSHIFT", "ASSIGN", "AUTO_INCREMENT", "AUTO_DECREMENT", + "AUTO_SUM", "AUTO_SUB", "AUTO_MULTIPLY", "AUTO_DIVIDE", + "AUTO_MODULE", "END_OF_STATEMENT", "VAR_STATEMENT", "FOR_STATEMENT", + "FOREACH_STATEMENT", "SEARCH_STATEMENT", "IN_STATEMENT", + "WHERE_STATEMENT", "IF_STATEMENT", "ELSE_STATEMENT", "WHILE_STATEMENT", + "DO_STATEMENT", "CURLY_PARENTHESIS_OPEN", "CURLY_PARENTHESIS_CLOSE", + "ROUND_PARENTHESIS_OPEN", "ROUND_PARENTHESIS_CLOSE", "SQUARE_PARENTHESIS_OPEN", "SQUARE_PARENTHESIS_CLOSE", "DOT", "STRING_ENCLOSURE", "COMMA", "COMMENT", "TRUE", "FALSE", "DIGIT", "MATH_SIGN", "QUBIT_STANDARD", "BOOL_LITERAL", "INT_LITERAL", "FLOAT_LITERAL", diff --git a/src/qutes_antlr/qutes_lexer.tokens b/src/qutes_antlr/qutes_lexer.tokens index 9f5f556..e0fc4d9 100644 --- a/src/qutes_antlr/qutes_lexer.tokens +++ b/src/qutes_antlr/qutes_lexer.tokens @@ -27,54 +27,56 @@ MCP=26 HADAMARD=27 MEASURE=28 PRINT=29 -BARRIER=30 -EQUAL=31 -NOT_EQUAL=32 -GREATER=33 -GREATEREQUAL=34 -LOWER=35 -LOWEREQUAL=36 -LSHIFT=37 -RSHIFT=38 -ASSIGN=39 -AUTO_INCREMENT=40 -AUTO_DECREMENT=41 -AUTO_SUM=42 -AUTO_SUB=43 -AUTO_MULTIPLY=44 -AUTO_DIVIDE=45 -AUTO_MODULE=46 -END_OF_STATEMENT=47 -VAR_STATEMENT=48 -FOR_STATEMENT=49 -SEARCH_STATEMENT=50 -IN_STATEMENT=51 -WHERE_STATEMENT=52 -IF_STATEMENT=53 -ELSE_STATEMENT=54 -WHILE_STATEMENT=55 -DO_STATEMENT=56 -CURLY_PARENTHESIS_OPEN=57 -CURLY_PARENTHESIS_CLOSE=58 -ROUND_PARENTHESIS_OPEN=59 -ROUND_PARENTHESIS_CLOSE=60 -SQUARE_PARENTHESIS_OPEN=61 -SQUARE_PARENTHESIS_CLOSE=62 -DOT=63 -STRING_ENCLOSURE=64 -COMMA=65 -BOOL_LITERAL=66 -INT_LITERAL=67 -FLOAT_LITERAL=68 -HEX_LITERAL=69 -BIN_LITERAL=70 -QUBIT_LITERAL=71 -QUINT_LITERAL=72 -QUSTRING_LITERAL=73 -SYMBOL_LITERAL=74 -STRING_LITERAL=75 -WS=76 -NEWLINE=77 +PRINT_LN=30 +BARRIER=31 +EQUAL=32 +NOT_EQUAL=33 +GREATER=34 +GREATEREQUAL=35 +LOWER=36 +LOWEREQUAL=37 +LSHIFT=38 +RSHIFT=39 +ASSIGN=40 +AUTO_INCREMENT=41 +AUTO_DECREMENT=42 +AUTO_SUM=43 +AUTO_SUB=44 +AUTO_MULTIPLY=45 +AUTO_DIVIDE=46 +AUTO_MODULE=47 +END_OF_STATEMENT=48 +VAR_STATEMENT=49 +FOR_STATEMENT=50 +FOREACH_STATEMENT=51 +SEARCH_STATEMENT=52 +IN_STATEMENT=53 +WHERE_STATEMENT=54 +IF_STATEMENT=55 +ELSE_STATEMENT=56 +WHILE_STATEMENT=57 +DO_STATEMENT=58 +CURLY_PARENTHESIS_OPEN=59 +CURLY_PARENTHESIS_CLOSE=60 +ROUND_PARENTHESIS_OPEN=61 +ROUND_PARENTHESIS_CLOSE=62 +SQUARE_PARENTHESIS_OPEN=63 +SQUARE_PARENTHESIS_CLOSE=64 +DOT=65 +STRING_ENCLOSURE=66 +COMMA=67 +BOOL_LITERAL=68 +INT_LITERAL=69 +FLOAT_LITERAL=70 +HEX_LITERAL=71 +BIN_LITERAL=72 +QUBIT_LITERAL=73 +QUINT_LITERAL=74 +QUSTRING_LITERAL=75 +SYMBOL_LITERAL=76 +STRING_LITERAL=77 +WS=78 +NEWLINE=79 'int'=1 'bool'=2 'string'=3 @@ -104,39 +106,41 @@ NEWLINE=77 'hadamard'=27 'measure'=28 'print'=29 -'barrier'=30 -'=='=31 -'!='=32 -'>'=33 -'>='=34 -'<'=35 -'<='=36 -'<<'=37 -'>>'=38 -'='=39 -'++'=40 -'--'=41 -'+='=42 -'-='=43 -'*='=44 -'/='=45 -'%='=46 -';'=47 -'var'=48 -'for'=49 -'search'=50 -'in'=51 -'where'=52 -'if'=53 -'else'=54 -'while'=55 -'do'=56 -'{'=57 -'}'=58 -'('=59 -')'=60 -'['=61 -']'=62 -'.'=63 -'"'=64 -','=65 +'println'=30 +'barrier'=31 +'=='=32 +'!='=33 +'>'=34 +'>='=35 +'<'=36 +'<='=37 +'<<'=38 +'>>'=39 +'='=40 +'++'=41 +'--'=42 +'+='=43 +'-='=44 +'*='=45 +'/='=46 +'%='=47 +';'=48 +'var'=49 +'for'=50 +'foreach'=51 +'search'=52 +'in'=53 +'where'=54 +'if'=55 +'else'=56 +'while'=57 +'do'=58 +'{'=59 +'}'=60 +'('=61 +')'=62 +'['=63 +']'=64 +'.'=65 +'"'=66 +','=67 diff --git a/src/qutes_antlr/qutes_parser.py b/src/qutes_antlr/qutes_parser.py index e676b38..fb23db3 100644 --- a/src/qutes_antlr/qutes_parser.py +++ b/src/qutes_antlr/qutes_parser.py @@ -10,95 +10,99 @@ def serializedATN(): return [ - 4,1,77,245,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7, + 4,1,79,255,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7, 6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13, 2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,1,0, 5,0,42,8,0,10,0,12,0,45,9,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,70,8, - 1,10,1,12,1,73,9,1,1,1,1,1,1,1,1,1,1,1,3,1,80,8,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,3,1,102,8,1,1,2,1,2,1,2,3,2,107,8,2,1,3,1,3,1,3,1,3,3,3,113,8, - 3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3,4,126,8,4,1,4,1, - 4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3, - 4,145,8,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1, - 4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,5,4,175, - 8,4,10,4,12,4,178,9,4,1,5,1,5,3,5,182,8,5,1,5,1,5,3,5,186,8,5,1, - 6,1,6,1,6,1,6,1,7,1,7,1,7,3,7,195,8,7,1,7,1,7,1,7,3,7,200,8,7,3, - 7,202,8,7,1,8,1,8,1,9,1,9,1,9,5,9,209,8,9,10,9,12,9,212,9,9,1,9, - 1,9,3,9,216,8,9,1,10,1,10,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12, - 1,12,3,12,229,8,12,1,13,1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,17, - 1,17,1,18,1,18,1,19,1,19,1,19,0,1,8,20,0,2,4,6,8,10,12,14,16,18, - 20,22,24,26,28,30,32,34,36,38,0,12,2,0,28,28,30,30,2,0,13,15,40, - 41,2,0,19,19,23,25,2,0,20,21,27,29,1,0,10,12,1,0,13,14,1,0,37,38, - 1,0,33,36,1,0,31,32,1,0,40,41,1,0,1,8,2,0,67,67,69,70,273,0,43,1, - 0,0,0,2,101,1,0,0,0,4,103,1,0,0,0,6,108,1,0,0,0,8,144,1,0,0,0,10, - 181,1,0,0,0,12,187,1,0,0,0,14,201,1,0,0,0,16,203,1,0,0,0,18,215, - 1,0,0,0,20,217,1,0,0,0,22,219,1,0,0,0,24,228,1,0,0,0,26,230,1,0, - 0,0,28,232,1,0,0,0,30,234,1,0,0,0,32,236,1,0,0,0,34,238,1,0,0,0, - 36,240,1,0,0,0,38,242,1,0,0,0,40,42,3,2,1,0,41,40,1,0,0,0,42,45, - 1,0,0,0,43,41,1,0,0,0,43,44,1,0,0,0,44,46,1,0,0,0,45,43,1,0,0,0, - 46,47,5,0,0,1,47,1,1,0,0,0,48,49,5,53,0,0,49,50,3,8,4,0,50,51,3, - 2,1,0,51,102,1,0,0,0,52,53,5,53,0,0,53,54,3,8,4,0,54,55,3,2,1,0, - 55,56,5,54,0,0,56,57,3,2,1,0,57,102,1,0,0,0,58,59,5,55,0,0,59,60, - 3,8,4,0,60,61,3,2,1,0,61,102,1,0,0,0,62,63,5,56,0,0,63,64,3,2,1, - 0,64,65,5,55,0,0,65,66,3,8,4,0,66,102,1,0,0,0,67,71,5,57,0,0,68, - 70,3,2,1,0,69,68,1,0,0,0,70,73,1,0,0,0,71,69,1,0,0,0,71,72,1,0,0, - 0,72,74,1,0,0,0,73,71,1,0,0,0,74,102,5,58,0,0,75,76,3,14,7,0,76, - 77,3,22,11,0,77,79,5,59,0,0,78,80,3,4,2,0,79,78,1,0,0,0,79,80,1, - 0,0,0,80,81,1,0,0,0,81,82,5,60,0,0,82,83,3,2,1,0,83,102,1,0,0,0, - 84,85,3,6,3,0,85,86,5,47,0,0,86,102,1,0,0,0,87,88,3,18,9,0,88,89, - 5,39,0,0,89,90,3,8,4,0,90,91,5,47,0,0,91,102,1,0,0,0,92,93,5,9,0, - 0,93,94,3,8,4,0,94,95,5,47,0,0,95,102,1,0,0,0,96,97,3,8,4,0,97,98, - 5,47,0,0,98,102,1,0,0,0,99,102,7,0,0,0,100,102,5,47,0,0,101,48,1, - 0,0,0,101,52,1,0,0,0,101,58,1,0,0,0,101,62,1,0,0,0,101,67,1,0,0, - 0,101,75,1,0,0,0,101,84,1,0,0,0,101,87,1,0,0,0,101,92,1,0,0,0,101, - 96,1,0,0,0,101,99,1,0,0,0,101,100,1,0,0,0,102,3,1,0,0,0,103,106, - 3,6,3,0,104,105,5,65,0,0,105,107,3,4,2,0,106,104,1,0,0,0,106,107, - 1,0,0,0,107,5,1,0,0,0,108,109,3,14,7,0,109,112,3,20,10,0,110,111, - 5,39,0,0,111,113,3,8,4,0,112,110,1,0,0,0,112,113,1,0,0,0,113,7,1, - 0,0,0,114,115,6,4,-1,0,115,116,5,59,0,0,116,117,3,8,4,0,117,118, - 5,60,0,0,118,145,1,0,0,0,119,145,3,24,12,0,120,145,3,18,9,0,121, - 145,3,12,6,0,122,123,3,22,11,0,123,125,5,59,0,0,124,126,3,10,5,0, - 125,124,1,0,0,0,125,126,1,0,0,0,126,127,1,0,0,0,127,128,5,60,0,0, - 128,145,1,0,0,0,129,130,7,1,0,0,130,145,3,8,4,12,131,132,7,2,0,0, - 132,145,3,10,5,0,133,134,7,3,0,0,134,145,3,8,4,3,135,136,5,26,0, - 0,136,137,3,10,5,0,137,138,5,18,0,0,138,139,3,8,4,2,139,145,1,0, - 0,0,140,141,3,10,5,0,141,142,5,51,0,0,142,143,3,18,9,0,143,145,1, - 0,0,0,144,114,1,0,0,0,144,119,1,0,0,0,144,120,1,0,0,0,144,121,1, - 0,0,0,144,122,1,0,0,0,144,129,1,0,0,0,144,131,1,0,0,0,144,133,1, - 0,0,0,144,135,1,0,0,0,144,140,1,0,0,0,145,176,1,0,0,0,146,147,10, - 11,0,0,147,148,7,4,0,0,148,175,3,8,4,12,149,150,10,10,0,0,150,151, - 7,5,0,0,151,175,3,8,4,11,152,153,10,9,0,0,153,154,7,6,0,0,154,175, - 3,8,4,10,155,156,10,8,0,0,156,157,7,7,0,0,157,175,3,8,4,9,158,159, - 10,7,0,0,159,160,7,8,0,0,160,175,3,8,4,8,161,162,10,6,0,0,162,163, - 5,16,0,0,163,175,3,8,4,7,164,165,10,5,0,0,165,166,5,17,0,0,166,175, - 3,8,4,6,167,168,10,14,0,0,168,169,5,61,0,0,169,170,3,8,4,0,170,171, - 5,62,0,0,171,175,1,0,0,0,172,173,10,13,0,0,173,175,7,9,0,0,174,146, - 1,0,0,0,174,149,1,0,0,0,174,152,1,0,0,0,174,155,1,0,0,0,174,158, - 1,0,0,0,174,161,1,0,0,0,174,164,1,0,0,0,174,167,1,0,0,0,174,172, - 1,0,0,0,175,178,1,0,0,0,176,174,1,0,0,0,176,177,1,0,0,0,177,9,1, - 0,0,0,178,176,1,0,0,0,179,182,3,24,12,0,180,182,3,18,9,0,181,179, - 1,0,0,0,181,180,1,0,0,0,182,185,1,0,0,0,183,184,5,65,0,0,184,186, - 3,10,5,0,185,183,1,0,0,0,185,186,1,0,0,0,186,11,1,0,0,0,187,188, - 5,61,0,0,188,189,3,10,5,0,189,190,5,62,0,0,190,13,1,0,0,0,191,194, - 3,16,8,0,192,193,5,61,0,0,193,195,5,62,0,0,194,192,1,0,0,0,194,195, - 1,0,0,0,195,202,1,0,0,0,196,199,3,18,9,0,197,198,5,61,0,0,198,200, - 5,62,0,0,199,197,1,0,0,0,199,200,1,0,0,0,200,202,1,0,0,0,201,191, - 1,0,0,0,201,196,1,0,0,0,202,15,1,0,0,0,203,204,7,10,0,0,204,17,1, - 0,0,0,205,210,5,74,0,0,206,207,5,63,0,0,207,209,5,74,0,0,208,206, - 1,0,0,0,209,212,1,0,0,0,210,208,1,0,0,0,210,211,1,0,0,0,211,216, - 1,0,0,0,212,210,1,0,0,0,213,216,3,20,10,0,214,216,3,22,11,0,215, - 205,1,0,0,0,215,213,1,0,0,0,215,214,1,0,0,0,216,19,1,0,0,0,217,218, - 5,74,0,0,218,21,1,0,0,0,219,220,5,74,0,0,220,23,1,0,0,0,221,229, - 3,38,19,0,222,229,3,36,18,0,223,229,3,34,17,0,224,229,3,28,14,0, - 225,229,3,30,15,0,226,229,3,32,16,0,227,229,3,26,13,0,228,221,1, - 0,0,0,228,222,1,0,0,0,228,223,1,0,0,0,228,224,1,0,0,0,228,225,1, - 0,0,0,228,226,1,0,0,0,228,227,1,0,0,0,229,25,1,0,0,0,230,231,5,75, - 0,0,231,27,1,0,0,0,232,233,5,71,0,0,233,29,1,0,0,0,234,235,5,72, - 0,0,235,31,1,0,0,0,236,237,5,73,0,0,237,33,1,0,0,0,238,239,5,68, - 0,0,239,35,1,0,0,0,240,241,7,11,0,0,241,37,1,0,0,0,242,243,5,66, - 0,0,243,39,1,0,0,0,18,43,71,79,101,106,112,125,144,174,176,181,185, - 194,199,201,210,215,228 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,67,8,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,80,8,1,10,1,12,1,83,9,1,1, + 1,1,1,1,1,1,1,1,1,3,1,90,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,112,8,1,1,2,1,2, + 1,2,3,2,117,8,2,1,3,1,3,1,3,1,3,3,3,123,8,3,1,4,1,4,1,4,1,4,1,4, + 1,4,1,4,1,4,1,4,1,4,1,4,3,4,136,8,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4, + 1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,3,4,155,8,4,1,4,1,4,1,4, + 1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4, + 1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,5,4,185,8,4,10,4,12,4,188,9, + 4,1,5,1,5,3,5,192,8,5,1,5,1,5,3,5,196,8,5,1,6,1,6,1,6,1,6,1,7,1, + 7,1,7,3,7,205,8,7,1,7,1,7,1,7,3,7,210,8,7,3,7,212,8,7,1,8,1,8,1, + 9,1,9,1,9,5,9,219,8,9,10,9,12,9,222,9,9,1,9,1,9,3,9,226,8,9,1,10, + 1,10,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,3,12,239,8,12, + 1,13,1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,17,1,17,1,18,1,18,1,19, + 1,19,1,19,0,1,8,20,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32, + 34,36,38,0,12,2,0,28,28,30,31,2,0,13,15,41,42,2,0,19,19,23,25,2, + 0,20,21,27,30,1,0,10,12,1,0,13,14,1,0,38,39,1,0,34,37,1,0,32,33, + 1,0,41,42,1,0,1,8,2,0,69,69,71,72,285,0,43,1,0,0,0,2,111,1,0,0,0, + 4,113,1,0,0,0,6,118,1,0,0,0,8,154,1,0,0,0,10,191,1,0,0,0,12,197, + 1,0,0,0,14,211,1,0,0,0,16,213,1,0,0,0,18,225,1,0,0,0,20,227,1,0, + 0,0,22,229,1,0,0,0,24,238,1,0,0,0,26,240,1,0,0,0,28,242,1,0,0,0, + 30,244,1,0,0,0,32,246,1,0,0,0,34,248,1,0,0,0,36,250,1,0,0,0,38,252, + 1,0,0,0,40,42,3,2,1,0,41,40,1,0,0,0,42,45,1,0,0,0,43,41,1,0,0,0, + 43,44,1,0,0,0,44,46,1,0,0,0,45,43,1,0,0,0,46,47,5,0,0,1,47,1,1,0, + 0,0,48,49,5,55,0,0,49,50,3,8,4,0,50,51,3,2,1,0,51,112,1,0,0,0,52, + 53,5,55,0,0,53,54,3,8,4,0,54,55,3,2,1,0,55,56,5,56,0,0,56,57,3,2, + 1,0,57,112,1,0,0,0,58,59,5,57,0,0,59,60,3,8,4,0,60,61,3,2,1,0,61, + 112,1,0,0,0,62,63,5,51,0,0,63,66,3,6,3,0,64,65,5,67,0,0,65,67,3, + 6,3,0,66,64,1,0,0,0,66,67,1,0,0,0,67,68,1,0,0,0,68,69,5,53,0,0,69, + 70,3,18,9,0,70,71,3,2,1,0,71,112,1,0,0,0,72,73,5,58,0,0,73,74,3, + 2,1,0,74,75,5,57,0,0,75,76,3,8,4,0,76,112,1,0,0,0,77,81,5,59,0,0, + 78,80,3,2,1,0,79,78,1,0,0,0,80,83,1,0,0,0,81,79,1,0,0,0,81,82,1, + 0,0,0,82,84,1,0,0,0,83,81,1,0,0,0,84,112,5,60,0,0,85,86,3,14,7,0, + 86,87,3,22,11,0,87,89,5,61,0,0,88,90,3,4,2,0,89,88,1,0,0,0,89,90, + 1,0,0,0,90,91,1,0,0,0,91,92,5,62,0,0,92,93,3,2,1,0,93,112,1,0,0, + 0,94,95,3,6,3,0,95,96,5,48,0,0,96,112,1,0,0,0,97,98,3,18,9,0,98, + 99,5,40,0,0,99,100,3,8,4,0,100,101,5,48,0,0,101,112,1,0,0,0,102, + 103,5,9,0,0,103,104,3,8,4,0,104,105,5,48,0,0,105,112,1,0,0,0,106, + 107,3,8,4,0,107,108,5,48,0,0,108,112,1,0,0,0,109,112,7,0,0,0,110, + 112,5,48,0,0,111,48,1,0,0,0,111,52,1,0,0,0,111,58,1,0,0,0,111,62, + 1,0,0,0,111,72,1,0,0,0,111,77,1,0,0,0,111,85,1,0,0,0,111,94,1,0, + 0,0,111,97,1,0,0,0,111,102,1,0,0,0,111,106,1,0,0,0,111,109,1,0,0, + 0,111,110,1,0,0,0,112,3,1,0,0,0,113,116,3,6,3,0,114,115,5,67,0,0, + 115,117,3,4,2,0,116,114,1,0,0,0,116,117,1,0,0,0,117,5,1,0,0,0,118, + 119,3,14,7,0,119,122,3,20,10,0,120,121,5,40,0,0,121,123,3,8,4,0, + 122,120,1,0,0,0,122,123,1,0,0,0,123,7,1,0,0,0,124,125,6,4,-1,0,125, + 126,5,61,0,0,126,127,3,8,4,0,127,128,5,62,0,0,128,155,1,0,0,0,129, + 155,3,24,12,0,130,155,3,18,9,0,131,155,3,12,6,0,132,133,3,22,11, + 0,133,135,5,61,0,0,134,136,3,10,5,0,135,134,1,0,0,0,135,136,1,0, + 0,0,136,137,1,0,0,0,137,138,5,62,0,0,138,155,1,0,0,0,139,140,7,1, + 0,0,140,155,3,8,4,12,141,142,7,2,0,0,142,155,3,10,5,0,143,144,7, + 3,0,0,144,155,3,8,4,3,145,146,5,26,0,0,146,147,3,10,5,0,147,148, + 5,18,0,0,148,149,3,8,4,2,149,155,1,0,0,0,150,151,3,10,5,0,151,152, + 5,53,0,0,152,153,3,18,9,0,153,155,1,0,0,0,154,124,1,0,0,0,154,129, + 1,0,0,0,154,130,1,0,0,0,154,131,1,0,0,0,154,132,1,0,0,0,154,139, + 1,0,0,0,154,141,1,0,0,0,154,143,1,0,0,0,154,145,1,0,0,0,154,150, + 1,0,0,0,155,186,1,0,0,0,156,157,10,11,0,0,157,158,7,4,0,0,158,185, + 3,8,4,12,159,160,10,10,0,0,160,161,7,5,0,0,161,185,3,8,4,11,162, + 163,10,9,0,0,163,164,7,6,0,0,164,185,3,8,4,10,165,166,10,8,0,0,166, + 167,7,7,0,0,167,185,3,8,4,9,168,169,10,7,0,0,169,170,7,8,0,0,170, + 185,3,8,4,8,171,172,10,6,0,0,172,173,5,16,0,0,173,185,3,8,4,7,174, + 175,10,5,0,0,175,176,5,17,0,0,176,185,3,8,4,6,177,178,10,14,0,0, + 178,179,5,63,0,0,179,180,3,8,4,0,180,181,5,64,0,0,181,185,1,0,0, + 0,182,183,10,13,0,0,183,185,7,9,0,0,184,156,1,0,0,0,184,159,1,0, + 0,0,184,162,1,0,0,0,184,165,1,0,0,0,184,168,1,0,0,0,184,171,1,0, + 0,0,184,174,1,0,0,0,184,177,1,0,0,0,184,182,1,0,0,0,185,188,1,0, + 0,0,186,184,1,0,0,0,186,187,1,0,0,0,187,9,1,0,0,0,188,186,1,0,0, + 0,189,192,3,24,12,0,190,192,3,18,9,0,191,189,1,0,0,0,191,190,1,0, + 0,0,192,195,1,0,0,0,193,194,5,67,0,0,194,196,3,10,5,0,195,193,1, + 0,0,0,195,196,1,0,0,0,196,11,1,0,0,0,197,198,5,63,0,0,198,199,3, + 10,5,0,199,200,5,64,0,0,200,13,1,0,0,0,201,204,3,16,8,0,202,203, + 5,63,0,0,203,205,5,64,0,0,204,202,1,0,0,0,204,205,1,0,0,0,205,212, + 1,0,0,0,206,209,3,18,9,0,207,208,5,63,0,0,208,210,5,64,0,0,209,207, + 1,0,0,0,209,210,1,0,0,0,210,212,1,0,0,0,211,201,1,0,0,0,211,206, + 1,0,0,0,212,15,1,0,0,0,213,214,7,10,0,0,214,17,1,0,0,0,215,220,5, + 76,0,0,216,217,5,65,0,0,217,219,5,76,0,0,218,216,1,0,0,0,219,222, + 1,0,0,0,220,218,1,0,0,0,220,221,1,0,0,0,221,226,1,0,0,0,222,220, + 1,0,0,0,223,226,3,20,10,0,224,226,3,22,11,0,225,215,1,0,0,0,225, + 223,1,0,0,0,225,224,1,0,0,0,226,19,1,0,0,0,227,228,5,76,0,0,228, + 21,1,0,0,0,229,230,5,76,0,0,230,23,1,0,0,0,231,239,3,38,19,0,232, + 239,3,36,18,0,233,239,3,34,17,0,234,239,3,28,14,0,235,239,3,30,15, + 0,236,239,3,32,16,0,237,239,3,26,13,0,238,231,1,0,0,0,238,232,1, + 0,0,0,238,233,1,0,0,0,238,234,1,0,0,0,238,235,1,0,0,0,238,236,1, + 0,0,0,238,237,1,0,0,0,239,25,1,0,0,0,240,241,5,77,0,0,241,27,1,0, + 0,0,242,243,5,73,0,0,243,29,1,0,0,0,244,245,5,74,0,0,245,31,1,0, + 0,0,246,247,5,75,0,0,247,33,1,0,0,0,248,249,5,70,0,0,249,35,1,0, + 0,0,250,251,7,11,0,0,251,37,1,0,0,0,252,253,5,68,0,0,253,39,1,0, + 0,0,19,43,66,81,89,111,116,122,135,154,184,186,191,195,204,209,211, + 220,225,238 ] class qutes_parser ( Parser ): @@ -116,33 +120,33 @@ class qutes_parser ( Parser ): "'*'", "'/'", "'%'", "'+'", "'-'", "'not'", "'and'", "'or'", "'by'", "'swap'", "'pauliy'", "'pauliz'", "'grover'", "'mcz'", "'mcx'", "'mcy'", "'mcp'", "'hadamard'", "'measure'", - "'print'", "'barrier'", "'=='", "'!='", "'>'", "'>='", - "'<'", "'<='", "'<<'", "'>>'", "'='", "'++'", "'--'", - "'+='", "'-='", "'*='", "'/='", "'%='", "';'", "'var'", - "'for'", "'search'", "'in'", "'where'", "'if'", "'else'", - "'while'", "'do'", "'{'", "'}'", "'('", "')'", "'['", - "']'", "'.'", "'\"'", "','" ] + "'print'", "'println'", "'barrier'", "'=='", "'!='", + "'>'", "'>='", "'<'", "'<='", "'<<'", "'>>'", "'='", + "'++'", "'--'", "'+='", "'-='", "'*='", "'/='", "'%='", + "';'", "'var'", "'for'", "'foreach'", "'search'", "'in'", + "'where'", "'if'", "'else'", "'while'", "'do'", "'{'", + "'}'", "'('", "')'", "'['", "']'", "'.'", "'\"'", "','" ] symbolicNames = [ "", "INT_TYPE", "BOOL_TYPE", "STRING_TYPE", "QUBIT_TYPE", "QUINT_TYPE", "QUSTRING_TYPE", "FLOAT_TYPE", "VOID_TYPE", "RETURN", "MULTIPLY", "DIVIDE", "MODULE", "ADD", "SUB", "NOT", "AND", "OR", "BY", "SWAP", "PAULIY", "PAULIZ", "GROVER", "MCZ", "MCX", "MCY", "MCP", "HADAMARD", - "MEASURE", "PRINT", "BARRIER", "EQUAL", "NOT_EQUAL", - "GREATER", "GREATEREQUAL", "LOWER", "LOWEREQUAL", + "MEASURE", "PRINT", "PRINT_LN", "BARRIER", "EQUAL", + "NOT_EQUAL", "GREATER", "GREATEREQUAL", "LOWER", "LOWEREQUAL", "LSHIFT", "RSHIFT", "ASSIGN", "AUTO_INCREMENT", "AUTO_DECREMENT", "AUTO_SUM", "AUTO_SUB", "AUTO_MULTIPLY", "AUTO_DIVIDE", "AUTO_MODULE", "END_OF_STATEMENT", "VAR_STATEMENT", - "FOR_STATEMENT", "SEARCH_STATEMENT", "IN_STATEMENT", - "WHERE_STATEMENT", "IF_STATEMENT", "ELSE_STATEMENT", - "WHILE_STATEMENT", "DO_STATEMENT", "CURLY_PARENTHESIS_OPEN", - "CURLY_PARENTHESIS_CLOSE", "ROUND_PARENTHESIS_OPEN", - "ROUND_PARENTHESIS_CLOSE", "SQUARE_PARENTHESIS_OPEN", - "SQUARE_PARENTHESIS_CLOSE", "DOT", "STRING_ENCLOSURE", - "COMMA", "BOOL_LITERAL", "INT_LITERAL", "FLOAT_LITERAL", - "HEX_LITERAL", "BIN_LITERAL", "QUBIT_LITERAL", "QUINT_LITERAL", - "QUSTRING_LITERAL", "SYMBOL_LITERAL", "STRING_LITERAL", - "WS", "NEWLINE" ] + "FOR_STATEMENT", "FOREACH_STATEMENT", "SEARCH_STATEMENT", + "IN_STATEMENT", "WHERE_STATEMENT", "IF_STATEMENT", + "ELSE_STATEMENT", "WHILE_STATEMENT", "DO_STATEMENT", + "CURLY_PARENTHESIS_OPEN", "CURLY_PARENTHESIS_CLOSE", + "ROUND_PARENTHESIS_OPEN", "ROUND_PARENTHESIS_CLOSE", + "SQUARE_PARENTHESIS_OPEN", "SQUARE_PARENTHESIS_CLOSE", + "DOT", "STRING_ENCLOSURE", "COMMA", "BOOL_LITERAL", + "INT_LITERAL", "FLOAT_LITERAL", "HEX_LITERAL", "BIN_LITERAL", + "QUBIT_LITERAL", "QUINT_LITERAL", "QUSTRING_LITERAL", + "SYMBOL_LITERAL", "STRING_LITERAL", "WS", "NEWLINE" ] RULE_program = 0 RULE_statement = 1 @@ -201,54 +205,56 @@ class qutes_parser ( Parser ): HADAMARD=27 MEASURE=28 PRINT=29 - BARRIER=30 - EQUAL=31 - NOT_EQUAL=32 - GREATER=33 - GREATEREQUAL=34 - LOWER=35 - LOWEREQUAL=36 - LSHIFT=37 - RSHIFT=38 - ASSIGN=39 - AUTO_INCREMENT=40 - AUTO_DECREMENT=41 - AUTO_SUM=42 - AUTO_SUB=43 - AUTO_MULTIPLY=44 - AUTO_DIVIDE=45 - AUTO_MODULE=46 - END_OF_STATEMENT=47 - VAR_STATEMENT=48 - FOR_STATEMENT=49 - SEARCH_STATEMENT=50 - IN_STATEMENT=51 - WHERE_STATEMENT=52 - IF_STATEMENT=53 - ELSE_STATEMENT=54 - WHILE_STATEMENT=55 - DO_STATEMENT=56 - CURLY_PARENTHESIS_OPEN=57 - CURLY_PARENTHESIS_CLOSE=58 - ROUND_PARENTHESIS_OPEN=59 - ROUND_PARENTHESIS_CLOSE=60 - SQUARE_PARENTHESIS_OPEN=61 - SQUARE_PARENTHESIS_CLOSE=62 - DOT=63 - STRING_ENCLOSURE=64 - COMMA=65 - BOOL_LITERAL=66 - INT_LITERAL=67 - FLOAT_LITERAL=68 - HEX_LITERAL=69 - BIN_LITERAL=70 - QUBIT_LITERAL=71 - QUINT_LITERAL=72 - QUSTRING_LITERAL=73 - SYMBOL_LITERAL=74 - STRING_LITERAL=75 - WS=76 - NEWLINE=77 + PRINT_LN=30 + BARRIER=31 + EQUAL=32 + NOT_EQUAL=33 + GREATER=34 + GREATEREQUAL=35 + LOWER=36 + LOWEREQUAL=37 + LSHIFT=38 + RSHIFT=39 + ASSIGN=40 + AUTO_INCREMENT=41 + AUTO_DECREMENT=42 + AUTO_SUM=43 + AUTO_SUB=44 + AUTO_MULTIPLY=45 + AUTO_DIVIDE=46 + AUTO_MODULE=47 + END_OF_STATEMENT=48 + VAR_STATEMENT=49 + FOR_STATEMENT=50 + FOREACH_STATEMENT=51 + SEARCH_STATEMENT=52 + IN_STATEMENT=53 + WHERE_STATEMENT=54 + IF_STATEMENT=55 + ELSE_STATEMENT=56 + WHILE_STATEMENT=57 + DO_STATEMENT=58 + CURLY_PARENTHESIS_OPEN=59 + CURLY_PARENTHESIS_CLOSE=60 + ROUND_PARENTHESIS_OPEN=61 + ROUND_PARENTHESIS_CLOSE=62 + SQUARE_PARENTHESIS_OPEN=63 + SQUARE_PARENTHESIS_CLOSE=64 + DOT=65 + STRING_ENCLOSURE=66 + COMMA=67 + BOOL_LITERAL=68 + INT_LITERAL=69 + FLOAT_LITERAL=70 + HEX_LITERAL=71 + BIN_LITERAL=72 + QUBIT_LITERAL=73 + QUINT_LITERAL=74 + QUSTRING_LITERAL=75 + SYMBOL_LITERAL=76 + STRING_LITERAL=77 + WS=78 + NEWLINE=79 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) @@ -306,7 +312,7 @@ def program(self): self.state = 43 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & 3143656578070668286) != 0) or ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): + while (((_la) & ~0x3f) == 0 and ((1 << _la) & -5870154037940657154) != 0) or ((((_la - 68)) & ~0x3f) == 0 and ((1 << (_la - 68)) & 1023) != 0): self.state = 40 self.statement() self.state = 45 @@ -341,6 +347,155 @@ def copyFrom(self, ctx:ParserRuleContext): + class FactStatementContext(StatementContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext + super().__init__(parser) + self.copyFrom(ctx) + + def MEASURE(self): + return self.getToken(qutes_parser.MEASURE, 0) + def BARRIER(self): + return self.getToken(qutes_parser.BARRIER, 0) + def PRINT_LN(self): + return self.getToken(qutes_parser.PRINT_LN, 0) + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterFactStatement" ): + listener.enterFactStatement(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitFactStatement" ): + listener.exitFactStatement(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitFactStatement" ): + return visitor.visitFactStatement(self) + else: + return visitor.visitChildren(self) + + + class IfElseStatementContext(StatementContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext + super().__init__(parser) + self.copyFrom(ctx) + + def IF_STATEMENT(self): + return self.getToken(qutes_parser.IF_STATEMENT, 0) + def expr(self): + return self.getTypedRuleContext(qutes_parser.ExprContext,0) + + def statement(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(qutes_parser.StatementContext) + else: + return self.getTypedRuleContext(qutes_parser.StatementContext,i) + + def ELSE_STATEMENT(self): + return self.getToken(qutes_parser.ELSE_STATEMENT, 0) + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterIfElseStatement" ): + listener.enterIfElseStatement(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitIfElseStatement" ): + listener.exitIfElseStatement(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitIfElseStatement" ): + return visitor.visitIfElseStatement(self) + else: + return visitor.visitChildren(self) + + + class EmptyStatementContext(StatementContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext + super().__init__(parser) + self.copyFrom(ctx) + + def END_OF_STATEMENT(self): + return self.getToken(qutes_parser.END_OF_STATEMENT, 0) + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterEmptyStatement" ): + listener.enterEmptyStatement(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitEmptyStatement" ): + listener.exitEmptyStatement(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitEmptyStatement" ): + return visitor.visitEmptyStatement(self) + else: + return visitor.visitChildren(self) + + + class BlockStatementContext(StatementContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext + super().__init__(parser) + self.copyFrom(ctx) + + def CURLY_PARENTHESIS_OPEN(self): + return self.getToken(qutes_parser.CURLY_PARENTHESIS_OPEN, 0) + def CURLY_PARENTHESIS_CLOSE(self): + return self.getToken(qutes_parser.CURLY_PARENTHESIS_CLOSE, 0) + def statement(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(qutes_parser.StatementContext) + else: + return self.getTypedRuleContext(qutes_parser.StatementContext,i) + + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterBlockStatement" ): + listener.enterBlockStatement(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitBlockStatement" ): + listener.exitBlockStatement(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitBlockStatement" ): + return visitor.visitBlockStatement(self) + else: + return visitor.visitChildren(self) + + + class WhileStatementContext(StatementContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext + super().__init__(parser) + self.copyFrom(ctx) + + def WHILE_STATEMENT(self): + return self.getToken(qutes_parser.WHILE_STATEMENT, 0) + def expr(self): + return self.getTypedRuleContext(qutes_parser.ExprContext,0) + + def statement(self): + return self.getTypedRuleContext(qutes_parser.StatementContext,0) + + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterWhileStatement" ): + listener.enterWhileStatement(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitWhileStatement" ): + listener.exitWhileStatement(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitWhileStatement" ): + return visitor.visitWhileStatement(self) + else: + return visitor.visitChildren(self) + + class IfStatementContext(StatementContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext @@ -441,32 +596,6 @@ def accept(self, visitor:ParseTreeVisitor): return visitor.visitChildren(self) - class FactStatementContext(StatementContext): - - def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext - super().__init__(parser) - self.copyFrom(ctx) - - def MEASURE(self): - return self.getToken(qutes_parser.MEASURE, 0) - def BARRIER(self): - return self.getToken(qutes_parser.BARRIER, 0) - - def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterFactStatement" ): - listener.enterFactStatement(self) - - def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitFactStatement" ): - listener.exitFactStatement(self) - - def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitFactStatement" ): - return visitor.visitFactStatement(self) - else: - return visitor.visitChildren(self) - - class ExpressionStatementContext(StatementContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext @@ -494,41 +623,6 @@ def accept(self, visitor:ParseTreeVisitor): return visitor.visitChildren(self) - class IfElseStatementContext(StatementContext): - - def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext - super().__init__(parser) - self.copyFrom(ctx) - - def IF_STATEMENT(self): - return self.getToken(qutes_parser.IF_STATEMENT, 0) - def expr(self): - return self.getTypedRuleContext(qutes_parser.ExprContext,0) - - def statement(self, i:int=None): - if i is None: - return self.getTypedRuleContexts(qutes_parser.StatementContext) - else: - return self.getTypedRuleContext(qutes_parser.StatementContext,i) - - def ELSE_STATEMENT(self): - return self.getToken(qutes_parser.ELSE_STATEMENT, 0) - - def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterIfElseStatement" ): - listener.enterIfElseStatement(self) - - def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitIfElseStatement" ): - listener.exitIfElseStatement(self) - - def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitIfElseStatement" ): - return visitor.visitIfElseStatement(self) - else: - return visitor.visitChildren(self) - - class ReturnStatementContext(StatementContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext @@ -558,88 +652,42 @@ def accept(self, visitor:ParseTreeVisitor): return visitor.visitChildren(self) - class EmptyStatementContext(StatementContext): - - def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext - super().__init__(parser) - self.copyFrom(ctx) - - def END_OF_STATEMENT(self): - return self.getToken(qutes_parser.END_OF_STATEMENT, 0) - - def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterEmptyStatement" ): - listener.enterEmptyStatement(self) - - def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitEmptyStatement" ): - listener.exitEmptyStatement(self) - - def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitEmptyStatement" ): - return visitor.visitEmptyStatement(self) - else: - return visitor.visitChildren(self) - - - class BlockStatementContext(StatementContext): + class ForeachStatementContext(StatementContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext super().__init__(parser) self.copyFrom(ctx) - def CURLY_PARENTHESIS_OPEN(self): - return self.getToken(qutes_parser.CURLY_PARENTHESIS_OPEN, 0) - def CURLY_PARENTHESIS_CLOSE(self): - return self.getToken(qutes_parser.CURLY_PARENTHESIS_CLOSE, 0) - def statement(self, i:int=None): + def FOREACH_STATEMENT(self): + return self.getToken(qutes_parser.FOREACH_STATEMENT, 0) + def variableDeclaration(self, i:int=None): if i is None: - return self.getTypedRuleContexts(qutes_parser.StatementContext) + return self.getTypedRuleContexts(qutes_parser.VariableDeclarationContext) else: - return self.getTypedRuleContext(qutes_parser.StatementContext,i) + return self.getTypedRuleContext(qutes_parser.VariableDeclarationContext,i) - - def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterBlockStatement" ): - listener.enterBlockStatement(self) - - def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitBlockStatement" ): - listener.exitBlockStatement(self) - - def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitBlockStatement" ): - return visitor.visitBlockStatement(self) - else: - return visitor.visitChildren(self) - - - class WhileStatementContext(StatementContext): - - def __init__(self, parser, ctx:ParserRuleContext): # actually a qutes_parser.StatementContext - super().__init__(parser) - self.copyFrom(ctx) - - def WHILE_STATEMENT(self): - return self.getToken(qutes_parser.WHILE_STATEMENT, 0) - def expr(self): - return self.getTypedRuleContext(qutes_parser.ExprContext,0) + def IN_STATEMENT(self): + return self.getToken(qutes_parser.IN_STATEMENT, 0) + def qualifiedName(self): + return self.getTypedRuleContext(qutes_parser.QualifiedNameContext,0) def statement(self): return self.getTypedRuleContext(qutes_parser.StatementContext,0) + def COMMA(self): + return self.getToken(qutes_parser.COMMA, 0) def enterRule(self, listener:ParseTreeListener): - if hasattr( listener, "enterWhileStatement" ): - listener.enterWhileStatement(self) + if hasattr( listener, "enterForeachStatement" ): + listener.enterForeachStatement(self) def exitRule(self, listener:ParseTreeListener): - if hasattr( listener, "exitWhileStatement" ): - listener.exitWhileStatement(self) + if hasattr( listener, "exitForeachStatement" ): + listener.exitForeachStatement(self) def accept(self, visitor:ParseTreeVisitor): - if hasattr( visitor, "visitWhileStatement" ): - return visitor.visitWhileStatement(self) + if hasattr( visitor, "visitForeachStatement" ): + return visitor.visitForeachStatement(self) else: return visitor.visitChildren(self) @@ -710,9 +758,9 @@ def statement(self): self.enterRule(localctx, 2, self.RULE_statement) self._la = 0 # Token type try: - self.state = 101 + self.state = 111 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,3,self._ctx) + la_ = self._interp.adaptivePredict(self._input,4,self._ctx) if la_ == 1: localctx = qutes_parser.IfStatementContext(self, localctx) self.enterOuterAlt(localctx, 1) @@ -751,118 +799,143 @@ def statement(self): pass elif la_ == 4: - localctx = qutes_parser.DoWhileStatementContext(self, localctx) + localctx = qutes_parser.ForeachStatementContext(self, localctx) self.enterOuterAlt(localctx, 4) self.state = 62 - self.match(qutes_parser.DO_STATEMENT) + self.match(qutes_parser.FOREACH_STATEMENT) self.state = 63 + self.variableDeclaration() + self.state = 66 + self._errHandler.sync(self) + _la = self._input.LA(1) + if _la==67: + self.state = 64 + self.match(qutes_parser.COMMA) + self.state = 65 + self.variableDeclaration() + + + self.state = 68 + self.match(qutes_parser.IN_STATEMENT) + self.state = 69 + self.qualifiedName() + self.state = 70 + self.statement() + pass + + elif la_ == 5: + localctx = qutes_parser.DoWhileStatementContext(self, localctx) + self.enterOuterAlt(localctx, 5) + self.state = 72 + self.match(qutes_parser.DO_STATEMENT) + self.state = 73 self.statement() - self.state = 64 + self.state = 74 self.match(qutes_parser.WHILE_STATEMENT) - self.state = 65 + self.state = 75 self.expr(0) pass - elif la_ == 5: + elif la_ == 6: localctx = qutes_parser.BlockStatementContext(self, localctx) - self.enterOuterAlt(localctx, 5) - self.state = 67 + self.enterOuterAlt(localctx, 6) + self.state = 77 self.match(qutes_parser.CURLY_PARENTHESIS_OPEN) - self.state = 71 + self.state = 81 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & 3143656578070668286) != 0) or ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): - self.state = 68 + while (((_la) & ~0x3f) == 0 and ((1 << _la) & -5870154037940657154) != 0) or ((((_la - 68)) & ~0x3f) == 0 and ((1 << (_la - 68)) & 1023) != 0): + self.state = 78 self.statement() - self.state = 73 + self.state = 83 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 74 + self.state = 84 self.match(qutes_parser.CURLY_PARENTHESIS_CLOSE) pass - elif la_ == 6: + elif la_ == 7: localctx = qutes_parser.FunctionStatementContext(self, localctx) - self.enterOuterAlt(localctx, 6) - self.state = 75 + self.enterOuterAlt(localctx, 7) + self.state = 85 self.variableType() - self.state = 76 + self.state = 86 self.functionName() - self.state = 77 + self.state = 87 self.match(qutes_parser.ROUND_PARENTHESIS_OPEN) - self.state = 79 + self.state = 89 self._errHandler.sync(self) _la = self._input.LA(1) - if (((_la) & ~0x3f) == 0 and ((1 << _la) & 510) != 0) or _la==74: - self.state = 78 + if (((_la) & ~0x3f) == 0 and ((1 << _la) & 510) != 0) or _la==76: + self.state = 88 self.functionDeclarationParams() - self.state = 81 + self.state = 91 self.match(qutes_parser.ROUND_PARENTHESIS_CLOSE) - self.state = 82 + self.state = 92 self.statement() pass - elif la_ == 7: + elif la_ == 8: localctx = qutes_parser.DeclarationStatementContext(self, localctx) - self.enterOuterAlt(localctx, 7) - self.state = 84 + self.enterOuterAlt(localctx, 8) + self.state = 94 self.variableDeclaration() - self.state = 85 + self.state = 95 self.match(qutes_parser.END_OF_STATEMENT) pass - elif la_ == 8: + elif la_ == 9: localctx = qutes_parser.AssignmentStatementContext(self, localctx) - self.enterOuterAlt(localctx, 8) - self.state = 87 + self.enterOuterAlt(localctx, 9) + self.state = 97 self.qualifiedName() - self.state = 88 + self.state = 98 self.match(qutes_parser.ASSIGN) - self.state = 89 + self.state = 99 self.expr(0) - self.state = 90 + self.state = 100 self.match(qutes_parser.END_OF_STATEMENT) pass - elif la_ == 9: + elif la_ == 10: localctx = qutes_parser.ReturnStatementContext(self, localctx) - self.enterOuterAlt(localctx, 9) - self.state = 92 + self.enterOuterAlt(localctx, 10) + self.state = 102 self.match(qutes_parser.RETURN) - self.state = 93 + self.state = 103 self.expr(0) - self.state = 94 + self.state = 104 self.match(qutes_parser.END_OF_STATEMENT) pass - elif la_ == 10: + elif la_ == 11: localctx = qutes_parser.ExpressionStatementContext(self, localctx) - self.enterOuterAlt(localctx, 10) - self.state = 96 + self.enterOuterAlt(localctx, 11) + self.state = 106 self.expr(0) - self.state = 97 + self.state = 107 self.match(qutes_parser.END_OF_STATEMENT) pass - elif la_ == 11: + elif la_ == 12: localctx = qutes_parser.FactStatementContext(self, localctx) - self.enterOuterAlt(localctx, 11) - self.state = 99 + self.enterOuterAlt(localctx, 12) + self.state = 109 _la = self._input.LA(1) - if not(_la==28 or _la==30): + if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 3489660928) != 0)): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() pass - elif la_ == 12: + elif la_ == 13: localctx = qutes_parser.EmptyStatementContext(self, localctx) - self.enterOuterAlt(localctx, 12) - self.state = 100 + self.enterOuterAlt(localctx, 13) + self.state = 110 self.match(qutes_parser.END_OF_STATEMENT) pass @@ -921,15 +994,15 @@ def functionDeclarationParams(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 103 + self.state = 113 self.variableDeclaration() - self.state = 106 + self.state = 116 self._errHandler.sync(self) _la = self._input.LA(1) - if _la==65: - self.state = 104 + if _la==67: + self.state = 114 self.match(qutes_parser.COMMA) - self.state = 105 + self.state = 115 self.functionDeclarationParams() @@ -991,17 +1064,17 @@ def variableDeclaration(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 108 + self.state = 118 self.variableType() - self.state = 109 + self.state = 119 self.variableName() - self.state = 112 + self.state = 122 self._errHandler.sync(self) _la = self._input.LA(1) - if _la==39: - self.state = 110 + if _la==40: + self.state = 120 self.match(qutes_parser.ASSIGN) - self.state = 111 + self.state = 121 self.expr(0) @@ -1544,6 +1617,8 @@ def expr(self): def PRINT(self): return self.getToken(qutes_parser.PRINT, 0) + def PRINT_LN(self): + return self.getToken(qutes_parser.PRINT_LN, 0) def PAULIY(self): return self.getToken(qutes_parser.PAULIY, 0) def PAULIZ(self): @@ -1642,19 +1717,19 @@ def expr(self, _p:int=0): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 144 + self.state = 154 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,7,self._ctx) + la_ = self._interp.adaptivePredict(self._input,8,self._ctx) if la_ == 1: localctx = qutes_parser.ParentesizeExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 115 + self.state = 125 self.match(qutes_parser.ROUND_PARENTHESIS_OPEN) - self.state = 116 + self.state = 126 self.expr(0) - self.state = 117 + self.state = 127 self.match(qutes_parser.ROUND_PARENTHESIS_CLOSE) pass @@ -1662,7 +1737,7 @@ def expr(self, _p:int=0): localctx = qutes_parser.LiteralExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 119 + self.state = 129 self.literal() pass @@ -1670,7 +1745,7 @@ def expr(self, _p:int=0): localctx = qutes_parser.QualifiedNameExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 120 + self.state = 130 self.qualifiedName() pass @@ -1678,7 +1753,7 @@ def expr(self, _p:int=0): localctx = qutes_parser.ArrayExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 121 + self.state = 131 self.array() pass @@ -1686,19 +1761,19 @@ def expr(self, _p:int=0): localctx = qutes_parser.FunctionCallExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 122 + self.state = 132 self.functionName() - self.state = 123 + self.state = 133 self.match(qutes_parser.ROUND_PARENTHESIS_OPEN) - self.state = 125 + self.state = 135 self._errHandler.sync(self) _la = self._input.LA(1) - if ((((_la - 66)) & ~0x3f) == 0 and ((1 << (_la - 66)) & 1023) != 0): - self.state = 124 + if ((((_la - 68)) & ~0x3f) == 0 and ((1 << (_la - 68)) & 1023) != 0): + self.state = 134 self.termList() - self.state = 127 + self.state = 137 self.match(qutes_parser.ROUND_PARENTHESIS_CLOSE) pass @@ -1706,15 +1781,15 @@ def expr(self, _p:int=0): localctx = qutes_parser.PrefixOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 129 + self.state = 139 localctx.op = self._input.LT(1) _la = self._input.LA(1) - if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 3298534940672) != 0)): + if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 6597069824000) != 0)): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 130 + self.state = 140 self.expr(12) pass @@ -1722,7 +1797,7 @@ def expr(self, _p:int=0): localctx = qutes_parser.MultipleUnaryOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 131 + self.state = 141 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 59244544) != 0)): @@ -1730,7 +1805,7 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 132 + self.state = 142 self.termList() pass @@ -1738,15 +1813,15 @@ def expr(self, _p:int=0): localctx = qutes_parser.UnaryOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 133 + self.state = 143 localctx.op = self._input.LT(1) _la = self._input.LA(1) - if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 942669824) != 0)): + if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 2016411648) != 0)): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 134 + self.state = 144 self.expr(3) pass @@ -1754,13 +1829,13 @@ def expr(self, _p:int=0): localctx = qutes_parser.MultipleUnaryPhaseOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 135 + self.state = 145 localctx.op = self.match(qutes_parser.MCP) - self.state = 136 + self.state = 146 self.termList() - self.state = 137 + self.state = 147 self.match(qutes_parser.BY) - self.state = 138 + self.state = 148 self.expr(2) pass @@ -1768,35 +1843,35 @@ def expr(self, _p:int=0): localctx = qutes_parser.GroverOperatorContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 140 + self.state = 150 self.termList() - self.state = 141 + self.state = 151 localctx.op = self.match(qutes_parser.IN_STATEMENT) - self.state = 142 + self.state = 152 self.qualifiedName() pass self._ctx.stop = self._input.LT(-1) - self.state = 176 + self.state = 186 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,9,self._ctx) + _alt = self._interp.adaptivePredict(self._input,10,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 174 + self.state = 184 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,8,self._ctx) + la_ = self._interp.adaptivePredict(self._input,9,self._ctx) if la_ == 1: localctx = qutes_parser.MultiplicativeOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 146 + self.state = 156 if not self.precpred(self._ctx, 11): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 11)") - self.state = 147 + self.state = 157 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 7168) != 0)): @@ -1804,18 +1879,18 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 148 + self.state = 158 self.expr(12) pass elif la_ == 2: localctx = qutes_parser.SumOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 149 + self.state = 159 if not self.precpred(self._ctx, 10): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 10)") - self.state = 150 + self.state = 160 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not(_la==13 or _la==14): @@ -1823,119 +1898,119 @@ def expr(self, _p:int=0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 151 + self.state = 161 self.expr(11) pass elif la_ == 3: localctx = qutes_parser.ShiftOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 152 + self.state = 162 if not self.precpred(self._ctx, 9): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 9)") - self.state = 153 + self.state = 163 localctx.op = self._input.LT(1) _la = self._input.LA(1) - if not(_la==37 or _la==38): + if not(_la==38 or _la==39): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 154 + self.state = 164 self.expr(10) pass elif la_ == 4: localctx = qutes_parser.RelationalOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 155 + self.state = 165 if not self.precpred(self._ctx, 8): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 8)") - self.state = 156 + self.state = 166 localctx.op = self._input.LT(1) _la = self._input.LA(1) - if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 128849018880) != 0)): + if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 257698037760) != 0)): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 157 + self.state = 167 self.expr(9) pass elif la_ == 5: localctx = qutes_parser.EqualityOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 158 + self.state = 168 if not self.precpred(self._ctx, 7): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 7)") - self.state = 159 + self.state = 169 localctx.op = self._input.LT(1) _la = self._input.LA(1) - if not(_la==31 or _la==32): + if not(_la==32 or _la==33): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 160 + self.state = 170 self.expr(8) pass elif la_ == 6: localctx = qutes_parser.LogicAndOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 161 + self.state = 171 if not self.precpred(self._ctx, 6): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 6)") - self.state = 162 + self.state = 172 localctx.op = self.match(qutes_parser.AND) - self.state = 163 + self.state = 173 self.expr(7) pass elif la_ == 7: localctx = qutes_parser.LogicOrOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 164 + self.state = 174 if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") - self.state = 165 + self.state = 175 localctx.op = self.match(qutes_parser.OR) - self.state = 166 + self.state = 176 self.expr(6) pass elif la_ == 8: localctx = qutes_parser.ArrayAccessExpressionContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 167 + self.state = 177 if not self.precpred(self._ctx, 14): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 14)") - self.state = 168 + self.state = 178 self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) - self.state = 169 + self.state = 179 self.expr(0) - self.state = 170 + self.state = 180 self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) pass elif la_ == 9: localctx = qutes_parser.PostfixOperatorContext(self, qutes_parser.ExprContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 172 + self.state = 182 if not self.precpred(self._ctx, 13): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 13)") - self.state = 173 + self.state = 183 localctx.op = self._input.LT(1) _la = self._input.LA(1) - if not(_la==40 or _la==41): + if not(_la==41 or _la==42): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) @@ -1943,9 +2018,9 @@ def expr(self, _p:int=0): pass - self.state = 178 + self.state = 188 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,9,self._ctx) + _alt = self._interp.adaptivePredict(self._input,10,self._ctx) except RecognitionException as re: localctx.exception = re @@ -2004,27 +2079,27 @@ def termList(self): self.enterRule(localctx, 10, self.RULE_termList) try: self.enterOuterAlt(localctx, 1) - self.state = 181 + self.state = 191 self._errHandler.sync(self) token = self._input.LA(1) - if token in [66, 67, 68, 69, 70, 71, 72, 73, 75]: - self.state = 179 + if token in [68, 69, 70, 71, 72, 73, 74, 75, 77]: + self.state = 189 self.literal() pass - elif token in [74]: - self.state = 180 + elif token in [76]: + self.state = 190 self.qualifiedName() pass else: raise NoViableAltException(self) - self.state = 185 + self.state = 195 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,11,self._ctx) + la_ = self._interp.adaptivePredict(self._input,12,self._ctx) if la_ == 1: - self.state = 183 + self.state = 193 self.match(qutes_parser.COMMA) - self.state = 184 + self.state = 194 self.termList() @@ -2080,11 +2155,11 @@ def array(self): self.enterRule(localctx, 12, self.RULE_array) try: self.enterOuterAlt(localctx, 1) - self.state = 187 + self.state = 197 self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) - self.state = 188 + self.state = 198 self.termList() - self.state = 189 + self.state = 199 self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) except RecognitionException as re: localctx.exception = re @@ -2142,35 +2217,35 @@ def variableType(self): self.enterRule(localctx, 14, self.RULE_variableType) self._la = 0 # Token type try: - self.state = 201 + self.state = 211 self._errHandler.sync(self) token = self._input.LA(1) if token in [1, 2, 3, 4, 5, 6, 7, 8]: self.enterOuterAlt(localctx, 1) - self.state = 191 + self.state = 201 self.type_() - self.state = 194 + self.state = 204 self._errHandler.sync(self) _la = self._input.LA(1) - if _la==61: - self.state = 192 + if _la==63: + self.state = 202 self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) - self.state = 193 + self.state = 203 self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) pass - elif token in [74]: + elif token in [76]: self.enterOuterAlt(localctx, 2) - self.state = 196 + self.state = 206 self.qualifiedName() - self.state = 199 + self.state = 209 self._errHandler.sync(self) _la = self._input.LA(1) - if _la==61: - self.state = 197 + if _la==63: + self.state = 207 self.match(qutes_parser.SQUARE_PARENTHESIS_OPEN) - self.state = 198 + self.state = 208 self.match(qutes_parser.SQUARE_PARENTHESIS_CLOSE) @@ -2245,7 +2320,7 @@ def type_(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 203 + self.state = 213 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & 510) != 0)): self._errHandler.recoverInline(self) @@ -2313,37 +2388,37 @@ def qualifiedName(self): localctx = qutes_parser.QualifiedNameContext(self, self._ctx, self.state) self.enterRule(localctx, 18, self.RULE_qualifiedName) try: - self.state = 215 + self.state = 225 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,16,self._ctx) + la_ = self._interp.adaptivePredict(self._input,17,self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 205 + self.state = 215 self.match(qutes_parser.SYMBOL_LITERAL) - self.state = 210 + self.state = 220 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,15,self._ctx) + _alt = self._interp.adaptivePredict(self._input,16,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: - self.state = 206 + self.state = 216 self.match(qutes_parser.DOT) - self.state = 207 + self.state = 217 self.match(qutes_parser.SYMBOL_LITERAL) - self.state = 212 + self.state = 222 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,15,self._ctx) + _alt = self._interp.adaptivePredict(self._input,16,self._ctx) pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 213 + self.state = 223 self.variableName() pass elif la_ == 3: self.enterOuterAlt(localctx, 3) - self.state = 214 + self.state = 224 self.functionName() pass @@ -2393,7 +2468,7 @@ def variableName(self): self.enterRule(localctx, 20, self.RULE_variableName) try: self.enterOuterAlt(localctx, 1) - self.state = 217 + self.state = 227 self.match(qutes_parser.SYMBOL_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2440,7 +2515,7 @@ def functionName(self): self.enterRule(localctx, 22, self.RULE_functionName) try: self.enterOuterAlt(localctx, 1) - self.state = 219 + self.state = 229 self.match(qutes_parser.SYMBOL_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2511,42 +2586,42 @@ def literal(self): localctx = qutes_parser.LiteralContext(self, self._ctx, self.state) self.enterRule(localctx, 24, self.RULE_literal) try: - self.state = 228 + self.state = 238 self._errHandler.sync(self) token = self._input.LA(1) - if token in [66]: + if token in [68]: self.enterOuterAlt(localctx, 1) - self.state = 221 + self.state = 231 self.boolean() pass - elif token in [67, 69, 70]: + elif token in [69, 71, 72]: self.enterOuterAlt(localctx, 2) - self.state = 222 + self.state = 232 self.integer() pass - elif token in [68]: + elif token in [70]: self.enterOuterAlt(localctx, 3) - self.state = 223 + self.state = 233 self.float_() pass - elif token in [71]: + elif token in [73]: self.enterOuterAlt(localctx, 4) - self.state = 224 + self.state = 234 self.qubit() pass - elif token in [72]: + elif token in [74]: self.enterOuterAlt(localctx, 5) - self.state = 225 + self.state = 235 self.quint() pass - elif token in [73]: + elif token in [75]: self.enterOuterAlt(localctx, 6) - self.state = 226 + self.state = 236 self.qustring() pass - elif token in [75]: + elif token in [77]: self.enterOuterAlt(localctx, 7) - self.state = 227 + self.state = 237 self.string() pass else: @@ -2597,7 +2672,7 @@ def string(self): self.enterRule(localctx, 26, self.RULE_string) try: self.enterOuterAlt(localctx, 1) - self.state = 230 + self.state = 240 self.match(qutes_parser.STRING_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2644,7 +2719,7 @@ def qubit(self): self.enterRule(localctx, 28, self.RULE_qubit) try: self.enterOuterAlt(localctx, 1) - self.state = 232 + self.state = 242 self.match(qutes_parser.QUBIT_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2691,7 +2766,7 @@ def quint(self): self.enterRule(localctx, 30, self.RULE_quint) try: self.enterOuterAlt(localctx, 1) - self.state = 234 + self.state = 244 self.match(qutes_parser.QUINT_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2738,7 +2813,7 @@ def qustring(self): self.enterRule(localctx, 32, self.RULE_qustring) try: self.enterOuterAlt(localctx, 1) - self.state = 236 + self.state = 246 self.match(qutes_parser.QUSTRING_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2785,7 +2860,7 @@ def float_(self): self.enterRule(localctx, 34, self.RULE_float) try: self.enterOuterAlt(localctx, 1) - self.state = 238 + self.state = 248 self.match(qutes_parser.FLOAT_LITERAL) except RecognitionException as re: localctx.exception = re @@ -2839,9 +2914,9 @@ def integer(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 240 + self.state = 250 _la = self._input.LA(1) - if not(((((_la - 67)) & ~0x3f) == 0 and ((1 << (_la - 67)) & 13) != 0)): + if not(((((_la - 69)) & ~0x3f) == 0 and ((1 << (_la - 69)) & 13) != 0)): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) @@ -2891,7 +2966,7 @@ def boolean(self): self.enterRule(localctx, 38, self.RULE_boolean) try: self.enterOuterAlt(localctx, 1) - self.state = 242 + self.state = 252 self.match(qutes_parser.BOOL_LITERAL) except RecognitionException as re: localctx.exception = re diff --git a/src/qutes_antlr/qutes_parser.tokens b/src/qutes_antlr/qutes_parser.tokens index 9f5f556..e0fc4d9 100644 --- a/src/qutes_antlr/qutes_parser.tokens +++ b/src/qutes_antlr/qutes_parser.tokens @@ -27,54 +27,56 @@ MCP=26 HADAMARD=27 MEASURE=28 PRINT=29 -BARRIER=30 -EQUAL=31 -NOT_EQUAL=32 -GREATER=33 -GREATEREQUAL=34 -LOWER=35 -LOWEREQUAL=36 -LSHIFT=37 -RSHIFT=38 -ASSIGN=39 -AUTO_INCREMENT=40 -AUTO_DECREMENT=41 -AUTO_SUM=42 -AUTO_SUB=43 -AUTO_MULTIPLY=44 -AUTO_DIVIDE=45 -AUTO_MODULE=46 -END_OF_STATEMENT=47 -VAR_STATEMENT=48 -FOR_STATEMENT=49 -SEARCH_STATEMENT=50 -IN_STATEMENT=51 -WHERE_STATEMENT=52 -IF_STATEMENT=53 -ELSE_STATEMENT=54 -WHILE_STATEMENT=55 -DO_STATEMENT=56 -CURLY_PARENTHESIS_OPEN=57 -CURLY_PARENTHESIS_CLOSE=58 -ROUND_PARENTHESIS_OPEN=59 -ROUND_PARENTHESIS_CLOSE=60 -SQUARE_PARENTHESIS_OPEN=61 -SQUARE_PARENTHESIS_CLOSE=62 -DOT=63 -STRING_ENCLOSURE=64 -COMMA=65 -BOOL_LITERAL=66 -INT_LITERAL=67 -FLOAT_LITERAL=68 -HEX_LITERAL=69 -BIN_LITERAL=70 -QUBIT_LITERAL=71 -QUINT_LITERAL=72 -QUSTRING_LITERAL=73 -SYMBOL_LITERAL=74 -STRING_LITERAL=75 -WS=76 -NEWLINE=77 +PRINT_LN=30 +BARRIER=31 +EQUAL=32 +NOT_EQUAL=33 +GREATER=34 +GREATEREQUAL=35 +LOWER=36 +LOWEREQUAL=37 +LSHIFT=38 +RSHIFT=39 +ASSIGN=40 +AUTO_INCREMENT=41 +AUTO_DECREMENT=42 +AUTO_SUM=43 +AUTO_SUB=44 +AUTO_MULTIPLY=45 +AUTO_DIVIDE=46 +AUTO_MODULE=47 +END_OF_STATEMENT=48 +VAR_STATEMENT=49 +FOR_STATEMENT=50 +FOREACH_STATEMENT=51 +SEARCH_STATEMENT=52 +IN_STATEMENT=53 +WHERE_STATEMENT=54 +IF_STATEMENT=55 +ELSE_STATEMENT=56 +WHILE_STATEMENT=57 +DO_STATEMENT=58 +CURLY_PARENTHESIS_OPEN=59 +CURLY_PARENTHESIS_CLOSE=60 +ROUND_PARENTHESIS_OPEN=61 +ROUND_PARENTHESIS_CLOSE=62 +SQUARE_PARENTHESIS_OPEN=63 +SQUARE_PARENTHESIS_CLOSE=64 +DOT=65 +STRING_ENCLOSURE=66 +COMMA=67 +BOOL_LITERAL=68 +INT_LITERAL=69 +FLOAT_LITERAL=70 +HEX_LITERAL=71 +BIN_LITERAL=72 +QUBIT_LITERAL=73 +QUINT_LITERAL=74 +QUSTRING_LITERAL=75 +SYMBOL_LITERAL=76 +STRING_LITERAL=77 +WS=78 +NEWLINE=79 'int'=1 'bool'=2 'string'=3 @@ -104,39 +106,41 @@ NEWLINE=77 'hadamard'=27 'measure'=28 'print'=29 -'barrier'=30 -'=='=31 -'!='=32 -'>'=33 -'>='=34 -'<'=35 -'<='=36 -'<<'=37 -'>>'=38 -'='=39 -'++'=40 -'--'=41 -'+='=42 -'-='=43 -'*='=44 -'/='=45 -'%='=46 -';'=47 -'var'=48 -'for'=49 -'search'=50 -'in'=51 -'where'=52 -'if'=53 -'else'=54 -'while'=55 -'do'=56 -'{'=57 -'}'=58 -'('=59 -')'=60 -'['=61 -']'=62 -'.'=63 -'"'=64 -','=65 +'println'=30 +'barrier'=31 +'=='=32 +'!='=33 +'>'=34 +'>='=35 +'<'=36 +'<='=37 +'<<'=38 +'>>'=39 +'='=40 +'++'=41 +'--'=42 +'+='=43 +'-='=44 +'*='=45 +'/='=46 +'%='=47 +';'=48 +'var'=49 +'for'=50 +'foreach'=51 +'search'=52 +'in'=53 +'where'=54 +'if'=55 +'else'=56 +'while'=57 +'do'=58 +'{'=59 +'}'=60 +'('=61 +')'=62 +'['=63 +']'=64 +'.'=65 +'"'=66 +','=67 diff --git a/src/qutes_antlr/qutes_parserListener.py b/src/qutes_antlr/qutes_parserListener.py index 56734dd..ccfe70b 100644 --- a/src/qutes_antlr/qutes_parserListener.py +++ b/src/qutes_antlr/qutes_parserListener.py @@ -44,6 +44,15 @@ def exitWhileStatement(self, ctx:qutes_parser.WhileStatementContext): pass + # Enter a parse tree produced by qutes_parser#ForeachStatement. + def enterForeachStatement(self, ctx:qutes_parser.ForeachStatementContext): + pass + + # Exit a parse tree produced by qutes_parser#ForeachStatement. + def exitForeachStatement(self, ctx:qutes_parser.ForeachStatementContext): + pass + + # Enter a parse tree produced by qutes_parser#DoWhileStatement. def enterDoWhileStatement(self, ctx:qutes_parser.DoWhileStatementContext): pass diff --git a/src/qutes_antlr/qutes_parserVisitor.py b/src/qutes_antlr/qutes_parserVisitor.py index 0191cc7..c603ff6 100644 --- a/src/qutes_antlr/qutes_parserVisitor.py +++ b/src/qutes_antlr/qutes_parserVisitor.py @@ -29,6 +29,11 @@ def visitWhileStatement(self, ctx:qutes_parser.WhileStatementContext): return self.visitChildren(ctx) + # Visit a parse tree produced by qutes_parser#ForeachStatement. + def visitForeachStatement(self, ctx:qutes_parser.ForeachStatementContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by qutes_parser#DoWhileStatement. def visitDoWhileStatement(self, ctx:qutes_parser.DoWhileStatementContext): return self.visitChildren(ctx) From d3162037aa93edaa172e3913aeed6ffdedea83a9 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:28:56 +0000 Subject: [PATCH 25/34] Refactor and fix variable quantum register creation and update --- src/grammar_frontend/qutes_base_visitor.py | 1 + .../quantum_circuit_handler.py | 34 +++++++++++-------- src/quantum_circuit/qutes_gates.py | 4 +-- src/qutes.py | 2 +- src/symbols/variables_handler.py | 4 ++- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/grammar_frontend/qutes_base_visitor.py b/src/grammar_frontend/qutes_base_visitor.py index d39a404..b84b6e7 100644 --- a/src/grammar_frontend/qutes_base_visitor.py +++ b/src/grammar_frontend/qutes_base_visitor.py @@ -21,6 +21,7 @@ def __init__(self, symbols_tree:ScopeTreeNode, quantum_circuit_handler : Quantum # Debug flags Symbol.verbose_print = verbose + ScopeHandlerForSymbolsUpdate.print_trace = False self.allow_program_print = True self.log_code_structure = False self.log_trace_enabled = False diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 44cdda2..9f8578d 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -53,22 +53,21 @@ def declare_quantum_register(self, variable_name : str, quantum_variable : Qubit self._registers_states[new_register] = quantum_variable.qubit_state return new_register - # TODO: this should be a correlation operation, or a measure and then update. - # We cannot rely on quantum_variable.qubit_state - def replace_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring) -> QuantumRegister: + # TODO: this should be a correlation operation, or a measure and then update, + # because we cannot rely on quantum_variable.qubit_state + def create_and_assign_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring) -> QuantumRegister: register_to_update = self._varname_to_register[variable_name] if(register_to_update is None): raise SystemError("Error trying to update an undeclared quantum register") if(QutesDataType.is_quantum_type(QutesDataType.type_of(quantum_variable))): #TODO-CRITICAL: this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value and changing the name from update to replace. - #Delete old quantum register and reference - del self._registers_states[register_to_update] - self._quantum_registers.remove(register_to_update) #Add new quantum register - register_to_update = self._varname_to_register[variable_name] = QuantumRegister(quantum_variable.size, variable_name) - self._quantum_registers.append(register_to_update) + register_to_update = self.assign_quantum_register_to_variable(variable_name, QuantumRegister(quantum_variable.size, variable_name)) + if register_to_update not in self._quantum_registers: + self._quantum_registers.append(register_to_update) self._registers_states[register_to_update] = quantum_variable.qubit_state + self.__cleanup_orphan_registers() else: raise SystemError("Error trying to update a quantum register with an unsupported type") @@ -80,17 +79,22 @@ def assign_quantum_register_to_variable(self, variable_name : str, quantum_regi raise SystemError("Error trying to update an undeclared quantum register") #TODO-CRITICAL(pasted from above, i don't know if this applies here too): this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value and changing the name from update to replace. - - #TODO: check if we need to change the register size - #TODO: i don't know why we don't save the new quantum_register to the internal data structures. if(register_to_update != quantum_register): - #Delete old quantum register reference from the variable - del self._registers_states[register_to_update] - self._quantum_registers.remove(register_to_update) - #Assign already created register reference to the variable self._varname_to_register[variable_name] = quantum_register + self.__cleanup_orphan_registers() return quantum_register + def remove_quantum_register(self, quantum_register : QuantumRegister) -> None: + if self._registers_states.get(quantum_register) is not None: + del self._registers_states[quantum_register] + if quantum_register in self._quantum_registers: + self._quantum_registers.remove(quantum_register) + + def __cleanup_orphan_registers(self): + to_delete = [qreg for qreg in self._quantum_registers if not any([qreg == reg for reg in self._varname_to_register.values()])] + for qreg in to_delete: + self.remove_quantum_register(qreg) + def start_quantum_function(self): self._operation_stacks.append([]) self._current_operation_stack = self._operation_stacks[-1] diff --git a/src/quantum_circuit/qutes_gates.py b/src/quantum_circuit/qutes_gates.py index 188f06b..99fd550 100644 --- a/src/quantum_circuit/qutes_gates.py +++ b/src/quantum_circuit/qutes_gates.py @@ -52,9 +52,9 @@ def sum(self, var_a_symbol:'Symbol', var_b_symbol:'Symbol') -> 'Symbol': number_bits_number = max(var_a.size, var_b.size) if(var_a.size != number_bits_number): - var_a = self.ciruit_handler.replace_quantum_register(var_a_name, var_a.value.update_size_with_padding(number_bits_number)) + var_a = self.ciruit_handler.create_and_assign_quantum_register(var_a_name, var_a.value.update_size_with_padding(number_bits_number)) if(var_b.size != number_bits_number): - var_b = self.ciruit_handler.replace_quantum_register(var_b_name, var_b.value.update_size_with_padding(number_bits_number)) + var_b = self.ciruit_handler.create_and_assign_quantum_register(var_b_name, var_b.value.update_size_with_padding(number_bits_number)) carry = handler.declare_quantum_register(f"carry{self.count}", Qubit()) ancilla = handler.declare_quantum_register(f"ancilla{self.count}", Quint.init_from_size(5)) diff --git a/src/qutes.py b/src/qutes.py index 73db791..5d8af6a 100644 --- a/src/qutes.py +++ b/src/qutes.py @@ -44,7 +44,7 @@ def main(argv): quantum_circuit_handler = QuantumCircuitHandler() - grammar_listener = SymbolsDiscoveryVisitor(quantum_circuit_handler) + grammar_listener = SymbolsDiscoveryVisitor(quantum_circuit_handler, args.log_verbose) grammar_listener.visit(tree) symbols_tree = grammar_listener.scope_handler.symbols_tree diff --git a/src/symbols/variables_handler.py b/src/symbols/variables_handler.py index 970c3cc..637b637 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -50,7 +50,7 @@ def update_variable_state(self, variable_name : str, new_state) -> Symbol: #Handle quantum circuit update if(QutesDataType.is_quantum_type(symbol_to_update.symbol_declaration_static_type)): if(new_state.is_anonymous): - symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.replace_quantum_register(variable_name, value_to_assign) + symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.create_and_assign_quantum_register(variable_name, value_to_assign) if(new_state.is_quantum()): self.quantum_cirtcuit_handler.delete_variable(new_state.name) else: @@ -90,6 +90,8 @@ def create_symbol(self, qutes_type : QutesDataType, value, ast_token_index:int) value = QutesDataType.get_default_value(qutes_type) #TODO: in case of arrays, we need to check whether the elements are of the same type, and if any type cast is needed. + # also we need to create a quantum register for the array if it is a quantum type. + # and modify type handler to return true for quantum check even for array types. variable_name = None value_qutes_type = QutesDataType.type_of(value) definition_type = qutes_type From cf20f001c886c8cde0e889407f65827b3e1c8fdb Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:29:27 +0000 Subject: [PATCH 26/34] Add println operation to grammar, print now doesn't end with new line --- src/grammar_frontend/operation.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index a2252f4..1b5baa0 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -184,27 +184,15 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p if(self.log_code_structure): print(f"{first_term_symbol} {ctx.op.text}", end=None) if(isinstance(ctx, qutes_parser.UnaryOperatorContext)): - if(ctx.PRINT()): + if(ctx.PRINT() or ctx.PRINT_LN()): if(first_term_symbol): if(QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): - #TODO: we don't use any of this computed values, why? classical_register = self.quantum_circuit_handler.run_and_measure([first_term_symbol.quantum_register]) - bytes_str = [reg.measured_values[0] for reg in classical_register if first_term_symbol.quantum_register.name in reg.name][0] - if(first_term_symbol.symbol_declaration_static_type == QutesDataType.qustring): - index = 0 - string_value = "" - while index < first_term_symbol.value.number_of_chars * first_term_symbol.symbol_declaration_static_type.get_unit_size_in_qubit(): - bin_char = bytes_str[index:first_term_symbol.symbol_declaration_static_type.get_unit_size_in_qubit() + index] - string_value = string_value + Qustring.get_char_from_int(int(bin_char, 2)) - index = index + first_term_symbol.symbol_declaration_static_type.get_unit_size_in_qubit() - else: - new_value = int(bytes_str, 2) - #TODO: handle the conversion from a string of binadry digits to the current quantum variable type #TODO: adding the next line cause a crash in the circuit # self.variables_handler.update_variable_state(first_term_symbol.name, new_value) - print(first_term_symbol) + print(first_term_symbol, end=("" if ctx.PRINT() else "\n")) else: - print(first_term_value) + print(first_term_value, end=("" if ctx.PRINT() else "\n")) if(ctx.PAULIY()): if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): result = self.quantum_circuit_handler.push_pauliy_operation(first_term_symbol.quantum_register) From 9019452951987eb6b5033cfba0c248ebbd3c3106 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 21:29:52 +0000 Subject: [PATCH 27/34] Updates examples for arrays and bb84 protocol --- playground/examples/arrays.qut | 47 +++- .../quantum_key_distribution_bb84.qut | 229 +++--------------- ...tum_key_distribution_bb84_eyesdropping.qut | 55 +++++ 3 files changed, 130 insertions(+), 201 deletions(-) create mode 100644 playground/examples/quantum_key_distribution_bb84_eyesdropping.qut diff --git a/playground/examples/arrays.qut b/playground/examples/arrays.qut index 05bfba1..61bae4b 100644 --- a/playground/examples/arrays.qut +++ b/playground/examples/arrays.qut @@ -1,14 +1,47 @@ +// string[] bob_bases = ["1","0","1","0","1","0","1","0"]; +// foreach string base in bob_bases{ +// if(bob_bases[0] == base){ +// print base; +// } +// else{ +// print base; +// } +// } +// foreach string base, int index in bob_bases{ +// print "start"; +// print index; +// print base; +// print bob_bases[index]; +// print "end"; +// } + qubit b = 1q; qubit c = 0q; qubit[] a = [b, c, |+>]; qubit d = a[2]; -int i = 0; -while(i<3){ - print a[i]; - i = i + 1; +foreach qubit q in a{ + print q; +} + +int[] ba = [2, 3]; +foreach int q in ba{ + print q; } -print d; -print a; -print c; \ No newline at end of file +// print d; +// print a; +// print c; + +//========================================================= + +// int[] foo = [6, 2, 3]; +// print foo; +// print foo[1]; + +// int count=0; +// foreach int i in foo{ +// print i; +// count = count + i; +// } +// print count; \ No newline at end of file diff --git a/playground/examples/quantum_key_distribution_bb84.qut b/playground/examples/quantum_key_distribution_bb84.qut index 8cef717..084c350 100644 --- a/playground/examples/quantum_key_distribution_bb84.qut +++ b/playground/examples/quantum_key_distribution_bb84.qut @@ -1,212 +1,53 @@ -int n = 8; //number of qubits - //Alice create a random binary sequence -string message_0 = "1"; -string message_1 = "0"; -string message_2 = "1"; -string message_3 = "0"; -string message_4 = "0"; -string message_5 = "1"; -string message_6 = "0"; -string message_7 = "1"; +qubit[] original_message = [0q, 0q, 0q, 0q, 0q, 0q, 0q, 0q]; +qubit[] message = [0q, 0q, 0q, 0q, 0q, 0q, 0q, 0q]; //Alice create a random binary sequence of basis -string alice_bases0 = "1"; -string alice_bases1 = "1"; -string alice_bases2 = "0"; -string alice_bases3 = "0"; -string alice_bases4 = "0"; -string alice_bases5 = "1"; -string alice_bases6 = "1"; -string alice_bases7 = "1"; +string[] alice_bases = ["1","1","0","0","0","1","1","1"]; //Alice encodes the message with the basis //for each character in message, if the corresponding character in bases is 0, then encode the character in Z basis, otherwise in X basis -qubit alice_0 = 1q; -qubit alice_1 = 0q; -qubit alice_2 = 1q; -qubit alice_3 = 0q; -qubit alice_4 = 0q; -qubit alice_5 = 1q; -qubit alice_6 = 0q; -qubit alice_7 = 1q; - -//Bob create a random binary sequence of basis -string bob_bases0 = "1"; -string bob_bases1 = "0"; -string bob_bases2 = "1"; -string bob_bases3 = "0"; -string bob_bases4 = "1"; -string bob_bases5 = "0"; -string bob_bases6 = "1"; -string bob_bases7 = "0"; - - -if (alice_bases0 == "0"){ - //encode message_1 in Z basis - //do nothing. -} else { - //encode message_0 in X basis - hadamard alice_0; -} -if (alice_bases1 == "0"){ - //encode message_1 in Z basis - //do nothing. -} else { - //encode message_1 in X basis - hadamard alice_1; -} -if (alice_bases2 == "0"){ - //encode message_2 in Z basis - //do nothing. -} else { - //encode message_2 in X basis - hadamard alice_2; -} -if (alice_bases3 == "0"){ - //encode message_3 in Z basis - //do nothing. -} else { - //encode message_3 in X basis - hadamard alice_3; -} -if (alice_bases4 == "0"){ - //encode message_4 in Z basis - //do nothing. -} else { - //encode message_4 in X basis - hadamard alice_4; +foreach string base, int index in alice_bases{ + if(base == "0"){ + //encode message in Z basis + //do nothing + } else { + //encode message in X basis + hadamard message[index]; + } } -if (alice_bases5 == "0"){ - //encode message_5 in Z basis - //do nothing. -} else { - //encode message_5 in X basis - hadamard alice_5; -} -if (alice_bases6 == "0"){ - //encode message_6 in Z basis - //do nothing. -} else { - //encode message_6 in X basis - hadamard alice_6; -} -if (alice_bases7 == "0"){ - //encode message_7 in Z basis - //do nothing. -} else { - //encode message_7 in X basis - hadamard alice_7; -} - -//Alice sends the encoded message to Bob +// -----> Alice sends the encoded message to Bob +// <----- Bob receives the encoded message from Alice +//Bob create a random binary sequence of basis +string[] bob_bases = ["1","0","1","0","1","0","1","0"]; - - -if (bob_bases0 == "0"){ - //encode message_1 in Z basis - //do nothing. -} else { - //encode message_0 in X basis - hadamard alice_0; -} - -if (bob_bases1 == "0"){ - //encode message_1 in Z basis - //do nothing. -} else { - //encode message_1 in X basis - hadamard alice_1; -} -if (bob_bases2 == "0"){ - //encode message_2 in Z basis - //do nothing. -} else { - //encode message_2 in X basis - hadamard alice_2; -} -if (bob_bases3 == "0"){ - //encode message_3 in Z basis - //do nothing. -} else { - //encode message_3 in X basis - hadamard alice_3; -} -if (bob_bases4 == "0"){ - //encode message_4 in Z basis - //do nothing. -} else { - //encode message_4 in X basis - hadamard alice_4; -} -if (bob_bases5 == "0"){ - //encode message_5 in Z basis - //do nothing. -} else { - //encode message_5 in X basis - hadamard alice_5; +foreach string base, int index in bob_bases{ + if(base == "0"){ + //encode message in Z basis + //do nothing + } else { + //encode message in X basis + hadamard message[index]; + } } -if (bob_bases6 == "0"){ - //encode message_6 in Z basis - //do nothing. -} else { - //encode message_6 in X basis - hadamard alice_6; -} -if (bob_bases7 == "0"){ - //encode message_7 in Z basis - //do nothing. -} else { - //encode message_7 in X basis - hadamard alice_7; -} - - +// <----> Alice and Bob reveal their bases to each other -if(bob_bases0 == alice_bases0){ - print "Index 0 match so it can be used to create a key"; - print alice_0; - print message_0; -} -if(bob_bases1 == alice_bases1){ - print "Index 1 match so it can be used to create a key"; - print alice_1; - print message_1; -} -if(bob_bases2 == alice_bases2){ - print "Index 2 match so it can be used to create a key"; - print alice_2; - print message_2; -} -if(bob_bases3 == alice_bases3){ - print "Index 3 match so it can be used to create a key"; - print alice_3; - print message_3; -} -if(bob_bases4 == alice_bases4){ - print "Index 4 match so it can be used to create a key"; - print alice_4; - print message_4; -} -if(bob_bases5 == alice_bases5){ - print "Index 5 match so it can be used to create a key"; - print alice_5; - print message_5; -} -if(bob_bases6 == alice_bases6){ - print "Index 6 match so it can be used to create a key"; - print alice_6; - print message_6; -} -if(bob_bases7 == alice_bases7){ - print "Index 7 match so it can be used to create a key"; - print alice_7; - print message_7; +//Alice and Bob compare their bases and discard the bits where their bases do not match +foreach string base, int index in bob_bases{ + if(alice_bases[index] == base){ + print "Index match so it can be used to create a key, index: "; + print index; + print " that correspond to this original message: "; + print original_message[index]; + println; + } } +measure; + print "If the above values matches, then no one is eyesdropping."; \ No newline at end of file diff --git a/playground/examples/quantum_key_distribution_bb84_eyesdropping.qut b/playground/examples/quantum_key_distribution_bb84_eyesdropping.qut new file mode 100644 index 0000000..cc76a17 --- /dev/null +++ b/playground/examples/quantum_key_distribution_bb84_eyesdropping.qut @@ -0,0 +1,55 @@ +//Alice create a random binary sequence +string[] original_message = ["1", "0", "1", "0", "0", "1", "0", "1"]; +qubit[] message = [1q, 0q, 1q, 0q, 0q, 1q, 0q, 1q]; + +//Alice create a random binary sequence of basis +string[] alice_bases = ["1","1","0","0","0","1","1","1"]; + +//Alice encodes the message with the basis +//for each character in message, if the corresponding character in bases is 0, then encode the character in Z basis, otherwise in X basis +foreach string base, int index in alice_bases{ + if(base == "0"){ + //encode message in Z basis + //do nothing + } else { + //encode message in X basis + hadamard message[index]; + } +} + +// -----> Alice sends the encoded message to Bob +// --X--> But Eve intercepts the message and tries to decode it +measure; +// <----- Bob receives the encoded message from Alice + + +//Bob create a random binary sequence of basis +string[] bob_bases = ["1","0","1","0","1","0","1","0"]; + +foreach string base, int index in bob_bases{ + if(base == "0"){ + //encode message in Z basis + //do nothing + } else { + //encode message in X basis + hadamard message[index]; + } +} + + +// <----> Alice and Bob reveal their bases to each other + +//Alice and Bob compare their bases and discard the bits where their bases do not match +foreach string base, int index in bob_bases{ + if(alice_bases[index] == base){ + print "Index match so it can be used to create a key, index: "; + print index; + print " that correspond to this original message: "; + print original_message[index]; + println; + } +} + +measure; + +print "If the measured values matches the printed ones, then no one is eyesdropping."; \ No newline at end of file From 01370016b44c970b3e26f33e1730442a61cdf734 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 22:17:05 +0000 Subject: [PATCH 28/34] Fix array access return a literal instead of a Symbol --- src/grammar_frontend/expression.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/grammar_frontend/expression.py b/src/grammar_frontend/expression.py index 42bec33..57303c9 100644 --- a/src/grammar_frontend/expression.py +++ b/src/grammar_frontend/expression.py @@ -74,4 +74,7 @@ def visitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionConte array_value = self.variables_handler.get_value(array_symbol) index_value = self.variables_handler.get_value(index_symbol) - return array_value[index_value] + value = array_value[index_value] + if not isinstance(value, Symbol): + value = self.variables_handler.declare_anonymous_variable(QutesDataType.get_unit_type_from_array_type(array_symbol.casted_static_type), value, array_symbol.ast_token_index) + return value From fa9485c6ba24ac887abcf8be2284f348e1a04a47 Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Sun, 18 Aug 2024 22:17:42 +0000 Subject: [PATCH 29/34] Add comment in measure operation --- src/grammar_frontend/operation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/grammar_frontend/operation.py b/src/grammar_frontend/operation.py index 1b5baa0..2f37fb7 100644 --- a/src/grammar_frontend/operation.py +++ b/src/grammar_frontend/operation.py @@ -204,7 +204,10 @@ def __visit_unary_operator(self, ctx:qutes_parser.UnaryOperatorContext | qutes_p result = self.quantum_circuit_handler.push_hadamard_operation(first_term_symbol.quantum_register) if(ctx.MEASURE()): if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)): - #TODO: at the moment we return just the first measure value as result, but when array type got implemented, then we should return a list. + #TODO: at the moment we return just the first measure value as result, but when array type got implemented, then we should return a list. + # but also, the result will have the right value only after the circuit is run. + # we should measure immediately? or avoid to return anything? + # we already measure immediately on assignment. result = self.quantum_circuit_handler.push_measure_operation([first_term_symbol.quantum_register])[0].measured_values if(isinstance(ctx, qutes_parser.PrefixOperatorContext)): if(ctx.ADD()): From b6e2751e07b829d508b9535a7a67f48e48d22b9a Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Mon, 19 Aug 2024 18:47:00 +0000 Subject: [PATCH 30/34] Handled type casting to/from array types --- .../quantum_circuit_handler.py | 4 +- src/symbols/symbol.py | 3 - src/symbols/types/quint.py | 6 +- src/symbols/types/qustring.py | 2 + src/symbols/types/qutes_data_type.py | 19 ++++ src/symbols/types/type_casting_handler.py | 88 ++++++++++++++----- 6 files changed, 92 insertions(+), 30 deletions(-) diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 9f8578d..412964d 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -224,9 +224,9 @@ def run_and_measure(self, quantum_registers : list[QuantumRegister] = None, clas (_, classical_registers) = self.get_run_and_measure_results(quantum_registers, classical_registers, repetition, max_results, print_count) return classical_registers - def get_run_and_measure_result_for_quantum_var(self, quantum_register : QuantumRegister, classical_register : ClassicalRegister = None, repetition = 1, max_results = 1, print_count:bool = False) -> tuple[str, ClassicalRegister]: + def get_run_and_measure_result_for_quantum_var(self, quantum_register : QuantumRegister, classical_register : ClassicalRegister = None, repetition = 1, max_results = 1, print_count:bool = False) -> list[str]: (_, classical_register) = self.get_run_and_measure_results([quantum_register], [classical_register] if classical_register != None else None, repetition, max_results, print_count) - return (classical_register[0].measured_values[0], classical_register[0]) + return classical_register[0].measured_values[0] def push_not_operation(self, quantum_register : QuantumRegister) -> None: self._current_operation_stack.append(lambda circuit : cast(QuantumCircuit, circuit).x(quantum_register)) diff --git a/src/symbols/symbol.py b/src/symbols/symbol.py index 07a2919..9ec55b7 100644 --- a/src/symbols/symbol.py +++ b/src/symbols/symbol.py @@ -55,9 +55,6 @@ def is_quantum(self) -> bool: def is_array(self) -> bool: return QutesDataType.is_array_type(self.symbol_declaration_static_type) - def get_array_unit_type(self) -> bool: - pass #TODO: handle - def __to_printable__(self) -> str: if(Symbol.verbose_print): if self.symbol_class is SymbolClass.FunctionSymbol: diff --git a/src/symbols/types/quint.py b/src/symbols/types/quint.py index ed88087..f7ec0d7 100644 --- a/src/symbols/types/quint.py +++ b/src/symbols/types/quint.py @@ -78,9 +78,11 @@ def fromValue(var_value : any) -> 'Quint': return Quint.init_from_integer(var_value) if(isinstance(var_value, bool)): return Quint.init_from_integer(var_value) + if(isinstance(var_value, list)): + return Quint.init_from_integer(int("".join([str(int(i)) for i in var_value]), 2)) raise TypeError(f"Cannot convert {type(var_value)} to quint.") - except: - raise TypeError(f"Cannot convert {type(var_value)} to quint.") + except Exception as e: + raise TypeError(f"Cannot convert {type(var_value)} to quint: {e}.") def update_size_with_padding(self, new_size : int) -> 'Quint': #TODO: qubit state is not reliable, we should add the qubit needed to expand the quint directly into the circuit. diff --git a/src/symbols/types/qustring.py b/src/symbols/types/qustring.py index 0d6ade6..d6f012e 100644 --- a/src/symbols/types/qustring.py +++ b/src/symbols/types/qustring.py @@ -64,6 +64,8 @@ def fromValue(var_value : any) -> 'Qustring': return Qustring(var_value.qubit_state) if(isinstance(var_value, str)): return Qustring.init_from_string(var_value) + if(isinstance(var_value, list)): + return Quint.init_from_string("".join([str(int(i)) for i in var_value])) raise TypeError(f"Cannot convert {type(var_value)} to quint.") def to_classical_type(self) -> int: diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index 665f716..020b78e 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -156,6 +156,25 @@ def promote_unit_to_array_type(unit_type : 'QutesDataType') -> 'QutesDataType': return QutesDataType.qustring_array case _: return QutesDataType.undefined + + def get_unit_type_from_array_type(array_type : 'QutesDataType') -> 'QutesDataType': + match array_type: + case QutesDataType.bool_array: + return QutesDataType.bool + case QutesDataType.int_array: + return QutesDataType.int + case QutesDataType.float_array: + return QutesDataType.float + case QutesDataType.string_array: + return QutesDataType.string + case QutesDataType.qubit_array: + return QutesDataType.qubit + case QutesDataType.quint_array: + return QutesDataType.quint + case QutesDataType.qustring_array: + return QutesDataType.qustring + case _: + return QutesDataType.undefined def get_default_value(var_type : 'QutesDataType'): match var_type: diff --git a/src/symbols/types/type_casting_handler.py b/src/symbols/types/type_casting_handler.py index 76e2376..1be419f 100644 --- a/src/symbols/types/type_casting_handler.py +++ b/src/symbols/types/type_casting_handler.py @@ -12,20 +12,20 @@ def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): #TODO: handle nested casting, like (quint a = true) bool->qubit->quint #..to this types <- this types can be converted to.. QutesDataType.bool: [QutesDataType.bool], - QutesDataType.int: [QutesDataType.int, QutesDataType.bool], - QutesDataType.float: [QutesDataType.float, QutesDataType.int, QutesDataType.bool], - QutesDataType.string: [QutesDataType.string, QutesDataType.float, QutesDataType.int, QutesDataType.bool], - QutesDataType.qubit: [QutesDataType.qubit, QutesDataType.string, QutesDataType.bool], - QutesDataType.quint: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], - QutesDataType.qustring: [QutesDataType.qustring, QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool], + QutesDataType.int: [QutesDataType.int, QutesDataType.bool, QutesDataType.bool_array], + QutesDataType.float: [QutesDataType.float, QutesDataType.int, QutesDataType.bool, QutesDataType.bool_array], + QutesDataType.string: [QutesDataType.string, QutesDataType.float, QutesDataType.int, QutesDataType.bool, QutesDataType.bool_array], + QutesDataType.qubit: [QutesDataType.qubit, QutesDataType.string, QutesDataType.bool, QutesDataType.bool_array], + QutesDataType.quint: [QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool, QutesDataType.bool_array], + QutesDataType.qustring: [QutesDataType.qustring, QutesDataType.quint, QutesDataType.qubit, QutesDataType.string, QutesDataType.int, QutesDataType.bool, QutesDataType.bool_array], QutesDataType.void: [], - QutesDataType.bool_array: [], - QutesDataType.int_array: [QutesDataType.bool_array], - QutesDataType.float_array: [QutesDataType.bool_array, QutesDataType.int_array], - QutesDataType.string_array: [QutesDataType.bool_array, QutesDataType.int_array, QutesDataType.float_array], - QutesDataType.qubit_array: [], - QutesDataType.quint_array: [], - QutesDataType.qustring_array: [], + QutesDataType.bool_array: [QutesDataType.bool_array], + QutesDataType.int_array: [QutesDataType.bool_array, QutesDataType.int_array], + QutesDataType.float_array: [QutesDataType.bool_array, QutesDataType.int_array, QutesDataType.float_array], + QutesDataType.string_array: [QutesDataType.bool_array, QutesDataType.int_array, QutesDataType.float_array, QutesDataType.string_array], + QutesDataType.qubit_array: [QutesDataType.bool_array, QutesDataType.qubit_array], + QutesDataType.quint_array: [QutesDataType.quint_array, QutesDataType.int_array, QutesDataType.qubit_array, QutesDataType.bool_array], + QutesDataType.qustring_array: [QutesDataType.qustring_array, QutesDataType.quint_array, QutesDataType.qubit_array, QutesDataType.string_array, QutesDataType.int_array, QutesDataType.float_array, QutesDataType.bool_array], } type_down_castable_to : dict[Enum, list[QutesDataType]] = { #..to this types <- this types can be converted(loosing information) to.. @@ -37,13 +37,13 @@ def __init__(self, quantum_cirtcuit_handler : 'QuantumCircuitHandler'): QutesDataType.quint: [QutesDataType.quint], QutesDataType.qustring: [QutesDataType.qustring], QutesDataType.void: [], - QutesDataType.bool_array: [], - QutesDataType.int_array: [], - QutesDataType.float_array: [], - QutesDataType.string_array: [], - QutesDataType.qubit_array: [], - QutesDataType.quint_array: [], - QutesDataType.qustring_array: [], + QutesDataType.bool_array: [QutesDataType.qubit_array, QutesDataType.bool_array], + QutesDataType.int_array: [QutesDataType.qubit_array, QutesDataType.quint_array, QutesDataType.int_array], + QutesDataType.float_array: [QutesDataType.qubit_array, QutesDataType.quint_array, QutesDataType.float_array, QutesDataType.int_array], + QutesDataType.string_array: [QutesDataType.qubit_array, QutesDataType.quint_array, QutesDataType.qustring_array, QutesDataType.float_array, QutesDataType.int_array, QutesDataType.string_array], + QutesDataType.qubit_array: [QutesDataType.qubit_array], + QutesDataType.quint_array: [QutesDataType.quint_array], + QutesDataType.qustring_array: [QutesDataType.qustring_array], } def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: @@ -51,8 +51,12 @@ def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_t case QutesDataType.bool: return bool(int(var_value)) case QutesDataType.int: + if isinstance(var_value, list): + return int(''.join([str(int(value)) for value in var_value]), 2) return int(var_value) case QutesDataType.float: + if isinstance(var_value, list): + return int(''.join([str(int(value)) for value in var_value]), 2) return float(var_value) case QutesDataType.string: return str(var_value) @@ -62,17 +66,41 @@ def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_t return Quint.fromValue(var_value) case QutesDataType.qustring: return Qustring.fromValue(var_value) + case QutesDataType.bool_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.bool) for value in var_value] + case QutesDataType.int_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.int) for value in var_value] + case QutesDataType.float_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.float) for value in var_value] + case QutesDataType.string_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.string) for value in var_value] + case QutesDataType.qubit_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.qubit) for value in var_value] + case QutesDataType.quint_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.quint) for value in var_value] + case QutesDataType.qustring_array: + return [self.promote_value_to_type(value, QutesDataType.type_of(value), QutesDataType.qustring) for value in var_value] case _: return QutesDataType.undefined + def __cast_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType') -> any: + if self.type_promotable_to[to_type].count(from_type) > 0: + return self.promote_value_to_type(var_value, from_type, to_type, None) + if self.type_down_castable_to[to_type].count(from_type) > 0: + return self.down_cast_value_to_type(var_value, from_type, to_type, None) + raise TypeError(f"Cannot cast type '{from_type}' to '{to_type}'.") + def down_cast_value_to_type(self, var_value : any, from_type:'QutesDataType', to_type : 'QutesDataType', symbol_or_literal) -> any: from symbols import Symbol from_type_value = None + + # if the value is a quantum type, we need to get the value from the quantum circuit measuring it. if QutesDataType.is_quantum_type(from_type): - if(isinstance(symbol_or_literal, Symbol) and symbol_or_literal.is_anonymous): - from_type_value = symbol_or_literal.value.to_classical_type() + from_type_value = [bool(value == '1') for value in self.quantum_cirtcuit_handler.get_run_and_measure_result_for_quantum_var(symbol_or_literal.quantum_register)] + if len(from_type_value) > 1: + from_type_value = self.__cast_value_to_type(from_type_value, QutesDataType.bool_array, to_type) else: - from_type_value, _ = self.quantum_cirtcuit_handler.get_run_and_measure_result_for_quantum_var(symbol_or_literal.quantum_register) + from_type_value = self.__cast_value_to_type(from_type_value[0], QutesDataType.bool, to_type) if from_type_value == None and isinstance(symbol_or_literal, Symbol): from_type_value = symbol_or_literal.value.to_classical_type() @@ -95,5 +123,19 @@ def down_cast_value_to_type(self, var_value : any, from_type:'QutesDataType', to return Quint.fromValue(var_value) case QutesDataType.qustring: return Qustring.fromValue(var_value) + case QutesDataType.bool_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.bool, value) for value in var_value] + case QutesDataType.int_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.int, value) for value in var_value] + case QutesDataType.float_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.float, value) for value in var_value] + case QutesDataType.string_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.string, value) for value in var_value] + case QutesDataType.qubit_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.qubit, value) for value in var_value] + case QutesDataType.quint_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.quint, value) for value in var_value] + case QutesDataType.qustring_array: + return [self.down_cast_value_to_type(value, QutesDataType.type_of(value), QutesDataType.qustring, value) for value in var_value] case _: return QutesDataType.undefined \ No newline at end of file From 714a91faa620e7f880f9d839cf91aaf5397e5cec Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Mon, 19 Aug 2024 18:47:26 +0000 Subject: [PATCH 31/34] Updated quantum teleportation and superdense conding exsamples with arrays and new language features --- playground/examples/quantum_teleportation.qut | 88 ++++++------------- playground/examples/superdense_coding.qut | 29 +++--- 2 files changed, 40 insertions(+), 77 deletions(-) diff --git a/playground/examples/quantum_teleportation.qut b/playground/examples/quantum_teleportation.qut index 57d8dc0..7122414 100644 --- a/playground/examples/quantum_teleportation.qut +++ b/playground/examples/quantum_teleportation.qut @@ -1,75 +1,45 @@ -//qubit a = 0.7,0.3q; -qubit a = 0q; -//measure a; +qubit originalAliceMessage = 0q; +qubit aliceMessage = 0q; + +initBellPairs(aliceMessage, originalAliceMessage); qubit bell1 = 0q; qubit bell2 = 0q; -//Provider -hadamard bell1; -mcx bell1, bell2; +initBellPairs(bell1, bell2); //Alice -mcx a, bell1; -hadamard a; -// measure a; -// measure bell1; +aliceEncoding(bell1); //Bob -bool do_z = a; +bool do_z = aliceMessage; bool do_x = bell1; -if(do_x){ - not bell2; -} -if(do_z){ - pauliz bell2; -} - -measure bell2; - - -print "Initial Message:"; -print a; -print "Teleported Message:"; -print bell2; - - +bobDecoding(do_z, do_x); -//TODO: There is some error when multiple functions are declared -// qubit aliceMessage = 0q; - -// qubit bell1 = 0q; -// qubit bell2 = 0q; - -// initBellPairs(bell1, bell2); - -// //Alice -// aliceEncoding(bell1); - -// //Bob -// bool do_z = aliceMessage; -// bool do_x = bell1; -// bobDecoding(do_z, do_x); +void initBellPairs(qubit a, qubit b){ + hadamard a; + mcx a, b; +} -// void initBellPairs(qubit a, qubit b){ -// hadamard a; -// mcx a, b; -// } +void aliceEncoding(qubit alice_bell){ + mcx aliceMessage, alice_bell; + hadamard aliceMessage; +} -// void aliceEncoding(qubit alice_bell){ -// mcx aliceMessage, alice_bell; -// hadamard aliceMessage; -// } +void bobDecoding(bool do_z, bool do_x){ + if(do_x){ + not bell2; + } + if(do_z){ + pauliz bell2; + } -// void bobDecoding(bool do_z, bool do_x){ -// if(do_x){ -// not bell2; -// } -// if(do_z){ -// pauliz bell2; -// } + measure bell2; +} -// measure bell2; -// } \ No newline at end of file +print "Initial Message: "; +print originalAliceMessage; +print " Teleported Message: "; +print bell2; \ No newline at end of file diff --git a/playground/examples/superdense_coding.qut b/playground/examples/superdense_coding.qut index 51fd275..4628ffc 100644 --- a/playground/examples/superdense_coding.qut +++ b/playground/examples/superdense_coding.qut @@ -4,41 +4,34 @@ qubit bell2; hadamard bell2; mcx bell2, bell1; -// - Send bell2 to Alice and Bell1 to Bob +// -----> Send bell2 to Alice +// -----> Send bell1 to Bob //Alice -qustring qu_message = "**"; -string message = qu_message; +qustring[] qu_message = ["*"q, "*"q]; +string[] message = qu_message; -if(message == "00"){ - //do nothing -} -else if(message == "01"){ - pauliz bell2; -} -else if(message == "10"){ + +if(message[0] == "1"){ not bell2; } -else if(message == "11"){ +if(message[1] == "1"){ pauliz bell2; - not bell2; } -// - Send transformed bell2 to Bob +// -----> Send transformed bell2 to Bob //Bob mcx bell2, bell1; hadamard bell2; -bool received_bit1 = bell1; -bool received_bit2 = bell2; +int received_bit1 = bell1; +int received_bit2 = bell2; print "Messaggio Inviato: "; print message; -print "Messaggio Ricevuto: "; -//TODO: Here we print always the first message because the circuit is created upon that. -// We should run Qutes 'runs' times or create the circuit with Qiskit if statements upon classical registers. +print " Messaggio Ricevuto: "; print received_bit1; print received_bit2; \ No newline at end of file From 59c5fe4ccd2d496066febf7859dad48c0e0538aa Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Mon, 19 Aug 2024 19:08:09 +0000 Subject: [PATCH 32/34] Update vscode extension with new language features --- qutes-vscode/package.json | 2 +- qutes-vscode/syntaxes/qutes.tmLanguage.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qutes-vscode/package.json b/qutes-vscode/package.json index 1f42f88..4a74415 100644 --- a/qutes-vscode/package.json +++ b/qutes-vscode/package.json @@ -5,7 +5,7 @@ "author": "Gabriele Messina", "publisher": "GabrieleMessina", "license": "MIT", - "version": "1.1.8", + "version": "1.2.1", "engines": { "vscode": "^1.52.0" }, diff --git a/qutes-vscode/syntaxes/qutes.tmLanguage.json b/qutes-vscode/syntaxes/qutes.tmLanguage.json index a161c56..b129473 100644 --- a/qutes-vscode/syntaxes/qutes.tmLanguage.json +++ b/qutes-vscode/syntaxes/qutes.tmLanguage.json @@ -5,12 +5,12 @@ "patterns": [ { "name": "keyword.control.qutes", - "match": "\\b(if|else|while|do|return|in|by)\\b" + "match": "\\b(for|foreach|if|else|while|do|return|in|by)\\b" }, { "name": "keyword.operator.qutes", - "match": "(\\*|/(?!/)|%|\\+|\\-|==|!=|>|>=|<|<=|=)|\\b(and|or|not|pauliy|pauliz|grover|mcz|mcx|mcp|mcy|swap|hadamard|measure|print|barrier)\\b|(\\+\\+|\\-\\-|\\+=|\\-=|\\*=|/=|&=)" - }, + "match": "((?|>=|<|<=|=)|\\b(and|or|not|pauliy|pauliz|grover|mcz|mcx|mcp|mcy|swap|hadamard|measure|print|println|barrier)\\b|(\\+\\+|\\-\\-|\\+=|\\-=|\\*=|/=|&=)" + } { "name": "storage.type.qutes", "match": "\\b(qustring|quint|qubit|int|string|bool|void|float)\\b" From b048c6233be8b3afc72a586611b57f0e776a0aef Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Mon, 19 Aug 2024 21:20:52 +0200 Subject: [PATCH 33/34] Fix qutes.tmLanguage.json missing comma --- qutes-vscode/syntaxes/qutes.tmLanguage.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qutes-vscode/syntaxes/qutes.tmLanguage.json b/qutes-vscode/syntaxes/qutes.tmLanguage.json index b129473..52d214f 100644 --- a/qutes-vscode/syntaxes/qutes.tmLanguage.json +++ b/qutes-vscode/syntaxes/qutes.tmLanguage.json @@ -10,7 +10,7 @@ { "name": "keyword.operator.qutes", "match": "((?|>=|<|<=|=)|\\b(and|or|not|pauliy|pauliz|grover|mcz|mcx|mcp|mcy|swap|hadamard|measure|print|println|barrier)\\b|(\\+\\+|\\-\\-|\\+=|\\-=|\\*=|/=|&=)" - } + }, { "name": "storage.type.qutes", "match": "\\b(qustring|quint|qubit|int|string|bool|void|float)\\b" @@ -82,4 +82,4 @@ "match": "=" } ] -} \ No newline at end of file +} From 1b7044b5e2aa8ad3a7916e6e31f2f568cb7617cb Mon Sep 17 00:00:00 2001 From: Gabriele Messina Date: Mon, 19 Aug 2024 19:42:23 +0000 Subject: [PATCH 34/34] Fix type casting from/to array types --- src/symbols/types/type_casting_handler.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/symbols/types/type_casting_handler.py b/src/symbols/types/type_casting_handler.py index 1be419f..d96b91d 100644 --- a/src/symbols/types/type_casting_handler.py +++ b/src/symbols/types/type_casting_handler.py @@ -59,6 +59,8 @@ def promote_value_to_type(self, var_value : any, from_type:'QutesDataType', to_t return int(''.join([str(int(value)) for value in var_value]), 2) return float(var_value) case QutesDataType.string: + if isinstance(var_value, list): + return str(''.join([str(int(value)) for value in var_value])) return str(var_value) case QutesDataType.qubit: return Qubit.fromValue(var_value) @@ -112,10 +114,16 @@ def down_cast_value_to_type(self, var_value : any, from_type:'QutesDataType', to case QutesDataType.bool: return bool(int(from_type_value)) case QutesDataType.int: - return int(from_type_value) + if isinstance(from_type_value, list): + return int(''.join([str(int(value)) for value in from_type_value]), 2) + return int(from_type_value) case QutesDataType.float: + if isinstance(from_type_value, list): + return int(''.join([str(int(value)) for value in from_type_value]), 2) return float(from_type_value) case QutesDataType.string: + if isinstance(from_type_value, list): + return str(''.join([str(int(value)) for value in from_type_value])) return str(from_type_value) case QutesDataType.qubit: return Qubit.fromValue(var_value)