classiq 0.43.3__py3-none-any.whl → 0.44.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 (112) hide show
  1. classiq/__init__.py +7 -1
  2. classiq/_internals/client.py +4 -7
  3. classiq/_internals/host_checker.py +34 -12
  4. classiq/_internals/jobs.py +2 -2
  5. classiq/applications/chemistry/chemistry_model_constructor.py +12 -6
  6. classiq/applications/combinatorial_helpers/allowed_constraints.py +4 -1
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
  8. classiq/applications/finance/finance_model_constructor.py +3 -2
  9. classiq/applications/grover/grover_model_constructor.py +7 -5
  10. classiq/applications/hamiltonian/__init__.py +0 -0
  11. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  12. classiq/applications/qnn/qlayer.py +1 -1
  13. classiq/exceptions.py +4 -0
  14. classiq/interface/_version.py +1 -1
  15. classiq/interface/ast_node.py +1 -18
  16. classiq/interface/backend/backend_preferences.py +10 -16
  17. classiq/interface/backend/ionq/ionq_quantum_program.py +1 -1
  18. classiq/interface/backend/pydantic_backend.py +0 -5
  19. classiq/interface/backend/quantum_backend_providers.py +3 -2
  20. classiq/interface/chemistry/operator.py +5 -1
  21. classiq/interface/debug_info/__init__.py +0 -0
  22. classiq/interface/debug_info/debug_info.py +32 -0
  23. classiq/interface/executor/execution_preferences.py +1 -45
  24. classiq/interface/executor/result.py +25 -12
  25. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  26. classiq/interface/generator/application_apis/chemistry_declarations.py +78 -60
  27. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +19 -10
  28. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  29. classiq/interface/generator/application_apis/finance_declarations.py +36 -22
  30. classiq/interface/generator/application_apis/qsvm_declarations.py +21 -15
  31. classiq/interface/generator/arith/arithmetic_expression_abc.py +21 -1
  32. classiq/interface/generator/arith/binary_ops.py +5 -4
  33. classiq/interface/generator/arith/extremum_operations.py +43 -19
  34. classiq/interface/generator/constant.py +1 -1
  35. classiq/interface/generator/expressions/atomic_expression_functions.py +1 -0
  36. classiq/interface/generator/expressions/expression_constants.py +3 -1
  37. classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -66
  38. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +35 -0
  39. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  40. classiq/interface/generator/functions/builtins/core_library/__init__.py +4 -2
  41. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +41 -41
  42. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +52 -42
  43. classiq/interface/generator/functions/builtins/open_lib_functions.py +1095 -3347
  44. classiq/interface/generator/functions/builtins/quantum_operators.py +9 -22
  45. classiq/interface/generator/functions/classical_function_declaration.py +14 -6
  46. classiq/interface/generator/functions/classical_type.py +7 -76
  47. classiq/interface/generator/functions/concrete_types.py +55 -0
  48. classiq/interface/generator/functions/function_declaration.py +10 -10
  49. classiq/interface/generator/functions/type_name.py +104 -0
  50. classiq/interface/generator/generated_circuit_data.py +3 -3
  51. classiq/interface/generator/model/model.py +11 -0
  52. classiq/interface/generator/model/preferences/preferences.py +5 -0
  53. classiq/interface/generator/quantum_function_call.py +3 -0
  54. classiq/interface/generator/quantum_program.py +2 -2
  55. classiq/interface/generator/register_role.py +7 -1
  56. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +1 -3
  57. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +1 -2
  58. classiq/interface/generator/types/qstruct_declaration.py +17 -0
  59. classiq/interface/generator/types/struct_declaration.py +1 -1
  60. classiq/interface/helpers/validation_helpers.py +1 -17
  61. classiq/interface/ide/visual_model.py +9 -2
  62. classiq/interface/interface_version.py +1 -0
  63. classiq/interface/model/bind_operation.py +25 -5
  64. classiq/interface/model/classical_parameter_declaration.py +8 -5
  65. classiq/interface/model/control.py +5 -5
  66. classiq/interface/model/handle_binding.py +185 -12
  67. classiq/interface/model/inplace_binary_operation.py +16 -4
  68. classiq/interface/model/model.py +28 -5
  69. classiq/interface/model/native_function_definition.py +8 -4
  70. classiq/interface/model/parameter.py +14 -0
  71. classiq/interface/model/port_declaration.py +20 -2
  72. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +21 -6
  73. classiq/interface/model/quantum_expressions/arithmetic_operation.py +30 -6
  74. classiq/interface/model/quantum_expressions/quantum_expression.py +4 -9
  75. classiq/interface/model/quantum_function_call.py +135 -192
  76. classiq/interface/model/quantum_function_declaration.py +147 -165
  77. classiq/interface/model/quantum_lambda_function.py +24 -6
  78. classiq/interface/model/quantum_statement.py +34 -8
  79. classiq/interface/model/quantum_type.py +61 -10
  80. classiq/interface/model/quantum_variable_declaration.py +1 -1
  81. classiq/interface/model/statement_block.py +2 -0
  82. classiq/interface/model/validation_handle.py +7 -0
  83. classiq/interface/server/global_versions.py +4 -4
  84. classiq/interface/server/routes.py +2 -0
  85. classiq/interface/source_reference.py +59 -0
  86. classiq/qmod/__init__.py +2 -3
  87. classiq/qmod/builtins/functions.py +39 -11
  88. classiq/qmod/builtins/operations.py +171 -40
  89. classiq/qmod/declaration_inferrer.py +99 -56
  90. classiq/qmod/expression_query.py +1 -1
  91. classiq/qmod/model_state_container.py +2 -0
  92. classiq/qmod/native/pretty_printer.py +71 -53
  93. classiq/qmod/pretty_print/pretty_printer.py +98 -52
  94. classiq/qmod/qfunc.py +11 -5
  95. classiq/qmod/qmod_parameter.py +1 -2
  96. classiq/qmod/qmod_variable.py +364 -172
  97. classiq/qmod/quantum_callable.py +3 -3
  98. classiq/qmod/quantum_expandable.py +119 -65
  99. classiq/qmod/quantum_function.py +15 -3
  100. classiq/qmod/semantics/annotation.py +12 -13
  101. classiq/qmod/semantics/error_manager.py +36 -10
  102. classiq/qmod/semantics/static_semantics_visitor.py +163 -75
  103. classiq/qmod/semantics/validation/func_call_validation.py +42 -96
  104. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  105. classiq/qmod/semantics/validation/types_validation.py +108 -1
  106. classiq/qmod/type_attribute_remover.py +32 -0
  107. classiq/qmod/utilities.py +26 -5
  108. {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/METADATA +3 -3
  109. {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/RECORD +111 -99
  110. classiq/qmod/qmod_struct.py +0 -13
  111. /classiq/{interface/ide/show.py → show.py} +0 -0
  112. {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/WHEEL +0 -0
@@ -1,15 +1,18 @@
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
9
  Optional,
10
+ Sequence,
11
+ Tuple,
10
12
  Type,
11
13
  get_args,
12
14
  get_origin,
15
+ overload,
13
16
  )
14
17
 
15
18
  from typing_extensions import _AnnotatedAlias
@@ -18,51 +21,55 @@ from classiq.interface.generator.functions.classical_type import (
18
21
  Bool,
19
22
  ClassicalArray,
20
23
  ClassicalList,
21
- ConcreteClassicalType,
22
- Enum,
23
24
  Integer,
24
25
  Real,
25
- Struct,
26
26
  )
27
+ from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
28
+ from classiq.interface.generator.functions.port_declaration import (
29
+ PortDeclarationDirection,
30
+ )
31
+ from classiq.interface.generator.functions.type_name import Enum
27
32
  from classiq.interface.generator.types.enum_declaration import (
28
33
  EnumDeclaration,
29
34
  declaration_from_enum,
30
35
  )
31
36
  from classiq.interface.model.classical_parameter_declaration import (
32
- ClassicalParameterDeclaration,
37
+ AnonClassicalParameterDeclaration,
33
38
  )
34
- from classiq.interface.model.port_declaration import PortDeclaration
39
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
35
40
  from classiq.interface.model.quantum_function_declaration import (
41
+ AnonPositionalArg,
42
+ AnonQuantumOperandDeclaration,
43
+ NamedParamsQuantumFunctionDeclaration,
36
44
  PositionalArg,
37
- QuantumFunctionDeclaration,
38
- QuantumOperandDeclaration,
39
45
  )
40
46
 
41
- from classiq import StructDeclaration
47
+ from classiq import Struct, StructDeclaration
42
48
  from classiq.exceptions import ClassiqValueError
43
49
  from classiq.qmod.model_state_container import ModelStateContainer
44
- from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CParam, CReal
50
+ from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CReal
45
51
  from classiq.qmod.qmod_variable import QVar, get_type_hint_expr
46
- from classiq.qmod.quantum_callable import QCallable, QCallableList
52
+ from classiq.qmod.quantum_callable import QCallableList
47
53
  from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
48
54
 
49
- OPERAND_ARG_NAME = "arg{i}"
55
+ if sys.version_info[0:2] >= (3, 9):
56
+ from typing import Annotated
50
57
 
51
58
 
52
59
  def python_type_to_qmod(
53
60
  py_type: type, *, qmodule: ModelStateContainer
54
61
  ) -> Optional[ConcreteClassicalType]:
55
- if py_type == int or py_type is CInt:
62
+ if py_type is int or py_type is CInt:
56
63
  return Integer()
57
- elif py_type == float or py_type is CReal:
64
+ elif py_type in (float, complex) or py_type is CReal:
58
65
  return Real()
59
- elif py_type == bool or py_type is CBool:
66
+ elif py_type is bool or py_type is CBool:
60
67
  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:
68
+ elif get_origin(py_type) is list:
69
+ element_type = python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
70
+ if element_type is not None:
71
+ return ClassicalList(element_type=element_type)
72
+ elif get_origin(py_type) is CArray:
66
73
  array_args = version_portable_get_args(py_type)
67
74
  if len(array_args) == 1:
68
75
  return ClassicalList(
@@ -112,72 +119,108 @@ def _add_qmod_struct(py_type: Type, *, qmodule: ModelStateContainer) -> None:
112
119
  )
113
120
 
114
121
 
115
- def _extract_port_decl(name: str, py_type: Any) -> PortDeclaration:
122
+ def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration:
116
123
  # FIXME: CAD-13409
117
124
  qtype: Type[QVar] = QVar.from_type_hint(py_type) # type:ignore[assignment]
118
125
  direction = qtype.port_direction(py_type)
119
126
  if isinstance(py_type, _AnnotatedAlias):
120
127
  py_type = py_type.__args__[0]
121
- return PortDeclaration(
122
- name=name,
128
+ param = AnonPortDeclaration(
129
+ name=None,
123
130
  direction=direction,
124
131
  quantum_type=qtype.to_qmod_quantum_type(py_type),
125
132
  )
133
+ if name is not None:
134
+ param = param.rename(name)
135
+ return param
126
136
 
127
137
 
128
138
  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(
139
+ name: Optional[str], py_type: Any, qmodule: ModelStateContainer
140
+ ) -> AnonQuantumOperandDeclaration:
141
+ is_list = (get_origin(py_type) or py_type) is QCallableList
142
+ if get_origin(py_type) is list:
143
+ is_list = True
144
+ py_type = version_portable_get_args(py_type)
145
+ type_args = version_portable_get_args(py_type)
146
+ param_decls = [_extract_operand_param(arg_type) for arg_type in type_args]
147
+ param = AnonQuantumOperandDeclaration(
136
148
  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,
149
+ positional_arg_declarations=_extract_positional_args(
150
+ param_decls, qmodule=qmodule
151
+ ),
152
+ is_list=is_list,
153
+ )
154
+ if name is not None:
155
+ param = param.rename(name)
156
+ return param
157
+
158
+
159
+ def _extract_operand_param(py_type: Any) -> Tuple[Optional[str], Any]:
160
+ if sys.version_info[0:2] < (3, 9) or get_origin(py_type) is not Annotated:
161
+ return None, py_type
162
+ args = get_args(py_type)
163
+ if len(args) == 2:
164
+ if isinstance(args[1], PortDeclarationDirection):
165
+ return None, py_type
166
+ elif isinstance(args[1], str):
167
+ return args[1], args[0]
168
+ elif (
169
+ len(args) == 3
170
+ and isinstance(args[1], PortDeclarationDirection)
171
+ and isinstance(args[2], str)
172
+ ):
173
+ return args[2], Annotated[args[0], args[1]]
174
+ raise ClassiqValueError(
175
+ f"Operand parameter declaration must be of the form <param-type> or "
176
+ f"Annotated[<param-type>, <param-name>]. Got {py_type}"
139
177
  )
140
178
 
141
179
 
180
+ @overload
142
181
  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():
182
+ args: Sequence[Tuple[str, Any]], qmodule: ModelStateContainer
183
+ ) -> Sequence[PositionalArg]:
184
+ pass
185
+
186
+
187
+ @overload
188
+ def _extract_positional_args(
189
+ args: Sequence[Tuple[Optional[str], Any]], qmodule: ModelStateContainer
190
+ ) -> Sequence[AnonPositionalArg]:
191
+ pass
192
+
193
+
194
+ def _extract_positional_args(
195
+ args: Sequence[Tuple[Optional[str], Any]], qmodule: ModelStateContainer
196
+ ) -> Sequence[AnonPositionalArg]:
197
+ result: List[AnonPositionalArg] = []
198
+ for name, py_type in args:
147
199
  if name == "return":
148
200
  continue
149
201
  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
- )
202
+ classical_type = python_type_to_qmod(py_type, qmodule=qmodule)
203
+ if classical_type is not None:
204
+ param = AnonClassicalParameterDeclaration(
205
+ name=None,
206
+ classical_type=classical_type,
164
207
  )
208
+ if name is not None:
209
+ param = param.rename(name)
210
+ result.append(param)
165
211
  elif QVar.from_type_hint(py_type) is not None:
166
212
  result.append(_extract_port_decl(name, py_type))
167
213
  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
214
  result.append(_extract_operand_decl(name, py_type, qmodule=qmodule))
172
215
  return result
173
216
 
174
217
 
175
218
  def infer_func_decl(
176
219
  py_func: Callable, qmodule: ModelStateContainer
177
- ) -> QuantumFunctionDeclaration:
178
- return QuantumFunctionDeclaration(
220
+ ) -> NamedParamsQuantumFunctionDeclaration:
221
+ return NamedParamsQuantumFunctionDeclaration(
179
222
  name=unmangle_keyword(py_func.__name__),
180
223
  positional_arg_declarations=_extract_positional_args(
181
- py_func.__annotations__, qmodule=qmodule
224
+ list(py_func.__annotations__.items()), qmodule=qmodule
182
225
  ),
183
226
  )
@@ -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 "="