classiq 0.53.0__py3-none-any.whl → 0.54.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. classiq/__init__.py +1 -3
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
  3. classiq/_internals/__init__.py +0 -20
  4. classiq/_internals/api_wrapper.py +8 -8
  5. classiq/_internals/async_utils.py +1 -3
  6. classiq/_internals/authentication/auth0.py +5 -5
  7. classiq/_internals/authentication/device.py +5 -4
  8. classiq/_internals/authentication/password_manager.py +3 -3
  9. classiq/_internals/authentication/token_manager.py +3 -2
  10. classiq/_internals/client.py +10 -12
  11. classiq/_internals/config.py +2 -2
  12. classiq/_internals/jobs.py +7 -6
  13. classiq/_internals/type_validation.py +9 -9
  14. classiq/analyzer/__init__.py +1 -3
  15. classiq/analyzer/analyzer.py +8 -7
  16. classiq/analyzer/analyzer_utilities.py +8 -8
  17. classiq/analyzer/rb.py +11 -11
  18. classiq/applications/__init__.py +1 -3
  19. classiq/applications/chemistry/__init__.py +1 -3
  20. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  21. classiq/applications/chemistry/chemistry_model_constructor.py +10 -9
  22. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +26 -9
  23. classiq/applications/combinatorial_helpers/encoding_mapping.py +10 -10
  24. classiq/applications/combinatorial_helpers/encoding_utils.py +4 -4
  25. classiq/applications/combinatorial_helpers/memory.py +5 -7
  26. classiq/applications/combinatorial_helpers/optimization_model.py +43 -24
  27. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +4 -6
  28. classiq/applications/combinatorial_helpers/pyomo_utils.py +95 -24
  29. classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
  30. classiq/applications/combinatorial_helpers/transformations/encoding.py +8 -8
  31. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +5 -5
  32. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +7 -9
  33. classiq/applications/combinatorial_helpers/transformations/penalty.py +1 -2
  34. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +1 -2
  35. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +1 -2
  36. classiq/applications/combinatorial_optimization/__init__.py +1 -3
  37. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  38. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  39. classiq/applications/finance/__init__.py +1 -3
  40. classiq/applications/grover/__init__.py +1 -3
  41. classiq/applications/grover/grover_model_constructor.py +7 -9
  42. classiq/applications/hamiltonian/pauli_decomposition.py +6 -6
  43. classiq/applications/qnn/__init__.py +1 -3
  44. classiq/applications/qnn/circuit_utils.py +5 -5
  45. classiq/applications/qnn/datasets/__init__.py +1 -3
  46. classiq/applications/qnn/datasets/dataset_base_classes.py +5 -4
  47. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  48. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  49. classiq/applications/qnn/qlayer.py +3 -3
  50. classiq/applications/qnn/torch_utils.py +2 -2
  51. classiq/applications/qnn/types.py +5 -5
  52. classiq/applications/qsvm/qsvm.py +1 -3
  53. classiq/applications/qsvm/qsvm_data_generation.py +3 -3
  54. classiq/applications/qsvm/qsvm_model_constructor.py +5 -5
  55. classiq/execution/__init__.py +1 -3
  56. classiq/execution/all_hardware_devices.py +1 -3
  57. classiq/execution/execution_session.py +16 -16
  58. classiq/execution/jobs.py +4 -4
  59. classiq/execution/qaoa.py +3 -3
  60. classiq/execution/qnn.py +3 -3
  61. classiq/executor.py +3 -3
  62. classiq/interface/_version.py +1 -1
  63. classiq/interface/analyzer/analysis_params.py +9 -10
  64. classiq/interface/analyzer/cytoscape_graph.py +5 -5
  65. classiq/interface/analyzer/result.py +17 -17
  66. classiq/interface/applications/qsvm.py +6 -10
  67. classiq/interface/backend/backend_preferences.py +4 -3
  68. classiq/interface/backend/ionq/ionq_quantum_program.py +4 -5
  69. classiq/interface/backend/pydantic_backend.py +1 -2
  70. classiq/interface/chemistry/fermionic_operator.py +5 -5
  71. classiq/interface/chemistry/ground_state_problem.py +7 -8
  72. classiq/interface/chemistry/molecule.py +4 -4
  73. classiq/interface/chemistry/operator.py +11 -13
  74. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
  75. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  76. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  77. classiq/interface/combinatorial_optimization/examples/mht.py +2 -3
  78. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  79. classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
  80. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +5 -7
  81. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  82. classiq/interface/combinatorial_optimization/result.py +1 -3
  83. classiq/interface/debug_info/debug_info.py +8 -7
  84. classiq/interface/exceptions.py +8 -6
  85. classiq/interface/execution/jobs.py +2 -2
  86. classiq/interface/execution/primitives.py +3 -3
  87. classiq/interface/executor/aws_execution_cost.py +4 -4
  88. classiq/interface/executor/execution_request.py +2 -3
  89. classiq/interface/executor/execution_result.py +3 -3
  90. classiq/interface/executor/iqae_result.py +3 -5
  91. classiq/interface/executor/optimizer_preferences.py +2 -2
  92. classiq/interface/executor/quantum_code.py +6 -6
  93. classiq/interface/executor/register_initialization.py +2 -4
  94. classiq/interface/executor/result.py +23 -27
  95. classiq/interface/executor/vqe_result.py +8 -8
  96. classiq/interface/finance/function_input.py +2 -2
  97. classiq/interface/finance/gaussian_model_input.py +5 -5
  98. classiq/interface/finance/log_normal_model_input.py +2 -2
  99. classiq/interface/finance/model_input.py +1 -2
  100. classiq/interface/generator/adjacency.py +1 -3
  101. classiq/interface/generator/ansatz_library.py +4 -4
  102. classiq/interface/generator/application_apis/finance_declarations.py +1 -1
  103. classiq/interface/generator/arith/argument_utils.py +3 -3
  104. classiq/interface/generator/arith/arithmetic.py +7 -7
  105. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +5 -5
  106. classiq/interface/generator/arith/arithmetic_expression_abc.py +11 -11
  107. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -7
  108. classiq/interface/generator/arith/arithmetic_expression_validator.py +8 -8
  109. classiq/interface/generator/arith/arithmetic_operations.py +4 -3
  110. classiq/interface/generator/arith/arithmetic_param_getters.py +6 -6
  111. classiq/interface/generator/arith/arithmetic_result_builder.py +9 -9
  112. classiq/interface/generator/arith/ast_node_rewrite.py +2 -1
  113. classiq/interface/generator/arith/binary_ops.py +10 -13
  114. classiq/interface/generator/arith/extremum_operations.py +3 -2
  115. classiq/interface/generator/arith/logical_ops.py +7 -6
  116. classiq/interface/generator/arith/number_utils.py +4 -4
  117. classiq/interface/generator/arith/register_user_input.py +4 -4
  118. classiq/interface/generator/arith/unary_ops.py +2 -1
  119. classiq/interface/generator/builtin_api_builder.py +2 -1
  120. classiq/interface/generator/circuit_code/circuit_code.py +4 -4
  121. classiq/interface/generator/circuit_code/types_and_constants.py +3 -5
  122. classiq/interface/generator/complex_type.py +1 -2
  123. classiq/interface/generator/control_state.py +2 -2
  124. classiq/interface/generator/custom_ansatz.py +1 -3
  125. classiq/interface/generator/distance.py +3 -5
  126. classiq/interface/generator/excitations.py +3 -2
  127. classiq/interface/generator/expressions/enums/finance_functions.py +1 -3
  128. classiq/interface/generator/expressions/evaluated_expression.py +4 -3
  129. classiq/interface/generator/expressions/expression.py +4 -5
  130. classiq/interface/generator/expressions/expression_constants.py +4 -4
  131. classiq/interface/generator/expressions/qmod_qarray_proxy.py +2 -1
  132. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +2 -1
  133. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +2 -1
  134. classiq/interface/generator/expressions/qmod_sized_proxy.py +2 -1
  135. classiq/interface/generator/expressions/qmod_struct_instance.py +2 -1
  136. classiq/interface/generator/expressions/sympy_supported_expressions.py +11 -13
  137. classiq/interface/generator/finance.py +2 -2
  138. classiq/interface/generator/function_param_library.py +6 -6
  139. classiq/interface/generator/function_params.py +13 -19
  140. classiq/interface/generator/functions/classical_function_declaration.py +4 -3
  141. classiq/interface/generator/functions/classical_type.py +13 -13
  142. classiq/interface/generator/functions/concrete_types.py +1 -2
  143. classiq/interface/generator/functions/function_declaration.py +1 -1
  144. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  145. classiq/interface/generator/functions/type_name.py +3 -2
  146. classiq/interface/generator/generated_circuit_data.py +34 -22
  147. classiq/interface/generator/grover_diffuser.py +7 -7
  148. classiq/interface/generator/grover_operator.py +2 -2
  149. classiq/interface/generator/hardware/hardware_data.py +7 -6
  150. classiq/interface/generator/hardware_efficient_ansatz.py +8 -8
  151. classiq/interface/generator/identity.py +5 -6
  152. classiq/interface/generator/linear_pauli_rotations.py +6 -6
  153. classiq/interface/generator/mcu.py +2 -2
  154. classiq/interface/generator/mcx.py +6 -6
  155. classiq/interface/generator/model/__init__.py +1 -3
  156. classiq/interface/generator/model/constraints.py +2 -2
  157. classiq/interface/generator/model/model.py +5 -6
  158. classiq/interface/generator/model/preferences/preferences.py +7 -6
  159. classiq/interface/generator/model/quantum_register.py +6 -11
  160. classiq/interface/generator/oracles/arithmetic_oracle.py +1 -2
  161. classiq/interface/generator/oracles/custom_oracle.py +2 -2
  162. classiq/interface/generator/oracles/oracle_abc.py +6 -5
  163. classiq/interface/generator/partitioned_register.py +6 -5
  164. classiq/interface/generator/piecewise_linear_amplitude_loading.py +8 -7
  165. classiq/interface/generator/qpe.py +4 -4
  166. classiq/interface/generator/qsvm.py +3 -3
  167. classiq/interface/generator/quantum_function_call.py +24 -29
  168. classiq/interface/generator/quantum_program.py +9 -9
  169. classiq/interface/generator/register_role.py +2 -4
  170. classiq/interface/generator/slice_parsing_utils.py +4 -3
  171. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  172. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  173. classiq/interface/generator/state_preparation/distributions.py +6 -5
  174. classiq/interface/generator/state_preparation/metrics.py +2 -4
  175. classiq/interface/generator/state_preparation/state_preparation.py +4 -4
  176. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -3
  177. classiq/interface/generator/transpiler_basis_gates.py +2 -2
  178. classiq/interface/generator/types/enum_declaration.py +2 -3
  179. classiq/interface/generator/types/qstruct_declaration.py +2 -1
  180. classiq/interface/generator/types/struct_declaration.py +3 -2
  181. classiq/interface/generator/ucc.py +2 -1
  182. classiq/interface/generator/unitary_gate.py +2 -2
  183. classiq/interface/generator/user_defined_function_params.py +1 -1
  184. classiq/interface/generator/validations/flow_graph.py +6 -5
  185. classiq/interface/generator/validations/validator_functions.py +3 -2
  186. classiq/interface/generator/visitor.py +9 -14
  187. classiq/interface/hardware.py +5 -6
  188. classiq/interface/helpers/custom_encoders.py +2 -2
  189. classiq/interface/helpers/custom_pydantic_types.py +8 -9
  190. classiq/interface/helpers/hashable_mixin.py +3 -2
  191. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  192. classiq/interface/helpers/pydantic_model_helpers.py +4 -3
  193. classiq/interface/helpers/validation_helpers.py +2 -2
  194. classiq/interface/ide/ide_data.py +11 -15
  195. classiq/interface/ide/visual_model.py +20 -22
  196. classiq/interface/jobs.py +2 -2
  197. classiq/interface/model/bind_operation.py +5 -4
  198. classiq/interface/model/classical_parameter_declaration.py +2 -2
  199. classiq/interface/model/handle_binding.py +3 -2
  200. classiq/interface/model/inplace_binary_operation.py +2 -1
  201. classiq/interface/model/model.py +12 -11
  202. classiq/interface/model/port_declaration.py +2 -2
  203. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +3 -2
  204. classiq/interface/model/quantum_expressions/arithmetic_operation.py +3 -2
  205. classiq/interface/model/quantum_expressions/quantum_expression.py +8 -7
  206. classiq/interface/model/quantum_function_call.py +9 -14
  207. classiq/interface/model/quantum_function_declaration.py +10 -12
  208. classiq/interface/model/quantum_lambda_function.py +3 -16
  209. classiq/interface/model/quantum_statement.py +4 -3
  210. classiq/interface/model/quantum_type.py +5 -5
  211. classiq/interface/model/statement_block.py +2 -3
  212. classiq/interface/model/validation_handle.py +5 -4
  213. classiq/interface/server/global_versions.py +3 -3
  214. classiq/model_expansions/atomic_expression_functions_defs.py +3 -2
  215. classiq/model_expansions/call_to_model_converter.py +190 -0
  216. classiq/model_expansions/capturing/captured_var_manager.py +4 -6
  217. classiq/model_expansions/capturing/propagated_var_stack.py +7 -7
  218. classiq/model_expansions/closure.py +17 -9
  219. classiq/model_expansions/evaluators/arg_type_match.py +3 -2
  220. classiq/model_expansions/evaluators/argument_types.py +3 -3
  221. classiq/model_expansions/evaluators/control.py +3 -3
  222. classiq/model_expansions/evaluators/parameter_types.py +7 -7
  223. classiq/model_expansions/evaluators/quantum_type_utils.py +2 -1
  224. classiq/model_expansions/evaluators/type_type_match.py +1 -1
  225. classiq/model_expansions/expression_evaluator.py +10 -9
  226. classiq/model_expansions/expression_renamer.py +6 -6
  227. classiq/model_expansions/function_builder.py +19 -12
  228. classiq/model_expansions/generative_functions.py +3 -2
  229. classiq/model_expansions/interpreter.py +31 -19
  230. classiq/model_expansions/model_tables.py +14 -14
  231. classiq/model_expansions/quantum_operations/bind.py +2 -4
  232. classiq/model_expansions/quantum_operations/classicalif.py +1 -1
  233. classiq/model_expansions/quantum_operations/control.py +2 -4
  234. classiq/model_expansions/quantum_operations/emitter.py +10 -13
  235. classiq/model_expansions/quantum_operations/expression_operation.py +23 -16
  236. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +160 -35
  237. classiq/model_expansions/quantum_operations/phase.py +6 -6
  238. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +25 -5
  239. classiq/model_expansions/quantum_operations/quantum_function_call.py +41 -2
  240. classiq/model_expansions/quantum_operations/repeat.py +1 -3
  241. classiq/model_expansions/scope.py +11 -10
  242. classiq/model_expansions/scope_initialization.py +6 -5
  243. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +6 -6
  244. classiq/model_expansions/sympy_conversion/sympy_to_python.py +2 -2
  245. classiq/model_expansions/visitors/variable_references.py +5 -4
  246. classiq/qmod/builtins/classical_execution_primitives.py +9 -9
  247. classiq/qmod/builtins/functions/__init__.py +72 -55
  248. classiq/qmod/builtins/functions/amplitude_estimation.py +4 -1
  249. classiq/qmod/builtins/functions/arithmetic.py +14 -1
  250. classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +86 -6
  251. classiq/qmod/builtins/functions/grover.py +41 -45
  252. classiq/qmod/builtins/functions/hea.py +60 -4
  253. classiq/qmod/builtins/functions/linear_pauli_rotation.py +26 -4
  254. classiq/qmod/builtins/functions/modular_exponentiation.py +90 -29
  255. classiq/qmod/builtins/functions/operators.py +1 -1
  256. classiq/qmod/builtins/functions/qaoa_penalty.py +14 -5
  257. classiq/qmod/builtins/functions/qft_functions.py +57 -0
  258. classiq/qmod/builtins/functions/qpe.py +20 -4
  259. classiq/qmod/builtins/functions/qsvt.py +49 -4
  260. classiq/qmod/builtins/functions/standard_gates.py +4 -4
  261. classiq/qmod/builtins/functions/state_preparation.py +92 -10
  262. classiq/qmod/builtins/functions/swap_test.py +7 -1
  263. classiq/qmod/builtins/functions/utility_functions.py +43 -0
  264. classiq/qmod/builtins/functions/variational.py +18 -2
  265. classiq/qmod/builtins/operations.py +4 -5
  266. classiq/qmod/cfunc.py +2 -2
  267. classiq/qmod/classical_function.py +3 -7
  268. classiq/qmod/create_model_function.py +7 -6
  269. classiq/qmod/declaration_inferrer.py +7 -10
  270. classiq/qmod/expression_query.py +3 -3
  271. classiq/qmod/generative.py +2 -1
  272. classiq/qmod/model_state_container.py +5 -7
  273. classiq/qmod/native/__init__.py +1 -3
  274. classiq/qmod/native/expression_to_qmod.py +9 -8
  275. classiq/qmod/native/pretty_printer.py +6 -5
  276. classiq/qmod/pretty_print/__init__.py +1 -3
  277. classiq/qmod/pretty_print/expression_to_python.py +13 -12
  278. classiq/qmod/pretty_print/pretty_printer.py +13 -12
  279. classiq/qmod/python_classical_type.py +8 -4
  280. classiq/qmod/qfunc.py +4 -4
  281. classiq/qmod/qmod_variable.py +11 -10
  282. classiq/qmod/quantum_expandable.py +12 -15
  283. classiq/qmod/quantum_function.py +10 -3
  284. classiq/qmod/semantics/annotation.py +1 -1
  285. classiq/qmod/semantics/error_manager.py +8 -7
  286. classiq/qmod/semantics/static_semantics_visitor.py +19 -24
  287. classiq/qmod/semantics/validation/constants_validation.py +1 -1
  288. classiq/qmod/semantics/validation/func_call_validation.py +2 -2
  289. classiq/qmod/semantics/validation/main_validation.py +33 -0
  290. classiq/qmod/semantics/validation/types_validation.py +2 -1
  291. classiq/qmod/symbolic.py +5 -8
  292. classiq/qmod/symbolic_type.py +2 -2
  293. {classiq-0.53.0.dist-info → classiq-0.54.0.dist-info}/METADATA +1 -1
  294. {classiq-0.53.0.dist-info → classiq-0.54.0.dist-info}/RECORD +295 -292
  295. classiq/qmod/builtins/functions/qft.py +0 -23
  296. {classiq-0.53.0.dist-info → classiq-0.54.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,7 @@
1
+ from collections.abc import Iterable, Iterator, Sequence
1
2
  from contextlib import contextmanager
2
3
  from dataclasses import dataclass, field
3
- from typing import Dict, Generic, Iterable, Iterator, List, Optional, Sequence, TypeVar
4
+ from typing import Generic, Optional, TypeVar
4
5
 
5
6
  from classiq.interface.exceptions import (
6
7
  ClassiqExpansionError,
@@ -18,6 +19,7 @@ from classiq.interface.generator.functions.port_declaration import (
18
19
  )
19
20
  from classiq.interface.model.model import MAIN_FUNCTION_NAME
20
21
  from classiq.interface.model.native_function_definition import (
22
+ FunctionSynthesisData,
21
23
  NativeFunctionDefinition,
22
24
  )
23
25
  from classiq.interface.model.port_declaration import PortDeclaration
@@ -35,14 +37,14 @@ ClosureType = TypeVar("ClosureType", bound=Closure)
35
37
 
36
38
  @dataclass
37
39
  class Block:
38
- statements: List[QuantumStatement] = field(default_factory=list)
39
- captured_vars: List[PortDeclaration] = field(default_factory=list)
40
+ statements: list[QuantumStatement] = field(default_factory=list)
41
+ captured_vars: list[PortDeclaration] = field(default_factory=list)
40
42
 
41
43
 
42
44
  @dataclass
43
45
  class OperationContext(Generic[ClosureType]):
44
46
  closure: ClosureType
45
- blocks: Dict[str, Block] = field(default_factory=dict)
47
+ blocks: dict[str, Block] = field(default_factory=dict)
46
48
 
47
49
  @property
48
50
  def name(self) -> str:
@@ -52,7 +54,7 @@ class OperationContext(Generic[ClosureType]):
52
54
  def positional_arg_declarations(self) -> Sequence[PositionalArg]:
53
55
  return self.closure.positional_arg_declarations
54
56
 
55
- def statements(self, block_name: str) -> List[QuantumStatement]:
57
+ def statements(self, block_name: str) -> list[QuantumStatement]:
56
58
  return self.blocks[block_name].statements
57
59
 
58
60
 
@@ -63,22 +65,26 @@ class FunctionContext(OperationContext[FunctionClosure]):
63
65
  return cls(original_function, {"body": Block()})
64
66
 
65
67
  @property
66
- def body(self) -> List[QuantumStatement]:
68
+ def body(self) -> list[QuantumStatement]:
67
69
  return self.statements("body")
68
70
 
69
71
  @property
70
- def captured_vars(self) -> List[PortDeclaration]:
72
+ def captured_vars(self) -> list[PortDeclaration]:
71
73
  return self.blocks["body"].captured_vars
72
74
 
73
75
  @property
74
76
  def is_lambda(self) -> bool:
75
77
  return self.closure.is_lambda
76
78
 
79
+ @property
80
+ def synthesis_data(self) -> FunctionSynthesisData:
81
+ return self.closure.synthesis_data
82
+
77
83
 
78
84
  class OperationBuilder:
79
85
  def __init__(self) -> None:
80
- self._operations: List[OperationContext] = []
81
- self._blocks: List[str] = []
86
+ self._operations: list[OperationContext] = []
87
+ self._blocks: list[str] = []
82
88
  self._counter = 0
83
89
 
84
90
  @property
@@ -93,7 +99,7 @@ class OperationBuilder:
93
99
  raise ClassiqInternalExpansionError("No function found")
94
100
 
95
101
  @property
96
- def _current_statements(self) -> List[QuantumStatement]:
102
+ def _current_statements(self) -> list[QuantumStatement]:
97
103
  return self._operations[-1].blocks[self._blocks[-1]].statements
98
104
 
99
105
  def emit_statement(self, statement: QuantumStatement) -> None:
@@ -160,7 +166,7 @@ class OperationBuilder:
160
166
  name = f"{name}_{LAMBDA_KEYWORD + '_0_0_' if function_context.is_lambda else ''}{EXPANDED_KEYWORD}_{self._counter}"
161
167
  self._counter += 1
162
168
 
163
- new_parameters: List[PortDeclaration] = [
169
+ new_parameters: list[PortDeclaration] = [
164
170
  param
165
171
  for param in function_context.positional_arg_declarations
166
172
  if isinstance(param, PortDeclaration)
@@ -170,10 +176,11 @@ class OperationBuilder:
170
176
  name=name,
171
177
  body=function_context.body,
172
178
  positional_arg_declarations=new_parameters,
179
+ synthesis_data=function_context.synthesis_data,
173
180
  )
174
181
 
175
182
 
176
- def validate_captured_vars(captured_vars: List[PortDeclaration]) -> None:
183
+ def validate_captured_vars(captured_vars: list[PortDeclaration]) -> None:
177
184
  if input_captured := [
178
185
  demangle_name(var.name)
179
186
  for var in captured_vars
@@ -1,4 +1,5 @@
1
- from typing import TYPE_CHECKING, Any, List, Mapping
1
+ from collections.abc import Mapping
2
+ from typing import TYPE_CHECKING, Any
2
3
 
3
4
  from classiq.interface.exceptions import ClassiqInternalExpansionError
4
5
  from classiq.interface.generator.expressions.qmod_struct_instance import (
@@ -127,7 +128,7 @@ class _InterpreterExpandable(QFunc):
127
128
  def emit_generative_statements(
128
129
  interpreter: "Interpreter",
129
130
  operation: GenerativeClosure,
130
- args: List[Evaluated],
131
+ args: list[Evaluated],
131
132
  ) -> None:
132
133
  python_qmod_args = [
133
134
  translate_ast_arg_to_python_qmod(param, arg)
@@ -1,7 +1,8 @@
1
1
  import copy
2
+ from collections.abc import Iterator, Sequence
2
3
  from contextlib import contextmanager, nullcontext
3
4
  from functools import singledispatchmethod
4
- from typing import Any, Iterator, List, Optional, Sequence, Tuple, Type, cast
5
+ from typing import Any, Optional, cast
5
6
 
6
7
  import numpy as np
7
8
  from numpy.random import permutation
@@ -45,6 +46,7 @@ from classiq.interface.model.variable_declaration_statement import (
45
46
  )
46
47
  from classiq.interface.model.within_apply_operation import WithinApply
47
48
 
49
+ from classiq.model_expansions.call_to_model_converter import BlockFunctionInfo
48
50
  from classiq.model_expansions.capturing.propagated_var_stack import PropagatedVarStack
49
51
  from classiq.model_expansions.closure import (
50
52
  Closure,
@@ -88,7 +90,7 @@ from classiq.qmod.builtins.functions import permute
88
90
  from classiq.qmod.quantum_function import GenerativeQFunc
89
91
  from classiq.qmod.semantics.error_manager import ErrorManager
90
92
 
91
- STATEMENT_TYPES_FOR_SOURCE_REFERENCE_PROPAGATION: Tuple[Type[QuantumStatement], ...] = (
93
+ STATEMENT_TYPES_FOR_SOURCE_REFERENCE_PROPAGATION: tuple[type[QuantumStatement], ...] = (
92
94
  QuantumFunctionCall,
93
95
  VariableDeclarationStatement,
94
96
  QuantumAssignmentOperation,
@@ -99,14 +101,14 @@ class Interpreter:
99
101
  def __init__(
100
102
  self,
101
103
  model: Model,
102
- generative_functions: Optional[List[GenerativeQFunc]] = None,
104
+ generative_functions: Optional[list[GenerativeQFunc]] = None,
103
105
  is_frontend: bool = False,
104
106
  ) -> None:
105
107
  self._is_frontend = is_frontend
106
108
  self._model = model
107
109
  self._current_scope = Scope()
108
110
  self._builder = OperationBuilder()
109
- self._expanded_functions: List[NativeFunctionDefinition] = []
111
+ self._expanded_functions: list[NativeFunctionDefinition] = []
110
112
  self._propagated_var_stack = PropagatedVarStack(
111
113
  self._current_scope, self._builder
112
114
  )
@@ -120,6 +122,7 @@ class Interpreter:
120
122
 
121
123
  self._counted_name_allocator = CountedNameAllocator()
122
124
  self._error_manager: ErrorManager = ErrorManager()
125
+ self._synthesized_separately_blocks: dict[str, BlockFunctionInfo] = {}
123
126
 
124
127
  @contextmanager
125
128
  def _scope_guard(self, scope: Scope) -> Iterator[None]:
@@ -154,9 +157,10 @@ class Interpreter:
154
157
  self._builder.create_definition(cast(FunctionContext, context))
155
158
  )
156
159
 
157
- def expand(self) -> Model:
160
+ def expand(self) -> tuple[Model, dict[str, BlockFunctionInfo]]:
158
161
  try:
159
162
  with self._error_manager.call("main"):
163
+ self._synthesized_separately_blocks = {}
160
164
  self._expand_main_func()
161
165
  except Exception as e:
162
166
  if isinstance(e, ClassiqInternalExpansionError) or debug_mode.get():
@@ -168,17 +172,20 @@ class Interpreter:
168
172
  finally:
169
173
  self._error_manager.report_errors(ClassiqExpansionError)
170
174
 
171
- return Model(
172
- constraints=self._model.constraints,
173
- preferences=self._model.preferences,
174
- classical_execution_code=self._model.classical_execution_code,
175
- execution_preferences=self._model.execution_preferences,
176
- functions=self._expanded_functions,
177
- constants=self._model.constants,
178
- enums=self._model.enums,
179
- types=self._model.types,
180
- qstructs=self._model.qstructs,
181
- debug_info=self._model.debug_info,
175
+ return (
176
+ Model(
177
+ constraints=self._model.constraints,
178
+ preferences=self._model.preferences,
179
+ classical_execution_code=self._model.classical_execution_code,
180
+ execution_preferences=self._model.execution_preferences,
181
+ functions=self._expanded_functions,
182
+ constants=self._model.constants,
183
+ enums=self._model.enums,
184
+ types=self._model.types,
185
+ qstructs=self._model.qstructs,
186
+ debug_info=self._model.debug_info,
187
+ ),
188
+ self._synthesized_separately_blocks,
182
189
  )
183
190
 
184
191
  @singledispatchmethod
@@ -196,7 +203,7 @@ class Interpreter:
196
203
  @evaluate.register
197
204
  def evaluate_lambda(self, function: QuantumLambdaFunction) -> Evaluated:
198
205
  renamed_params = [
199
- param.rename(function.get_rename_params()[idx])
206
+ param.rename(function.pos_rename_params[idx])
200
207
  for idx, param in enumerate(function.func_decl.positional_arg_declarations)
201
208
  ]
202
209
  func_decl = NamedParamsQuantumFunctionDeclaration(
@@ -204,7 +211,7 @@ class Interpreter:
204
211
  positional_arg_declarations=renamed_params,
205
212
  )
206
213
 
207
- closure_class: Type[FunctionClosure]
214
+ closure_class: type[FunctionClosure]
208
215
  extra_args: dict[str, Any]
209
216
  if function.is_generative():
210
217
  closure_class = GenerativeFunctionClosure
@@ -339,7 +346,12 @@ class Interpreter:
339
346
 
340
347
  def _expand_operation(self, operation: Closure) -> OperationContext:
341
348
  with self._builder.operation_context(operation) as context:
342
- if isinstance(operation, FunctionClosure) and operation.name == "permute":
349
+ if (
350
+ isinstance(operation, FunctionClosure)
351
+ and operation.synthesis_data.should_synthesize_separately
352
+ ):
353
+ pass
354
+ elif isinstance(operation, FunctionClosure) and operation.name == "permute":
343
355
  # special expansion since permute is generative
344
356
  with self._scope_guard(operation.scope):
345
357
  self._expand_permute()
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from enum import IntEnum
3
- from typing import ClassVar, Dict, Generic, List, Optional, TypeVar
3
+ from typing import ClassVar, Generic, Optional, TypeVar
4
4
 
5
5
  from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
6
6
  from classiq.interface.generator.functions.classical_type import QmodPyObject
@@ -18,15 +18,15 @@ DeclarationType = TypeVar(
18
18
 
19
19
 
20
20
  class TypeTable(Generic[DeclarationType], ABC):
21
- def __init__(self, user_types: List[DeclarationType]) -> None:
22
- self._all_types: Dict[str, DeclarationType] = self.builtins.copy()
21
+ def __init__(self, user_types: list[DeclarationType]) -> None:
22
+ self._all_types: dict[str, DeclarationType] = self.builtins.copy()
23
23
  for t in user_types:
24
24
  assert t.name not in self._all_types # FIXME: issue user error (CAD-7856)
25
25
  self._all_types[t.name] = t
26
26
 
27
27
  @property
28
28
  @abstractmethod
29
- def builtins(self) -> Dict[str, DeclarationType]:
29
+ def builtins(self) -> dict[str, DeclarationType]:
30
30
  pass
31
31
 
32
32
  def __getitem__(self, key: str) -> DeclarationType:
@@ -38,20 +38,20 @@ class TypeTable(Generic[DeclarationType], ABC):
38
38
  def __contains__(self, key: str) -> bool:
39
39
  return key in self._all_types
40
40
 
41
- def all_types(self) -> Dict[str, DeclarationType]:
41
+ def all_types(self) -> dict[str, DeclarationType]:
42
42
  return self._all_types
43
43
 
44
44
 
45
45
  class EnumTable(TypeTable[EnumDeclaration]):
46
- def __init__(self, user_types: List[EnumDeclaration]) -> None:
46
+ def __init__(self, user_types: list[EnumDeclaration]) -> None:
47
47
  super().__init__(user_types)
48
48
 
49
49
  @property
50
- def builtins(self) -> Dict[str, EnumDeclaration]:
50
+ def builtins(self) -> dict[str, EnumDeclaration]:
51
51
  return BUILTIN_ENUM_DECLARATIONS
52
52
 
53
53
  @property
54
- def enums(self) -> Dict[str, IntEnum]:
54
+ def enums(self) -> dict[str, IntEnum]:
55
55
  return {
56
56
  enum_decl.name: enum_decl.create_enum()
57
57
  for enum_decl in self.all_types().values()
@@ -60,13 +60,13 @@ class EnumTable(TypeTable[EnumDeclaration]):
60
60
 
61
61
  class StructTable(TypeTable[StructDeclaration]):
62
62
  @property
63
- def builtins(self) -> Dict[str, StructDeclaration]:
63
+ def builtins(self) -> dict[str, StructDeclaration]:
64
64
  return BUILTIN_STRUCT_DECLARATIONS
65
65
 
66
66
 
67
67
  class QStructTable(TypeTable[QStructDeclaration]):
68
68
  @property
69
- def builtins(self) -> Dict[str, QStructDeclaration]:
69
+ def builtins(self) -> dict[str, QStructDeclaration]:
70
70
  return {}
71
71
 
72
72
 
@@ -76,15 +76,15 @@ class SymbolTable:
76
76
  qstruct_table: ClassVar[QStructTable] = QStructTable([])
77
77
 
78
78
  @classmethod
79
- def init_user_enums(cls, user_enums: List[EnumDeclaration]) -> None:
79
+ def init_user_enums(cls, user_enums: list[EnumDeclaration]) -> None:
80
80
  cls.enum_table = EnumTable(user_enums)
81
81
 
82
82
  @classmethod
83
- def init_user_types(cls, user_types: List[StructDeclaration]) -> None:
83
+ def init_user_types(cls, user_types: list[StructDeclaration]) -> None:
84
84
  cls.type_table = StructTable(user_types)
85
85
 
86
86
  @classmethod
87
- def init_user_qstructs(cls, user_qstructs: List[QStructDeclaration]) -> None:
87
+ def init_user_qstructs(cls, user_qstructs: list[QStructDeclaration]) -> None:
88
88
  cls.qstruct_table = QStructTable(user_qstructs)
89
89
  QMODULE.qstruct_decls = {
90
90
  qstruct_decl.name: qstruct_decl for qstruct_decl in user_qstructs
@@ -92,7 +92,7 @@ class SymbolTable:
92
92
 
93
93
 
94
94
  class HandleTable:
95
- _handle_map: Dict[HandleIdentifier, QmodPyObject] = {}
95
+ _handle_map: dict[HandleIdentifier, QmodPyObject] = {}
96
96
 
97
97
  @classmethod
98
98
  def get_handle_object(cls, hid: HandleIdentifier) -> Optional[QmodPyObject]:
@@ -1,5 +1,3 @@
1
- from typing import List
2
-
3
1
  from classiq.interface.exceptions import ClassiqExpansionError
4
2
  from classiq.interface.model.bind_operation import BindOperation
5
3
 
@@ -18,11 +16,11 @@ class BindEmitter(Emitter[BindOperation]):
18
16
  def emit(self, bind: BindOperation, /) -> None:
19
17
  with self._propagated_var_stack.capture_variables(bind):
20
18
  pass
21
- inputs: List[QuantumSymbol] = [
19
+ inputs: list[QuantumSymbol] = [
22
20
  self._interpreter.evaluate(arg).as_type(QuantumSymbol)
23
21
  for arg in bind.in_handles
24
22
  ]
25
- outputs: List[QuantumSymbol] = [
23
+ outputs: list[QuantumSymbol] = [
26
24
  self._interpreter.evaluate(arg).as_type(QuantumSymbol)
27
25
  for arg in bind.out_handles
28
26
  ]
@@ -1,4 +1,4 @@
1
- from typing import Sequence
1
+ from collections.abc import Sequence
2
2
 
3
3
  from classiq.interface.model.classical_if import ClassicalIf
4
4
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
@@ -1,5 +1,3 @@
1
- from typing import List, Tuple
2
-
3
1
  from sympy import Equality
4
2
  from sympy.logic.boolalg import Boolean
5
3
  from typing_extensions import TypeGuard
@@ -160,7 +158,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
160
158
  def _emit_with_x_gates(
161
159
  self, control: Control, ctrl: QmodSizedProxy, ctrl_state: str
162
160
  ) -> None:
163
- compute_op: List[ConcreteQuantumStatement] = []
161
+ compute_op: list[ConcreteQuantumStatement] = []
164
162
 
165
163
  x_gate_value = self._get_x_gate_value(ctrl_state)
166
164
  if x_gate_value != 0:
@@ -194,7 +192,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
194
192
 
195
193
  def _get_array_cast_ops(
196
194
  self, ctrl: QmodQNumProxy
197
- ) -> Tuple[VariableDeclarationStatement, BindOperation]:
195
+ ) -> tuple[VariableDeclarationStatement, BindOperation]:
198
196
  array_cast = self._counted_name_allocator.allocate(
199
197
  f"{ctrl.handle}{ARRAY_CAST_SUFFIX}"
200
198
  )
@@ -1,11 +1,9 @@
1
1
  from abc import abstractmethod
2
+ from collections.abc import Sequence
2
3
  from typing import (
3
4
  TYPE_CHECKING,
4
- Dict,
5
5
  Generic,
6
- List,
7
6
  Optional,
8
- Sequence,
9
7
  TypeVar,
10
8
  Union,
11
9
  cast,
@@ -18,7 +16,7 @@ from classiq.interface.generator.expressions.evaluated_expression import (
18
16
  EvaluatedExpression,
19
17
  )
20
18
  from classiq.interface.generator.expressions.expression import Expression
21
- from classiq.interface.ide.visual_model import OperationLevel
19
+ from classiq.interface.generator.generated_circuit_data import OperationLevel
22
20
  from classiq.interface.model.classical_parameter_declaration import (
23
21
  ClassicalParameterDeclaration,
24
22
  )
@@ -63,7 +61,6 @@ from classiq.qmod.quantum_function import GenerativeQFunc
63
61
  if TYPE_CHECKING:
64
62
  from classiq.model_expansions.interpreter import Interpreter
65
63
 
66
-
67
64
  QuantumStatementT = TypeVar("QuantumStatementT", bound=QuantumStatement)
68
65
 
69
66
 
@@ -74,7 +71,7 @@ class Emitter(Generic[QuantumStatementT]):
74
71
  self._scope_guard = self._interpreter._scope_guard
75
72
  self._machine_precision = self._interpreter._model.preferences.machine_precision
76
73
 
77
- self._generative_contexts: Dict[str, OperationContext] = {}
74
+ self._generative_contexts: dict[str, OperationContext] = {}
78
75
 
79
76
  @abstractmethod
80
77
  def emit(self, statement: QuantumStatementT, /) -> None:
@@ -103,7 +100,7 @@ class Emitter(Generic[QuantumStatementT]):
103
100
  return self._interpreter._current_scope
104
101
 
105
102
  @property
106
- def _expanded_functions(self) -> List[NativeFunctionDefinition]:
103
+ def _expanded_functions(self) -> list[NativeFunctionDefinition]:
107
104
  return self._interpreter._expanded_functions
108
105
 
109
106
  @property
@@ -125,14 +122,14 @@ class Emitter(Generic[QuantumStatementT]):
125
122
  return self._create_quantum_function_call(wrapping_function, list())
126
123
 
127
124
  def _emit_quantum_function_call(
128
- self, function: FunctionClosure, args: List[ArgValue]
125
+ self, function: FunctionClosure, args: list[ArgValue]
129
126
  ) -> QuantumFunctionCall:
130
127
  call = self._create_quantum_function_call(function, args)
131
128
  self._builder.emit_statement(call)
132
129
  return call
133
130
 
134
131
  def _create_quantum_function_call(
135
- self, function: FunctionClosure, args: List[ArgValue]
132
+ self, function: FunctionClosure, args: list[ArgValue]
136
133
  ) -> QuantumFunctionCall:
137
134
  evaluated_args = [self._interpreter.evaluate(arg) for arg in args]
138
135
  new_declaration = self._prepare_fully_typed_declaration(
@@ -206,10 +203,10 @@ class Emitter(Generic[QuantumStatementT]):
206
203
 
207
204
  def _get_new_positional_args(
208
205
  self,
209
- evaluated_args: List[Evaluated],
206
+ evaluated_args: list[Evaluated],
210
207
  is_atomic: bool,
211
208
  new_positional_arg_decls: Sequence[PositionalArg],
212
- ) -> List[ArgValue]:
209
+ ) -> list[ArgValue]:
213
210
  evaluated_args = add_information_from_output_arguments(
214
211
  new_positional_arg_decls, evaluated_args
215
212
  )
@@ -230,7 +227,7 @@ class Emitter(Generic[QuantumStatementT]):
230
227
  return positional_args
231
228
 
232
229
  def _prepare_fully_typed_declaration(
233
- self, function: FunctionClosure, evaluated_args: List[Evaluated]
230
+ self, function: FunctionClosure, evaluated_args: list[Evaluated]
234
231
  ) -> NamedParamsQuantumFunctionDeclaration:
235
232
  """
236
233
  Given, for example,
@@ -260,7 +257,7 @@ class Emitter(Generic[QuantumStatementT]):
260
257
  self,
261
258
  op: QuantumOperation,
262
259
  context_name: str,
263
- block_names: Union[None, str, List[str]] = None,
260
+ block_names: Union[None, str, list[str]] = None,
264
261
  func_decl: Optional[NamedParamsQuantumFunctionDeclaration] = None,
265
262
  ) -> OperationContext:
266
263
  if isinstance(block_names, str):
@@ -1,7 +1,7 @@
1
1
  import ast
2
2
  from abc import abstractmethod
3
3
  from itertools import chain
4
- from typing import TYPE_CHECKING, Dict, List, Tuple, TypeVar
4
+ from typing import TYPE_CHECKING, TypeVar
5
5
 
6
6
  from classiq.interface.exceptions import (
7
7
  ClassiqExpansionError,
@@ -26,6 +26,7 @@ from classiq.interface.model.quantum_type import (
26
26
  QuantumBit,
27
27
  QuantumBitvector,
28
28
  QuantumNumeric,
29
+ QuantumType,
29
30
  )
30
31
  from classiq.interface.model.variable_declaration_statement import (
31
32
  VariableDeclarationStatement,
@@ -48,7 +49,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
48
49
  self,
49
50
  op: ExpressionOperationT,
50
51
  expression: Expression,
51
- symbols_to_split: List[QuantumSymbol],
52
+ symbols_to_split: list[QuantumSymbol],
52
53
  ) -> None:
53
54
  symbols_parts, bind_ops = self._get_bind_ops(symbols_to_split)
54
55
 
@@ -62,14 +63,13 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
62
63
  )
63
64
  )
64
65
 
65
- new_expression = self._update_op_expression(
66
- {
67
- symbol.handle: symbol_part_var_name
68
- for symbol, symbol_part_var_name in chain.from_iterable(symbols_parts)
69
- },
70
- expression,
71
- )
66
+ symbol_mapping = {
67
+ symbol.handle: (symbol_part_var_name, symbol.quantum_type)
68
+ for symbol, symbol_part_var_name in chain.from_iterable(symbols_parts)
69
+ }
70
+ new_expression = self._update_op_expression(symbol_mapping, expression)
72
71
  new_op = op.model_copy(update=dict(expression=new_expression))
72
+ new_op = self._get_updated_op_split_symbols(new_op, symbol_mapping)
73
73
 
74
74
  self._interpreter.emit_statement(
75
75
  WithinApply(
@@ -79,9 +79,16 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
79
79
  )
80
80
  )
81
81
 
82
+ @staticmethod
83
+ def _get_updated_op_split_symbols(
84
+ op: ExpressionOperationT,
85
+ symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
86
+ ) -> ExpressionOperationT:
87
+ return op
88
+
82
89
  def _update_op_expression(
83
90
  self,
84
- symbol_parts: Dict[HandleBinding, str],
91
+ symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
85
92
  expression: Expression,
86
93
  ) -> Expression:
87
94
  vrc = VarRefCollector(ignore_duplicated_handles=True)
@@ -90,9 +97,9 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
90
97
  new_expr_str = expression.expr
91
98
  for handle in vrc.var_handles:
92
99
  collapsed_handle = handle.collapse()
93
- if collapsed_handle in symbol_parts:
100
+ if collapsed_handle in symbol_mapping:
94
101
  new_expr_str = new_expr_str.replace(
95
- str(handle), symbol_parts[collapsed_handle]
102
+ str(handle), symbol_mapping[collapsed_handle][0]
96
103
  )
97
104
  self._check_all_handles_were_replaced(new_expr_str)
98
105
 
@@ -115,8 +122,8 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
115
122
 
116
123
  def _get_bind_ops(
117
124
  self,
118
- symbols_to_split: List[QuantumSymbol],
119
- ) -> Tuple[List[List[Tuple[QuantumSymbol, str]]], List[BindOperation]]:
125
+ symbols_to_split: list[QuantumSymbol],
126
+ ) -> tuple[list[list[tuple[QuantumSymbol, str]]], list[BindOperation]]:
120
127
  bind_ops = []
121
128
  symbols_parts = []
122
129
  for symbol in symbols_to_split:
@@ -135,7 +142,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
135
142
 
136
143
  def _get_symbol_parts(
137
144
  self, symbol: QuantumSymbol
138
- ) -> List[Tuple[QuantumSymbol, str]]:
145
+ ) -> list[tuple[QuantumSymbol, str]]:
139
146
  quantum_type = symbol.quantum_type
140
147
 
141
148
  if isinstance(quantum_type, (QuantumBit, QuantumNumeric)):
@@ -169,7 +176,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
169
176
  )
170
177
  )
171
178
 
172
- def _get_symbols_to_split(self, expression: Expression) -> List[QuantumSymbol]:
179
+ def _get_symbols_to_split(self, expression: Expression) -> list[QuantumSymbol]:
173
180
  vrc = VarRefCollector(ignore_duplicated_handles=True)
174
181
  vrc.visit(ast.parse(expression.expr))
175
182
  symbol_names_to_split = dict.fromkeys(