diff --git a/src/grammar_frontend/expression.py b/src/grammar_frontend/expression.py index e8b7115..9079765 100644 --- a/src/grammar_frontend/expression.py +++ b/src/grammar_frontend/expression.py @@ -71,7 +71,7 @@ def visitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionConte 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) + array_value = self.variables_handler.get_value(array_symbol).array index_value = self.variables_handler.get_value(index_symbol) value = array_value[index_value] diff --git a/src/grammar_frontend/statement.py b/src/grammar_frontend/statement.py index bad118e..de651c6 100644 --- a/src/grammar_frontend/statement.py +++ b/src/grammar_frontend/statement.py @@ -141,7 +141,7 @@ def __visit_assignment_statement(self, var_name : str | Symbol, var_value, ctx:( var_symbol = self.variables_handler.get_variable_symbol(var_name, ctx.start.tokenIndex) if(isinstance(var_value, list)): - var_value = QuantumArrayType(QutesDataType.get_unit_class_from_array_type(QutesDataType.type_of(var_value)), [symbol.value for symbol in var_value]) + var_value = QuantumArrayType(QutesDataType.get_unit_class_from_array_type(QutesDataType.type_of(var_value)), [symbol for symbol in var_value]) if(var_value == None): var_value = QutesDataType.get_default_value(var_symbol.symbol_declaration_static_type) diff --git a/src/quantum_circuit/quantum_circuit_handler.py b/src/quantum_circuit/quantum_circuit_handler.py index 035f5e3..dbeda61 100644 --- a/src/quantum_circuit/quantum_circuit_handler.py +++ b/src/quantum_circuit/quantum_circuit_handler.py @@ -36,11 +36,6 @@ def declare_classical_register(self, variable_name : str, bits_number : int) -> self._classic_registers.append(new_register) return new_register - def delete_variable(self, variable_name : str) -> None: - register = self._varname_to_register[variable_name] - if(register not in self._varname_to_register.values()): - self._classic_registers.remove(register) - def declare_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring|QuantumArrayType) -> QuantumRegister: new_register = None new_register = QuantumRegister(quantum_variable.size, variable_name) @@ -50,7 +45,8 @@ 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.qubit_state + if not isinstance(quantum_variable, QuantumArrayType): + 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, @@ -60,13 +56,23 @@ def create_and_assign_quantum_register(self, variable_name : str, quantum_varia if(register_to_update is None): raise SystemError("Error trying to update an undeclared quantum register") + quantum_register = QuantumRegister(quantum_variable.size, variable_name) + 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. + if(isinstance(quantum_variable, QuantumArrayType)): + bits = [] + quantum_registers:list[QuantumRegister] = [symbol.quantum_register for symbol in quantum_variable.array] + for index, reg in enumerate(quantum_registers): + reg._name = f"{variable_name}_{index}" + bits.extend(reg) + quantum_register = QuantumRegister(None, variable_name, bits=bits) #Add new quantum register - register_to_update = self.assign_quantum_register_to_variable(variable_name, QuantumRegister(quantum_variable.size, variable_name)) + #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. + register_to_update = self.assign_quantum_register_to_variable(variable_name, quantum_register) 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 + if not isinstance(quantum_variable, QuantumArrayType): + 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") @@ -78,7 +84,6 @@ def assign_quantum_register_to_variable(self, variable_name : str, quantum_regi if(register_to_update is None): 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. if(register_to_update != quantum_register): self._varname_to_register[variable_name] = quantum_register self.__cleanup_orphan_registers() @@ -116,10 +121,11 @@ def create_circuit(self, *regs, do_initialization:bool = True) -> QuantumCircuit for register in self._quantum_registers: if(do_initialization): - 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") + if register in self._registers_states: + 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 diff --git a/src/symbols/types/quantum_array_type.py b/src/symbols/types/quantum_array_type.py index c8a01a5..65eed0a 100644 --- a/src/symbols/types/quantum_array_type.py +++ b/src/symbols/types/quantum_array_type.py @@ -1,21 +1,15 @@ from typing import TypeVar from symbols.types import QuantumType from symbols.types.qubit import Qubit -from quantum_circuit.state_preparation import StatePreparation T = TypeVar("T") class QuantumArrayType(QuantumType[T]): - def __init__(self, unit_type: QuantumType[T], array:list[QuantumType]): #array is a list of Symbol - super().__init__(unit_type, sum([a.size for a in array])) + def __init__(self, unit_type: QuantumType[T], array:list['Symbol']): + super().__init__(unit_type, sum([a.value.size for a in array])) self.unit_type = unit_type self.array = array - self.size = sum([a.size for a in array]) - state_preparation = str() - array_elements_state_preparation = [a.qubit_state._params_arg for a in array] - for element in array_elements_state_preparation: - state_preparation = state_preparation + element - self.qubit_state = StatePreparation(state_preparation) + self.size = sum([a.value.size for a in array]) def get_default_value(): return QuantumArrayType(Qubit, [Qubit.get_default_value()]) diff --git a/src/symbols/types/qutes_data_type.py b/src/symbols/types/qutes_data_type.py index 9d933c8..85bc562 100644 --- a/src/symbols/types/qutes_data_type.py +++ b/src/symbols/types/qutes_data_type.py @@ -219,11 +219,11 @@ def get_default_value(var_type : 'QutesDataType'): case QutesDataType.string_array: return [] case QutesDataType.qubit_array: - return QuantumArrayType(Qubit, [Qubit()]) + return QuantumArrayType(Qubit, []) case QutesDataType.quint_array: - return QuantumArrayType(Quint, [Quint()]) + return QuantumArrayType(Quint, []) case QutesDataType.qustring_array: - return QuantumArrayType(Qustring, [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 637b637..2f5f790 100644 --- a/src/symbols/variables_handler.py +++ b/src/symbols/variables_handler.py @@ -1,6 +1,6 @@ from uuid import uuid4 from symbols.types.type_casting_handler import TypeCastingHandler -from symbols.types.qutes_data_type import QutesDataType +from symbols.types.qutes_data_type import QutesDataType, QuantumArrayType from symbols.scope_handler import ScopeHandler from symbols.symbol import Symbol, SymbolClass from quantum_circuit import QuantumCircuitHandler @@ -15,7 +15,7 @@ def __init__(self, scope_handler : ScopeHandler, quantum_cirtcuit_handler : Quan 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. + # In case multiple scopes declare a variable 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] @@ -52,7 +52,7 @@ def update_variable_state(self, variable_name : str, new_state) -> Symbol: if(new_state.is_anonymous): 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) + self.quantum_cirtcuit_handler.remove_quantum_register(new_state.quantum_register) else: pass #being classic it was not added to circuit handler and there is no need to delete it. else: