classiq 0.43.3__py3-none-any.whl → 0.45.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 (220) hide show
  1. classiq/__init__.py +8 -3
  2. classiq/_internals/api_wrapper.py +2 -2
  3. classiq/_internals/authentication/auth0.py +1 -1
  4. classiq/_internals/authentication/device.py +5 -1
  5. classiq/_internals/authentication/token_manager.py +5 -4
  6. classiq/_internals/client.py +5 -8
  7. classiq/_internals/config.py +1 -2
  8. classiq/_internals/host_checker.py +34 -13
  9. classiq/_internals/jobs.py +3 -3
  10. classiq/analyzer/analyzer.py +1 -1
  11. classiq/analyzer/analyzer_utilities.py +1 -1
  12. classiq/analyzer/rb.py +1 -1
  13. classiq/applications/chemistry/chemistry_model_constructor.py +13 -7
  14. classiq/applications/combinatorial_helpers/allowed_constraints.py +4 -1
  15. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +1 -1
  16. classiq/applications/combinatorial_helpers/encoding_mapping.py +1 -1
  17. classiq/applications/combinatorial_helpers/encoding_utils.py +2 -1
  18. classiq/applications/combinatorial_helpers/optimization_model.py +1 -1
  19. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +1 -1
  20. classiq/applications/combinatorial_helpers/pyomo_utils.py +1 -2
  21. classiq/applications/combinatorial_helpers/transformations/encoding.py +1 -1
  22. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +5 -4
  23. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +1 -1
  24. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +1 -1
  25. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
  26. classiq/applications/finance/finance_model_constructor.py +4 -3
  27. classiq/applications/grover/grover_model_constructor.py +7 -5
  28. classiq/applications/hamiltonian/__init__.py +0 -0
  29. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  30. classiq/applications/qnn/circuit_utils.py +1 -1
  31. classiq/applications/qnn/datasets/dataset_base_classes.py +2 -1
  32. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  33. classiq/applications/qnn/qlayer.py +3 -2
  34. classiq/applications/qnn/torch_utils.py +2 -1
  35. classiq/applications/qsvm/qsvm_model_constructor.py +1 -1
  36. classiq/execution/execution_session.py +1 -1
  37. classiq/execution/jobs.py +5 -2
  38. classiq/interface/_version.py +1 -1
  39. classiq/interface/analyzer/cytoscape_graph.py +1 -2
  40. classiq/interface/analyzer/result.py +2 -3
  41. classiq/interface/ast_node.py +1 -18
  42. classiq/interface/backend/backend_preferences.py +11 -18
  43. classiq/interface/backend/ionq/ionq_quantum_program.py +1 -1
  44. classiq/interface/backend/pydantic_backend.py +0 -5
  45. classiq/interface/backend/quantum_backend_providers.py +4 -3
  46. classiq/interface/chemistry/fermionic_operator.py +1 -2
  47. classiq/interface/chemistry/ground_state_problem.py +2 -3
  48. classiq/interface/chemistry/molecule.py +1 -2
  49. classiq/interface/chemistry/operator.py +8 -10
  50. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  51. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +1 -1
  52. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  53. classiq/interface/debug_info/__init__.py +0 -0
  54. classiq/interface/debug_info/debug_info.py +32 -0
  55. classiq/{exceptions.py → interface/exceptions.py} +4 -0
  56. classiq/interface/executor/aws_execution_cost.py +2 -2
  57. classiq/interface/executor/execution_preferences.py +2 -47
  58. classiq/interface/executor/execution_result.py +1 -2
  59. classiq/interface/executor/optimizer_preferences.py +2 -3
  60. classiq/interface/executor/quantum_code.py +1 -2
  61. classiq/interface/executor/quantum_instruction_set.py +2 -2
  62. classiq/interface/executor/register_initialization.py +1 -2
  63. classiq/interface/executor/result.py +29 -14
  64. classiq/interface/finance/function_input.py +6 -11
  65. classiq/interface/generator/amplitude_loading.py +2 -3
  66. classiq/interface/generator/ansatz_library.py +1 -1
  67. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  68. classiq/interface/generator/application_apis/chemistry_declarations.py +78 -60
  69. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +19 -10
  70. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  71. classiq/interface/generator/application_apis/finance_declarations.py +37 -44
  72. classiq/interface/generator/application_apis/qsvm_declarations.py +21 -15
  73. classiq/interface/generator/arith/arithmetic.py +10 -8
  74. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +1 -2
  75. classiq/interface/generator/arith/arithmetic_expression_abc.py +22 -3
  76. classiq/interface/generator/arith/arithmetic_expression_parser.py +3 -4
  77. classiq/interface/generator/arith/arithmetic_expression_validator.py +1 -2
  78. classiq/interface/generator/arith/arithmetic_param_getters.py +1 -2
  79. classiq/interface/generator/arith/arithmetic_result_builder.py +15 -11
  80. classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
  81. classiq/interface/generator/arith/binary_ops.py +7 -7
  82. classiq/interface/generator/arith/endianness.py +1 -1
  83. classiq/interface/generator/arith/extremum_operations.py +44 -21
  84. classiq/interface/generator/arith/logical_ops.py +1 -2
  85. classiq/interface/generator/arith/register_user_input.py +1 -2
  86. classiq/interface/generator/arith/unary_ops.py +1 -2
  87. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  88. classiq/interface/generator/chemistry_function_params.py +1 -2
  89. classiq/interface/generator/circuit_code/circuit_code.py +1 -2
  90. classiq/interface/generator/circuit_code/types_and_constants.py +1 -2
  91. classiq/interface/generator/commuting_pauli_exponentiation.py +1 -2
  92. classiq/interface/generator/constant.py +1 -1
  93. classiq/interface/generator/control_state.py +1 -2
  94. classiq/interface/generator/custom_ansatz.py +1 -2
  95. classiq/interface/generator/expressions/atomic_expression_functions.py +1 -0
  96. classiq/interface/generator/expressions/enums/finance_functions.py +4 -5
  97. classiq/interface/generator/expressions/evaluated_expression.py +1 -2
  98. classiq/interface/generator/expressions/expression.py +1 -2
  99. classiq/interface/generator/expressions/expression_constants.py +3 -1
  100. classiq/interface/generator/expressions/non_symbolic_expr.py +1 -1
  101. classiq/interface/generator/expressions/qmod_qarray_proxy.py +53 -70
  102. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +2 -7
  103. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +35 -0
  104. classiq/interface/generator/expressions/qmod_sized_proxy.py +1 -1
  105. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  106. classiq/interface/generator/function_params.py +2 -3
  107. classiq/interface/generator/functions/builtins/core_library/__init__.py +4 -2
  108. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +41 -41
  109. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +52 -42
  110. classiq/interface/generator/functions/builtins/open_lib_functions.py +1095 -3347
  111. classiq/interface/generator/functions/builtins/quantum_operators.py +9 -22
  112. classiq/interface/generator/functions/classical_function_declaration.py +14 -6
  113. classiq/interface/generator/functions/classical_type.py +7 -114
  114. classiq/interface/generator/functions/concrete_types.py +55 -0
  115. classiq/interface/generator/functions/function_declaration.py +10 -10
  116. classiq/interface/generator/functions/port_declaration.py +1 -2
  117. classiq/interface/generator/functions/type_name.py +80 -0
  118. classiq/interface/generator/generated_circuit_data.py +3 -3
  119. classiq/interface/generator/grover_diffuser.py +1 -2
  120. classiq/interface/generator/grover_operator.py +1 -2
  121. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +1 -2
  122. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +1 -2
  123. classiq/interface/generator/hardware/hardware_data.py +1 -2
  124. classiq/interface/generator/hardware_efficient_ansatz.py +2 -3
  125. classiq/interface/generator/hartree_fock.py +1 -2
  126. classiq/interface/generator/linear_pauli_rotations.py +1 -2
  127. classiq/interface/generator/mcmt_method.py +1 -1
  128. classiq/interface/generator/mcu.py +1 -2
  129. classiq/interface/generator/mcx.py +1 -2
  130. classiq/interface/generator/model/constraints.py +2 -3
  131. classiq/interface/generator/model/model.py +12 -2
  132. classiq/interface/generator/model/preferences/preferences.py +7 -3
  133. classiq/interface/generator/model/quantum_register.py +1 -2
  134. classiq/interface/generator/oracles/arithmetic_oracle.py +1 -2
  135. classiq/interface/generator/oracles/custom_oracle.py +1 -2
  136. classiq/interface/generator/oracles/oracle_abc.py +1 -2
  137. classiq/interface/generator/partitioned_register.py +1 -2
  138. classiq/interface/generator/piecewise_linear_amplitude_loading.py +1 -2
  139. classiq/interface/generator/preferences/optimization.py +1 -2
  140. classiq/interface/generator/qpe.py +1 -2
  141. classiq/interface/generator/qsvm.py +2 -3
  142. classiq/interface/generator/quantum_function_call.py +4 -2
  143. classiq/interface/generator/quantum_program.py +6 -7
  144. classiq/interface/generator/range_types.py +1 -1
  145. classiq/interface/generator/register_role.py +8 -2
  146. classiq/interface/generator/slice_parsing_utils.py +1 -2
  147. classiq/interface/generator/standard_gates/controlled_standard_gates.py +1 -2
  148. classiq/interface/generator/state_preparation/metrics.py +2 -3
  149. classiq/interface/generator/state_preparation/state_preparation.py +1 -2
  150. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +1 -3
  151. classiq/interface/generator/transpiler_basis_gates.py +1 -1
  152. classiq/interface/generator/types/builtin_enum_declarations.py +38 -45
  153. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +1 -2
  154. classiq/interface/generator/types/enum_declaration.py +1 -2
  155. classiq/interface/generator/types/qstruct_declaration.py +17 -0
  156. classiq/interface/generator/types/struct_declaration.py +2 -3
  157. classiq/interface/generator/ucc.py +1 -2
  158. classiq/interface/generator/unitary_gate.py +1 -2
  159. classiq/interface/generator/validations/flow_graph.py +1 -2
  160. classiq/interface/generator/validations/validator_functions.py +1 -2
  161. classiq/interface/hardware.py +1 -1
  162. classiq/interface/helpers/validation_helpers.py +2 -19
  163. classiq/interface/ide/visual_model.py +10 -4
  164. classiq/interface/interface_version.py +1 -0
  165. classiq/interface/jobs.py +2 -3
  166. classiq/interface/model/bind_operation.py +26 -7
  167. classiq/interface/model/classical_parameter_declaration.py +8 -5
  168. classiq/interface/model/control.py +5 -5
  169. classiq/interface/model/handle_binding.py +185 -12
  170. classiq/interface/model/inplace_binary_operation.py +17 -6
  171. classiq/interface/model/model.py +29 -7
  172. classiq/interface/model/native_function_definition.py +8 -4
  173. classiq/interface/model/parameter.py +13 -0
  174. classiq/interface/model/port_declaration.py +21 -4
  175. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +22 -8
  176. classiq/interface/model/quantum_expressions/arithmetic_operation.py +30 -6
  177. classiq/interface/model/quantum_expressions/quantum_expression.py +4 -9
  178. classiq/interface/model/quantum_function_call.py +136 -194
  179. classiq/interface/model/quantum_function_declaration.py +147 -165
  180. classiq/interface/model/quantum_lambda_function.py +23 -6
  181. classiq/interface/model/quantum_statement.py +34 -8
  182. classiq/interface/model/quantum_type.py +41 -11
  183. classiq/interface/model/quantum_variable_declaration.py +1 -1
  184. classiq/interface/model/statement_block.py +2 -0
  185. classiq/interface/model/validation_handle.py +8 -2
  186. classiq/interface/server/global_versions.py +4 -4
  187. classiq/interface/server/routes.py +2 -0
  188. classiq/interface/source_reference.py +59 -0
  189. classiq/qmod/__init__.py +2 -3
  190. classiq/qmod/builtins/classical_execution_primitives.py +1 -1
  191. classiq/qmod/builtins/functions.py +39 -11
  192. classiq/qmod/builtins/operations.py +172 -41
  193. classiq/qmod/classical_function.py +1 -1
  194. classiq/qmod/declaration_inferrer.py +102 -57
  195. classiq/qmod/expression_query.py +1 -1
  196. classiq/qmod/model_state_container.py +2 -0
  197. classiq/qmod/native/pretty_printer.py +71 -53
  198. classiq/qmod/pretty_print/pretty_printer.py +98 -52
  199. classiq/qmod/qfunc.py +11 -5
  200. classiq/qmod/qmod_constant.py +1 -1
  201. classiq/qmod/qmod_parameter.py +27 -4
  202. classiq/qmod/qmod_variable.py +405 -174
  203. classiq/qmod/quantum_callable.py +3 -3
  204. classiq/qmod/quantum_expandable.py +128 -68
  205. classiq/qmod/quantum_function.py +24 -5
  206. classiq/qmod/semantics/annotation.py +13 -15
  207. classiq/qmod/semantics/error_manager.py +36 -10
  208. classiq/qmod/semantics/static_semantics_visitor.py +164 -76
  209. classiq/qmod/semantics/validation/func_call_validation.py +43 -97
  210. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  211. classiq/qmod/semantics/validation/types_validation.py +108 -1
  212. classiq/qmod/symbolic.py +2 -1
  213. classiq/qmod/type_attribute_remover.py +32 -0
  214. classiq/qmod/utilities.py +26 -5
  215. classiq/{interface/ide/show.py → show.py} +1 -1
  216. {classiq-0.43.3.dist-info → classiq-0.45.0.dist-info}/METADATA +3 -3
  217. {classiq-0.43.3.dist-info → classiq-0.45.0.dist-info}/RECORD +219 -207
  218. classiq/qmod/qmod_struct.py +0 -13
  219. /classiq/{_internals → interface}/enum_utils.py +0 -0
  220. {classiq-0.43.3.dist-info → classiq-0.45.0.dist-info}/WHEEL +0 -0
@@ -1,68 +1,76 @@
1
1
  import dataclasses
2
2
  import inspect
3
+ import sys
3
4
  from enum import EnumMeta
4
5
  from typing import (
5
6
  Any,
6
7
  Callable,
7
- Dict,
8
8
  List,
9
+ Literal,
9
10
  Optional,
11
+ Sequence,
12
+ Tuple,
10
13
  Type,
11
14
  get_args,
12
15
  get_origin,
16
+ overload,
13
17
  )
14
18
 
15
19
  from typing_extensions import _AnnotatedAlias
16
20
 
21
+ from classiq.interface.exceptions import ClassiqValueError
17
22
  from classiq.interface.generator.functions.classical_type import (
18
23
  Bool,
19
24
  ClassicalArray,
20
25
  ClassicalList,
21
- ConcreteClassicalType,
22
- Enum,
23
26
  Integer,
24
27
  Real,
25
- Struct,
26
28
  )
29
+ from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
30
+ from classiq.interface.generator.functions.port_declaration import (
31
+ PortDeclarationDirection,
32
+ )
33
+ from classiq.interface.generator.functions.type_name import Enum
27
34
  from classiq.interface.generator.types.enum_declaration import (
28
35
  EnumDeclaration,
29
36
  declaration_from_enum,
30
37
  )
31
38
  from classiq.interface.model.classical_parameter_declaration import (
32
- ClassicalParameterDeclaration,
39
+ AnonClassicalParameterDeclaration,
33
40
  )
34
- from classiq.interface.model.port_declaration import PortDeclaration
41
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
35
42
  from classiq.interface.model.quantum_function_declaration import (
43
+ AnonPositionalArg,
44
+ AnonQuantumOperandDeclaration,
45
+ NamedParamsQuantumFunctionDeclaration,
36
46
  PositionalArg,
37
- QuantumFunctionDeclaration,
38
- QuantumOperandDeclaration,
39
47
  )
40
48
 
41
- from classiq import StructDeclaration
42
- from classiq.exceptions import ClassiqValueError
49
+ from classiq import Struct, StructDeclaration
43
50
  from classiq.qmod.model_state_container import ModelStateContainer
44
- from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CParam, CReal
51
+ from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CReal
45
52
  from classiq.qmod.qmod_variable import QVar, get_type_hint_expr
46
- from classiq.qmod.quantum_callable import QCallable, QCallableList
53
+ from classiq.qmod.quantum_callable import QCallableList
47
54
  from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
48
55
 
49
- OPERAND_ARG_NAME = "arg{i}"
56
+ if sys.version_info[0:2] >= (3, 9):
57
+ from typing import Annotated
50
58
 
51
59
 
52
60
  def python_type_to_qmod(
53
61
  py_type: type, *, qmodule: ModelStateContainer
54
62
  ) -> Optional[ConcreteClassicalType]:
55
- if py_type == int or py_type is CInt:
63
+ if py_type is int or py_type is CInt:
56
64
  return Integer()
57
- elif py_type == float or py_type is CReal:
65
+ elif py_type in (float, complex) or py_type is CReal:
58
66
  return Real()
59
- elif py_type == bool or py_type is CBool:
67
+ elif py_type is bool or py_type is CBool:
60
68
  return Bool()
61
- elif get_origin(py_type) == list:
62
- return ClassicalList(
63
- element_type=python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
64
- )
65
- elif get_origin(py_type) == CArray:
69
+ elif get_origin(py_type) is list:
70
+ element_type = python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
71
+ if element_type is not None:
72
+ return ClassicalList(element_type=element_type)
73
+ elif get_origin(py_type) is CArray:
66
74
  array_args = version_portable_get_args(py_type)
67
75
  if len(array_args) == 1:
68
76
  return ClassicalList(
@@ -112,72 +120,109 @@ def _add_qmod_struct(py_type: Type, *, qmodule: ModelStateContainer) -> None:
112
120
  )
113
121
 
114
122
 
115
- def _extract_port_decl(name: str, py_type: Any) -> PortDeclaration:
123
+ def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration:
116
124
  # FIXME: CAD-13409
117
125
  qtype: Type[QVar] = QVar.from_type_hint(py_type) # type:ignore[assignment]
118
126
  direction = qtype.port_direction(py_type)
119
127
  if isinstance(py_type, _AnnotatedAlias):
120
128
  py_type = py_type.__args__[0]
121
- return PortDeclaration(
122
- name=name,
129
+ param = AnonPortDeclaration(
130
+ name=None,
123
131
  direction=direction,
124
132
  quantum_type=qtype.to_qmod_quantum_type(py_type),
125
133
  )
134
+ if name is not None:
135
+ param = param.rename(name)
136
+ return param
126
137
 
127
138
 
128
139
  def _extract_operand_decl(
129
- name: str, py_type: Any, qmodule: ModelStateContainer
130
- ) -> QuantumOperandDeclaration:
131
- qc_args = version_portable_get_args(py_type)
132
- arg_dict = {
133
- OPERAND_ARG_NAME.format(i=i): arg_type for i, arg_type in enumerate(qc_args)
134
- }
135
- return QuantumOperandDeclaration(
140
+ name: Optional[str], py_type: Any, qmodule: ModelStateContainer
141
+ ) -> AnonQuantumOperandDeclaration:
142
+ is_list = (get_origin(py_type) or py_type) is QCallableList
143
+ if get_origin(py_type) is list:
144
+ is_list = True
145
+ py_type = version_portable_get_args(py_type)
146
+ type_args = version_portable_get_args(py_type)
147
+ param_decls = [_extract_operand_param(arg_type) for arg_type in type_args]
148
+ param = AnonQuantumOperandDeclaration(
136
149
  name=name,
137
- positional_arg_declarations=_extract_positional_args(arg_dict, qmodule=qmodule),
138
- is_list=(get_origin(py_type) or py_type) is QCallableList,
150
+ positional_arg_declarations=_extract_positional_args(
151
+ param_decls, qmodule=qmodule
152
+ ),
153
+ is_list=is_list,
154
+ )
155
+ if name is not None:
156
+ param = param.rename(name)
157
+ return param
158
+
159
+
160
+ def _extract_operand_param(py_type: Any) -> Tuple[Optional[str], Any]:
161
+ if sys.version_info[0:2] < (3, 9) or get_origin(py_type) is not Annotated:
162
+ return None, py_type
163
+ args = get_args(py_type)
164
+ if len(args) == 2:
165
+ if isinstance(args[1], PortDeclarationDirection):
166
+ return None, py_type
167
+ elif isinstance(args[1], str):
168
+ return args[1], args[0]
169
+ elif get_origin(args[1]) is Literal:
170
+ return version_portable_get_args(args[1])[0], args[0]
171
+ elif len(args) == 3 and isinstance(args[1], PortDeclarationDirection):
172
+ if isinstance(args[2], str):
173
+ return args[2], Annotated[args[0], args[1]]
174
+ elif get_origin(args[2]) is Literal:
175
+ return version_portable_get_args(args[2])[0], Annotated[args[0], args[1]]
176
+ raise ClassiqValueError(
177
+ f"Operand parameter declaration must be of the form <param-type> or "
178
+ f"Annotated[<param-type>, <param-name>]. Got {py_type}"
139
179
  )
140
180
 
141
181
 
182
+ @overload
142
183
  def _extract_positional_args(
143
- args: Dict[str, Any], qmodule: ModelStateContainer
144
- ) -> List[PositionalArg]:
145
- result: List[PositionalArg] = []
146
- for name, py_type in args.items():
184
+ args: Sequence[Tuple[str, Any]], qmodule: ModelStateContainer
185
+ ) -> Sequence[PositionalArg]:
186
+ pass
187
+
188
+
189
+ @overload
190
+ def _extract_positional_args(
191
+ args: Sequence[Tuple[Optional[str], Any]], qmodule: ModelStateContainer
192
+ ) -> Sequence[AnonPositionalArg]:
193
+ pass
194
+
195
+
196
+ def _extract_positional_args(
197
+ args: Sequence[Tuple[Optional[str], Any]], qmodule: ModelStateContainer
198
+ ) -> Sequence[AnonPositionalArg]:
199
+ result: List[AnonPositionalArg] = []
200
+ for name, py_type in args:
147
201
  if name == "return":
148
202
  continue
149
203
  name = unmangle_keyword(name)
150
- if (
151
- inspect.isclass(py_type)
152
- and (
153
- issubclass(py_type, CParam)
154
- or dataclasses.is_dataclass(py_type)
155
- or isinstance(py_type, EnumMeta)
156
- )
157
- or get_origin(py_type) == CArray
158
- ):
159
- result.append(
160
- ClassicalParameterDeclaration(
161
- name=name,
162
- classical_type=python_type_to_qmod(py_type, qmodule=qmodule),
163
- )
204
+ classical_type = python_type_to_qmod(py_type, qmodule=qmodule)
205
+ if classical_type is not None:
206
+ param = AnonClassicalParameterDeclaration(
207
+ name=None,
208
+ classical_type=classical_type,
164
209
  )
210
+ if name is not None:
211
+ param = param.rename(name)
212
+ result.append(param)
165
213
  elif QVar.from_type_hint(py_type) is not None:
166
214
  result.append(_extract_port_decl(name, py_type))
167
215
  else:
168
- assert (get_origin(py_type) or py_type) is QCallable or (
169
- get_origin(py_type) or py_type
170
- ) is QCallableList
171
216
  result.append(_extract_operand_decl(name, py_type, qmodule=qmodule))
172
217
  return result
173
218
 
174
219
 
175
220
  def infer_func_decl(
176
221
  py_func: Callable, qmodule: ModelStateContainer
177
- ) -> QuantumFunctionDeclaration:
178
- return QuantumFunctionDeclaration(
222
+ ) -> NamedParamsQuantumFunctionDeclaration:
223
+ return NamedParamsQuantumFunctionDeclaration(
179
224
  name=unmangle_keyword(py_func.__name__),
180
225
  positional_arg_declarations=_extract_positional_args(
181
- py_func.__annotations__, qmodule=qmodule
226
+ list(py_func.__annotations__.items()), qmodule=qmodule
182
227
  ),
183
228
  )
@@ -15,7 +15,7 @@ def get_expression_numeric_attributes(
15
15
  ) -> Tuple[int, bool, int]:
16
16
  res_type = compute_arithmetic_result_type(
17
17
  expr_str=str(expr),
18
- var_types={var._name: var.get_qmod_type() for var in vars},
18
+ var_types={str(var.get_handle_binding()): var.get_qmod_type() for var in vars},
19
19
  machine_precision=machine_precision,
20
20
  )
21
21
  if TYPE_CHECKING:
@@ -2,6 +2,7 @@ from typing import Dict
2
2
 
3
3
  from classiq.interface.generator.constant import Constant
4
4
  from classiq.interface.generator.types.enum_declaration import EnumDeclaration
5
+ from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
5
6
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
6
7
 
7
8
  from classiq import StructDeclaration
@@ -10,6 +11,7 @@ from classiq import StructDeclaration
10
11
  class ModelStateContainer:
11
12
  enum_decls: Dict[str, EnumDeclaration]
12
13
  type_decls: Dict[str, StructDeclaration]
14
+ qstruct_decls: Dict[str, QStructDeclaration]
13
15
  native_defs: Dict[str, NativeFunctionDefinition]
14
16
  constants: Dict[str, Constant]
15
17
 
@@ -1,24 +1,29 @@
1
- from typing import Dict, List, Optional
1
+ from typing import Dict, List, Mapping, Optional, Union
2
2
 
3
3
  from classiq.interface.generator.constant import Constant
4
4
  from classiq.interface.generator.expressions.expression import Expression
5
5
  from classiq.interface.generator.functions.classical_type import (
6
6
  ClassicalArray,
7
+ )
8
+ from classiq.interface.generator.functions.concrete_types import (
7
9
  ConcreteClassicalType,
8
- TypeName,
10
+ ConcreteQuantumType,
9
11
  )
10
12
  from classiq.interface.generator.functions.port_declaration import (
11
13
  PortDeclarationDirection,
12
14
  )
15
+ from classiq.interface.generator.functions.type_name import TypeName
13
16
  from classiq.interface.generator.types.enum_declaration import EnumDeclaration
17
+ from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
14
18
  from classiq.interface.generator.visitor import NodeType, Visitor
15
19
  from classiq.interface.model.bind_operation import BindOperation
16
20
  from classiq.interface.model.classical_if import ClassicalIf
17
21
  from classiq.interface.model.classical_parameter_declaration import (
18
- ClassicalParameterDeclaration,
22
+ AnonClassicalParameterDeclaration,
19
23
  )
20
24
  from classiq.interface.model.control import Control
21
25
  from classiq.interface.model.handle_binding import (
26
+ FieldHandleBinding,
22
27
  HandleBinding,
23
28
  SlicedHandleBinding,
24
29
  SubscriptHandleBinding,
@@ -27,7 +32,9 @@ from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperat
27
32
  from classiq.interface.model.invert import Invert
28
33
  from classiq.interface.model.model import Model
29
34
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
30
- from classiq.interface.model.port_declaration import PortDeclaration
35
+ from classiq.interface.model.port_declaration import (
36
+ AnonPortDeclaration,
37
+ )
31
38
  from classiq.interface.model.power import Power
32
39
  from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
33
40
  AmplitudeLoadingOperation,
@@ -40,6 +47,8 @@ from classiq.interface.model.quantum_function_call import (
40
47
  QuantumFunctionCall,
41
48
  )
42
49
  from classiq.interface.model.quantum_function_declaration import (
50
+ AnonQuantumFunctionDeclaration,
51
+ AnonQuantumOperandDeclaration,
43
52
  QuantumFunctionDeclaration,
44
53
  QuantumOperandDeclaration,
45
54
  )
@@ -59,7 +68,13 @@ from classiq.interface.model.variable_declaration_statement import (
59
68
  )
60
69
  from classiq.interface.model.within_apply_operation import WithinApply
61
70
 
62
- from classiq import Bool, ClassicalList, Integer, Real, StructDeclaration
71
+ from classiq import (
72
+ Bool,
73
+ ClassicalList,
74
+ Integer,
75
+ Real,
76
+ StructDeclaration,
77
+ )
63
78
  from classiq.qmod.native.expression_to_qmod import transform_expression
64
79
  from classiq.qmod.semantics.static_semantics_visitor import (
65
80
  static_semantics_analysis_pass,
@@ -82,36 +97,37 @@ class DSLPrettyPrinter(Visitor):
82
97
 
83
98
  def visit_Model(self, model: Model) -> str:
84
99
  # FIXME - CAD-20149: Remove this line once the froggies are removed, and the visit of lambdas can be done without accessing the func_decl property (with rename_params values only).
85
- static_semantics_analysis_pass(model)
100
+ static_semantics_analysis_pass(model, None)
86
101
  enum_decls = [self.visit(enum_decl) for enum_decl in model.enums]
87
102
  struct_decls = [self.visit(struct_decl) for struct_decl in model.types]
103
+ qstruct_decls = [self.visit(qstruct_decl) for qstruct_decl in model.qstructs]
88
104
  func_defs = [self.visit(func_def) for func_def in model.functions]
89
105
  constants = [self.visit(constant) for constant in model.constants]
90
106
  classical_code = (
91
- f"cscope ```\n{model.classical_execution_code}\n```"
107
+ [f"cscope ```\n{model.classical_execution_code}\n```\n"]
92
108
  if model.classical_execution_code
93
- else ""
109
+ else []
94
110
  )
111
+
95
112
  return "\n".join(
96
- [*constants, *enum_decls, *struct_decls, *func_defs, classical_code]
113
+ [
114
+ *constants,
115
+ *enum_decls,
116
+ *struct_decls,
117
+ *qstruct_decls,
118
+ *func_defs,
119
+ *classical_code,
120
+ ]
97
121
  )
98
122
 
99
123
  def visit_Constant(self, constant: Constant) -> str:
100
124
  return f"{self._indent}{self.visit(constant.name)}: {self.visit(constant.const_type)} = {self.visit(constant.value)};\n"
101
125
 
102
- def _visit_arg_decls(self, func_def: QuantumFunctionDeclaration) -> str:
103
- gen_time_args = ", ".join(
104
- self.visit(arg_decl)
105
- for arg_decl in func_def.get_positional_arg_decls()
106
- if not isinstance(arg_decl, PortDeclaration)
107
- )
108
- quantum_args = ", ".join(
109
- self.visit(arg_decl)
110
- for arg_decl in func_def.get_positional_arg_decls()
111
- if isinstance(arg_decl, PortDeclaration)
126
+ def _visit_arg_decls(self, func_def: AnonQuantumFunctionDeclaration) -> str:
127
+ positional_args = ", ".join(
128
+ self.visit(arg_decl) for arg_decl in func_def.positional_arg_declarations
112
129
  )
113
- gen_time_arg_list = f"<{gen_time_args}>" if gen_time_args else ""
114
- return f"{gen_time_arg_list}({quantum_args})"
130
+ return f"({positional_args})"
115
131
 
116
132
  def visit_QuantumFunctionDeclaration(
117
133
  self, func_decl: QuantumFunctionDeclaration
@@ -133,7 +149,12 @@ class DSLPrettyPrinter(Visitor):
133
149
  def visit_StructDeclaration(self, struct_decl: StructDeclaration) -> str:
134
150
  return f"struct {struct_decl.name} {{\n{self._visit_variables(struct_decl.variables)}}}\n"
135
151
 
136
- def _visit_variables(self, variables: Dict[str, ConcreteClassicalType]) -> str:
152
+ def visit_QStructDeclaration(self, qstruct_decl: QStructDeclaration) -> str:
153
+ return f"qstruct {qstruct_decl.name} {{\n{self._visit_variables(qstruct_decl.fields)}}}\n"
154
+
155
+ def _visit_variables(
156
+ self, variables: Mapping[str, Union[ConcreteClassicalType, ConcreteQuantumType]]
157
+ ) -> str:
137
158
  self._level += 1
138
159
  variables_str = "".join(
139
160
  f"{self._indent}{self.visit(field_name)}: {self.visit(var_decl)};\n"
@@ -147,13 +168,14 @@ class DSLPrettyPrinter(Visitor):
147
168
  ) -> str:
148
169
  return f"{var_decl.name}: {self.visit(var_decl.quantum_type)}"
149
170
 
150
- def visit_PortDeclaration(self, port_decl: PortDeclaration) -> str:
171
+ def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
151
172
  dir_str = (
152
173
  f"{port_decl.direction} "
153
174
  if port_decl.direction != PortDeclarationDirection.Inout
154
175
  else ""
155
176
  )
156
- return f"{dir_str}{self.visit_QuantumVariableDeclaration(port_decl)}"
177
+ param_name = f"{port_decl.name}: " if port_decl.name is not None else ""
178
+ return f"{dir_str}{param_name}{self.visit(port_decl.quantum_type)}"
157
179
 
158
180
  def visit_QuantumBit(self, qtype: QuantumBit) -> str:
159
181
  return "qbit"
@@ -179,10 +201,11 @@ class DSLPrettyPrinter(Visitor):
179
201
 
180
202
  return f"qnum{params}"
181
203
 
182
- def visit_ClassicalParameterDeclaration(
183
- self, cparam: ClassicalParameterDeclaration
204
+ def visit_AnonClassicalParameterDeclaration(
205
+ self, cparam: AnonClassicalParameterDeclaration
184
206
  ) -> str:
185
- return f"{cparam.name}: {self.visit(cparam.classical_type)}"
207
+ param_name = f"{cparam.name}: " if cparam.name is not None else ""
208
+ return f"{param_name}{self.visit(cparam.classical_type)}"
186
209
 
187
210
  def visit_Integer(self, ctint: Integer) -> str:
188
211
  return "int"
@@ -207,10 +230,16 @@ class DSLPrettyPrinter(Visitor):
207
230
  ) -> str:
208
231
  return f"{self._indent}{self.visit_QuantumVariableDeclaration(local_decl)};\n"
209
232
 
233
+ def visit_AnonQuantumOperandDeclaration(
234
+ self, op_decl: AnonQuantumOperandDeclaration
235
+ ) -> str:
236
+ param_name = f"{op_decl.name}: " if op_decl.name is not None else ""
237
+ return f"{param_name}qfunc{[] if op_decl.is_list else ''} {self._visit_arg_decls(op_decl)}"
238
+
210
239
  def visit_QuantumOperandDeclaration(
211
240
  self, op_decl: QuantumOperandDeclaration
212
241
  ) -> str:
213
- return f"{op_decl.name}: qfunc{[] if op_decl.is_list else ''} {self._visit_arg_decls(op_decl)}"
242
+ return self.visit_AnonQuantumOperandDeclaration(op_decl)
214
243
 
215
244
  def visit_NativeFunctionDefinition(self, func_def: NativeFunctionDefinition) -> str:
216
245
  self._level += 1
@@ -219,18 +248,10 @@ class DSLPrettyPrinter(Visitor):
219
248
  return f"{self.visit_QuantumFunctionDeclaration(func_def)} {{\n{body}}}\n"
220
249
 
221
250
  def visit_QuantumFunctionCall(self, func_call: QuantumFunctionCall) -> str:
222
- gen_time_args = ", ".join(
223
- self.visit(arg_decl)
224
- for arg_decl in func_call.get_positional_args()
225
- if not isinstance(arg_decl, HandleBinding)
226
- )
227
- gen_time_arg_list = f"<{gen_time_args}>" if gen_time_args else ""
228
- quantum_args = ", ".join(
229
- self.visit(arg_decl)
230
- for arg_decl in func_call.get_positional_args()
231
- if isinstance(arg_decl, HandleBinding)
251
+ positional_args = ", ".join(
252
+ self.visit(arg_decl) for arg_decl in func_call.positional_args
232
253
  )
233
- return f"{self._indent}{func_call.func_name}{f'[{self.visit(func_call.function.index)}]' if isinstance(func_call.function, OperandIdentifier) else ''}{gen_time_arg_list}({quantum_args});\n"
254
+ return f"{self._indent}{func_call.func_name}{f'[{self.visit(func_call.function.index)}]' if isinstance(func_call.function, OperandIdentifier) else ''}({positional_args});\n"
234
255
 
235
256
  def visit_Control(self, op: Control) -> str:
236
257
  control = f"{self._indent}control ({self.visit(op.expression)}) {{\n"
@@ -301,29 +322,26 @@ class DSLPrettyPrinter(Visitor):
301
322
  )
302
323
 
303
324
  def visit_QuantumLambdaFunction(self, qlambda: QuantumLambdaFunction) -> str:
304
- assert qlambda.func_decl is not None
305
- gen_time_args = ", ".join(
306
- qlambda.rename_params.get(arg_decl.name, arg_decl.name)
307
- for arg_decl in qlambda.func_decl.get_positional_arg_decls()
308
- if not isinstance(arg_decl, PortDeclaration)
309
- )
310
- quantum_args = ", ".join(
311
- qlambda.rename_params.get(arg_decl.name, arg_decl.name)
312
- for arg_decl in qlambda.func_decl.get_positional_arg_decls()
313
- if isinstance(arg_decl, PortDeclaration)
325
+ positional_args = ", ".join(
326
+ qlambda.get_rename_params()[idx]
327
+ for idx, arg_decl in enumerate(
328
+ qlambda.func_decl.positional_arg_declarations
329
+ )
314
330
  )
315
- gen_time_arg_list = f"<{gen_time_args}>" if gen_time_args else ""
316
331
  body = self._visit_body(qlambda.body)
317
- return f"lambda{gen_time_arg_list}({quantum_args}) {{\n{body}{self._indent}}}"
332
+ return f"lambda({positional_args}) {{\n{body}{self._indent}}}"
318
333
 
319
334
  def visit_HandleBinding(self, var_ref: HandleBinding) -> str:
320
335
  return var_ref.name
321
336
 
322
337
  def visit_SlicedHandleBinding(self, var_ref: SlicedHandleBinding) -> str:
323
- return f"{var_ref.name}[{self.visit(var_ref.start)}:{self.visit(var_ref.end)}]"
338
+ return f"{self.visit(var_ref.base_handle)}[{self.visit(var_ref.start)}:{self.visit(var_ref.end)}]"
324
339
 
325
340
  def visit_SubscriptHandleBinding(self, var_ref: SubscriptHandleBinding) -> str:
326
- return f"{var_ref.name}[{self.visit(var_ref.index)}]"
341
+ return f"{self.visit(var_ref.base_handle)}[{self.visit(var_ref.index)}]"
342
+
343
+ def visit_FieldHandleBinding(self, var_ref: FieldHandleBinding) -> str:
344
+ return f"{self.visit(var_ref.base_handle)}.{self.visit(var_ref.field)}"
327
345
 
328
346
  def visit_ArithmeticOperation(self, arith_op: ArithmeticOperation) -> str:
329
347
  op = "^=" if arith_op.inplace_result else "="