classiq 0.39.0__py3-none-any.whl → 0.40.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 (51) hide show
  1. classiq/__init__.py +1 -0
  2. classiq/applications/chemistry/chemistry_model_constructor.py +1 -1
  3. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +5 -6
  4. classiq/applications/combinatorial_helpers/optimization_model.py +7 -6
  5. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -10
  6. classiq/applications/combinatorial_optimization/__init__.py +2 -0
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
  8. classiq/interface/_version.py +1 -1
  9. classiq/interface/backend/backend_preferences.py +5 -5
  10. classiq/interface/backend/quantum_backend_providers.py +7 -7
  11. classiq/interface/executor/execution_preferences.py +4 -9
  12. classiq/interface/generator/application_apis/chemistry_declarations.py +2 -4
  13. classiq/interface/generator/application_apis/finance_declarations.py +1 -1
  14. classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -0
  15. classiq/interface/generator/expressions/qmod_qarray_proxy.py +82 -0
  16. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +21 -0
  17. classiq/interface/generator/expressions/qmod_sized_proxy.py +22 -0
  18. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +8 -6
  19. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +10 -4
  20. classiq/interface/generator/functions/builtins/open_lib_functions.py +624 -76
  21. classiq/interface/generator/functions/classical_type.py +29 -17
  22. classiq/interface/generator/model/preferences/preferences.py +4 -2
  23. classiq/interface/model/control.py +104 -8
  24. classiq/interface/model/quantum_type.py +6 -5
  25. classiq/interface/model/resolvers/function_call_resolver.py +0 -5
  26. classiq/interface/model/statement_block.py +1 -4
  27. classiq/qmod/__init__.py +6 -2
  28. classiq/qmod/builtins/classical_functions.py +30 -35
  29. classiq/qmod/builtins/functions.py +213 -153
  30. classiq/qmod/builtins/operations.py +78 -24
  31. classiq/qmod/builtins/structs.py +50 -48
  32. classiq/qmod/declaration_inferrer.py +30 -18
  33. classiq/qmod/native/expression_to_qmod.py +5 -4
  34. classiq/qmod/native/pretty_printer.py +7 -14
  35. classiq/qmod/qmod_constant.py +7 -7
  36. classiq/qmod/qmod_parameter.py +54 -33
  37. classiq/qmod/qmod_struct.py +2 -2
  38. classiq/qmod/qmod_variable.py +40 -29
  39. classiq/qmod/quantum_callable.py +7 -4
  40. classiq/qmod/quantum_expandable.py +19 -13
  41. classiq/qmod/quantum_function.py +25 -2
  42. classiq/qmod/symbolic.py +78 -68
  43. classiq/qmod/symbolic_expr.py +1 -1
  44. classiq/qmod/symbolic_type.py +1 -4
  45. classiq/qmod/utilities.py +29 -0
  46. {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/METADATA +1 -1
  47. {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/RECORD +48 -50
  48. classiq/interface/executor/error_mitigation.py +0 -6
  49. classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
  50. classiq/interface/model/quantum_if_operation.py +0 -94
  51. {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,8 @@
1
1
  import inspect
2
+ import sys
3
+ import warnings
2
4
  from types import FrameType
3
- from typing import Any, Callable, Final, List, Mapping, Union
5
+ from typing import Any, Callable, Final, List, Mapping, Union, overload
4
6
 
5
7
  from classiq.interface.generator.expressions.expression import Expression
6
8
  from classiq.interface.generator.functions.builtins.internal_operators import (
@@ -19,7 +21,6 @@ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
19
21
  from classiq.interface.model.quantum_function_declaration import (
20
22
  QuantumOperandDeclaration,
21
23
  )
22
- from classiq.interface.model.quantum_if_operation import QuantumIf
23
24
  from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
24
25
  from classiq.interface.model.repeat import Repeat
25
26
  from classiq.interface.model.statement_block import StatementBlock
@@ -30,6 +31,7 @@ from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QVar
30
31
  from classiq.qmod.quantum_callable import QCallable
31
32
  from classiq.qmod.quantum_expandable import prepare_arg
32
33
  from classiq.qmod.symbolic_expr import SymbolicExpr
34
+ from classiq.qmod.utilities import get_source_ref
33
35
 
34
36
  _MISSING_VALUE: Final[int] = -1
35
37
 
@@ -39,6 +41,7 @@ def bind(
39
41
  destination: Union[Output[QVar], List[Output[QVar]]],
40
42
  ) -> None:
41
43
  assert QCallable.CURRENT_EXPANDABLE is not None
44
+ source_ref = get_source_ref(sys._getframe(1))
42
45
  if not isinstance(source, list):
43
46
  source = [source]
44
47
  if not isinstance(destination, list):
@@ -47,19 +50,7 @@ def bind(
47
50
  BindOperation(
48
51
  in_handles=[src_var.get_handle_binding() for src_var in source],
49
52
  out_handles=[dst_var.get_handle_binding() for dst_var in destination],
50
- )
51
- )
52
-
53
-
54
- def control(
55
- operand: Union[QCallable, Callable[[], None]], ctrl: Union[QBit, QArray[QBit]]
56
- ) -> None:
57
- _validate_operand(operand)
58
- assert QCallable.CURRENT_EXPANDABLE is not None
59
- QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
60
- Control(
61
- control=ctrl.get_handle_binding(),
62
- body=_operand_to_body(operand),
53
+ source_ref=source_ref,
63
54
  )
64
55
  )
65
56
 
@@ -73,38 +64,90 @@ def if_(
73
64
  if else_ != _MISSING_VALUE:
74
65
  _validate_operand(else_)
75
66
  assert QCallable.CURRENT_EXPANDABLE is not None
67
+ source_ref = get_source_ref(sys._getframe(1))
76
68
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
77
69
  ClassicalIf(
78
70
  condition=Expression(expr=str(condition)),
79
71
  then=_operand_to_body(then),
80
72
  else_=_operand_to_body(else_) if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
73
+ source_ref=source_ref,
81
74
  )
82
75
  )
83
76
 
84
77
 
85
- def quantum_if(
86
- condition: SymbolicExpr, then: Union[QCallable, Callable[[], None]]
78
+ @overload
79
+ def control(
80
+ ctrl: Union[QBit, QArray[QBit]], operand: Union[QCallable, Callable[[], None]]
87
81
  ) -> None:
88
- _validate_operand(then)
82
+ pass
83
+
84
+
85
+ @overload
86
+ def control(ctrl: SymbolicExpr, operand: Union[QCallable, Callable[[], None]]) -> None:
87
+ pass
88
+
89
+
90
+ def control(
91
+ ctrl: Union[SymbolicExpr, QBit, QArray[QBit]],
92
+ operand: Union[QCallable, Callable[[], None]],
93
+ ) -> None:
94
+ if isinstance(operand, (SymbolicExpr, QVar)) and isinstance(
95
+ control, (QCallable, Callable)
96
+ ): # type:ignore[unreachable]
97
+ warnings.warn( # type:ignore[unreachable]
98
+ "The `control` syntax has changed. Switch the `ctrl` and "
99
+ "`operand` arguments. The old syntax will not be supported in the future.",
100
+ category=DeprecationWarning,
101
+ stacklevel=2,
102
+ )
103
+ ctrl, operand = operand, ctrl
104
+ if isinstance(ctrl, QNum):
105
+ warnings.warn(
106
+ "The `control` semantics has changed. Applying `control` to "
107
+ "a `QNum` without comparing it to an integer will not be supported in the "
108
+ "future.\nTips:\n 1. Use a `bind` statement to cast `ctrl` into a "
109
+ "QArray.\n 2.`control(n, ...)` is equivalent to "
110
+ "`ctrl(n == 2 ** n.size - 1, ...)` if n>=0 or to `ctrl(n == -1, ...)` if "
111
+ "n<0.",
112
+ category=DeprecationWarning,
113
+ stacklevel=2,
114
+ )
115
+ _validate_operand(operand)
89
116
  assert QCallable.CURRENT_EXPANDABLE is not None
117
+ source_ref = get_source_ref(sys._getframe(1))
90
118
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
91
- QuantumIf(
92
- expression=Expression(expr=str(condition)),
93
- then=_operand_to_body(then),
119
+ Control(
120
+ expression=Expression(expr=str(ctrl)),
121
+ body=_operand_to_body(operand),
122
+ source_ref=source_ref,
94
123
  )
95
124
  )
96
125
 
97
126
 
127
+ def quantum_if(
128
+ ctrl: SymbolicExpr, operand: Union[QCallable, Callable[[], None]]
129
+ ) -> None:
130
+ warnings.warn(
131
+ "`quantum_if` is no longer supported, use `control` instead (with the "
132
+ "same arguments). `quantum_if` will be removed in a future release.",
133
+ category=DeprecationWarning,
134
+ stacklevel=2,
135
+ )
136
+ control(ctrl, operand)
137
+
138
+
98
139
  def inplace_add(
99
140
  value: QNum,
100
141
  target: QNum,
101
142
  ) -> None:
102
143
  assert QCallable.CURRENT_EXPANDABLE is not None
144
+ source_ref = get_source_ref(sys._getframe(1))
103
145
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
104
146
  InplaceBinaryOperation(
105
147
  target=target.get_handle_binding(),
106
148
  value=value.get_handle_binding(),
107
149
  operation=BinaryOperation.Addition,
150
+ source_ref=source_ref,
108
151
  )
109
152
  )
110
153
 
@@ -114,11 +157,13 @@ def inplace_xor(
114
157
  target: QNum,
115
158
  ) -> None:
116
159
  assert QCallable.CURRENT_EXPANDABLE is not None
160
+ source_ref = get_source_ref(sys._getframe(1))
117
161
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
118
162
  InplaceBinaryOperation(
119
163
  target=target.get_handle_binding(),
120
164
  value=value.get_handle_binding(),
121
165
  operation=BinaryOperation.Xor,
166
+ source_ref=source_ref,
122
167
  )
123
168
  )
124
169
 
@@ -130,10 +175,12 @@ def within_apply(
130
175
  _validate_operand(compute)
131
176
  _validate_operand(action)
132
177
  assert QCallable.CURRENT_EXPANDABLE is not None
178
+ source_ref = get_source_ref(sys._getframe(1))
133
179
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
134
180
  WithinApply(
135
181
  compute=_operand_to_body(compute),
136
182
  action=_operand_to_body(action),
183
+ source_ref=source_ref,
137
184
  )
138
185
  )
139
186
 
@@ -141,6 +188,7 @@ def within_apply(
141
188
  def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) -> None:
142
189
  _validate_operand(iteration)
143
190
  assert QCallable.CURRENT_EXPANDABLE is not None
191
+ source_ref = get_source_ref(sys._getframe(1))
144
192
  iteration_operand = prepare_arg(
145
193
  REPEAT_OPERATOR.operand_declarations["iteration"], iteration
146
194
  )
@@ -149,6 +197,7 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
149
197
  iter_var=inspect.getfullargspec(iteration).args[0],
150
198
  count=Expression(expr=str(count)),
151
199
  body=iteration_operand.body,
200
+ source_ref=source_ref,
152
201
  )
153
202
  )
154
203
 
@@ -159,8 +208,13 @@ def power(
159
208
  ) -> None:
160
209
  _validate_operand(operand)
161
210
  assert QCallable.CURRENT_EXPANDABLE is not None
211
+ source_ref = get_source_ref(sys._getframe(1))
162
212
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
163
- Power(power=Expression(expr=str(power)), body=_operand_to_body(operand))
213
+ Power(
214
+ power=Expression(expr=str(power)),
215
+ body=_operand_to_body(operand),
216
+ source_ref=source_ref,
217
+ )
164
218
  )
165
219
 
166
220
 
@@ -169,8 +223,9 @@ def invert(
169
223
  ) -> None:
170
224
  _validate_operand(operand)
171
225
  assert QCallable.CURRENT_EXPANDABLE is not None
226
+ source_ref = get_source_ref(sys._getframe(1))
172
227
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
173
- Invert(body=_operand_to_body(operand))
228
+ Invert(body=_operand_to_body(operand), source_ref=source_ref)
174
229
  )
175
230
 
176
231
 
@@ -240,7 +295,6 @@ __all__ = [
240
295
  "control",
241
296
  "invert",
242
297
  "if_",
243
- "quantum_if",
244
298
  "inplace_add",
245
299
  "inplace_xor",
246
300
  "power",
@@ -1,113 +1,115 @@
1
1
  # This file was generated automatically - do not edit manually
2
2
 
3
- from typing import List
3
+ from classiq.interface.generator.expressions.enums.ladder_operator import LadderOperator
4
+ from classiq.interface.generator.expressions.enums.pauli import Pauli
4
5
 
6
+ from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CReal
5
7
  from classiq.qmod.qmod_struct import struct
6
8
 
7
9
 
8
10
  @struct
9
11
  class PauliTerm:
10
- pauli: List[int]
11
- coefficient: float
12
+ pauli: CArray[Pauli]
13
+ coefficient: CReal
12
14
 
13
15
 
14
16
  @struct
15
17
  class MoleculeProblem:
16
- mapping: int
17
- z2_symmetries: bool
18
+ mapping: CInt
19
+ z2_symmetries: CBool
18
20
  molecule: "Molecule"
19
- freeze_core: bool
20
- remove_orbitals: List[int]
21
+ freeze_core: CBool
22
+ remove_orbitals: CArray[CInt]
21
23
 
22
24
 
23
25
  @struct
24
26
  class Molecule:
25
- atoms: List["ChemistryAtom"]
26
- spin: int
27
- charge: int
27
+ atoms: CArray["ChemistryAtom"]
28
+ spin: CInt
29
+ charge: CInt
28
30
 
29
31
 
30
32
  @struct
31
33
  class ChemistryAtom:
32
- element: int
34
+ element: CInt
33
35
  position: "Position"
34
36
 
35
37
 
36
38
  @struct
37
39
  class Position:
38
- x: float
39
- y: float
40
- z: float
40
+ x: CReal
41
+ y: CReal
42
+ z: CReal
41
43
 
42
44
 
43
45
  @struct
44
46
  class FockHamiltonianProblem:
45
- mapping: int
46
- z2_symmetries: bool
47
- terms: List["LadderTerm"]
48
- num_particles: List[int]
47
+ mapping: CInt
48
+ z2_symmetries: CBool
49
+ terms: CArray["LadderTerm"]
50
+ num_particles: CArray[CInt]
49
51
 
50
52
 
51
53
  @struct
52
54
  class LadderTerm:
53
- coefficient: float
54
- ops: List["LadderOp"]
55
+ coefficient: CReal
56
+ ops: CArray["LadderOp"]
55
57
 
56
58
 
57
59
  @struct
58
60
  class LadderOp:
59
- op: int
60
- index: int
61
+ op: LadderOperator
62
+ index: CInt
61
63
 
62
64
 
63
65
  @struct
64
66
  class CombinatorialOptimizationSolution:
65
- probability: float
66
- cost: float
67
- solution: List[int]
68
- count: int
67
+ probability: CReal
68
+ cost: CReal
69
+ solution: CArray[CInt]
70
+ count: CInt
69
71
 
70
72
 
71
73
  @struct
72
74
  class GaussianModel:
73
- num_qubits: int
74
- normal_max_value: float
75
- default_probabilities: List[float]
76
- rhos: List[float]
77
- loss: List[int]
78
- min_loss: int
75
+ num_qubits: CInt
76
+ normal_max_value: CReal
77
+ default_probabilities: CArray[CReal]
78
+ rhos: CArray[CReal]
79
+ loss: CArray[CInt]
80
+ min_loss: CInt
79
81
 
80
82
 
81
83
  @struct
82
84
  class LogNormalModel:
83
- num_qubits: int
84
- mu: float
85
- sigma: float
85
+ num_qubits: CInt
86
+ mu: CReal
87
+ sigma: CReal
86
88
 
87
89
 
88
90
  @struct
89
91
  class FinanceFunction:
90
- f: int
91
- threshold: float
92
- larger: bool
93
- polynomial_degree: int
94
- use_chebyshev_polynomial_approximation: bool
95
- tail_probability: float
92
+ f: CInt
93
+ threshold: CReal
94
+ larger: CBool
95
+ polynomial_degree: CInt
96
+ use_chebyshev_polynomial_approximation: CBool
97
+ tail_probability: CReal
96
98
 
97
99
 
98
100
  @struct
99
101
  class QsvmResult:
100
- test_score: float
101
- predicted_labels: List[float]
102
+ test_score: CReal
103
+ predicted_labels: CArray[CReal]
102
104
 
103
105
 
104
106
  @struct
105
107
  class QSVMFeatureMapPauli:
106
- feature_dimension: int
107
- reps: int
108
- entanglement: int
109
- alpha: float
110
- paulis: List[List[int]]
108
+ feature_dimension: CInt
109
+ reps: CInt
110
+ entanglement: CInt
111
+ alpha: CReal
112
+ paulis: CArray[CArray[Pauli]]
111
113
 
112
114
 
113
115
  __all__ = [
@@ -9,8 +9,8 @@ from classiq.interface.generator.functions.classical_type import (
9
9
  ClassicalArray,
10
10
  ClassicalList,
11
11
  ConcreteClassicalType,
12
+ CStructBase,
12
13
  Integer,
13
- QStructBase,
14
14
  Real,
15
15
  Struct,
16
16
  )
@@ -27,7 +27,7 @@ from classiq.interface.model.quantum_function_declaration import (
27
27
  from classiq import StructDeclaration
28
28
  from classiq.exceptions import ClassiqValueError
29
29
  from classiq.qmod.model_state_container import ModelStateContainer
30
- from classiq.qmod.qmod_parameter import Array, QParam
30
+ from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CParam, CReal, QParam
31
31
  from classiq.qmod.qmod_variable import QVar, get_type_hint_expr
32
32
  from classiq.qmod.quantum_callable import QCallable, QCallableList
33
33
  from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
@@ -38,34 +38,39 @@ OPERAND_ARG_NAME = "arg{i}"
38
38
  def python_type_to_qmod(
39
39
  py_type: type, *, qmodule: ModelStateContainer
40
40
  ) -> Optional[ConcreteClassicalType]:
41
- if py_type == int:
41
+ if py_type == int or py_type is CInt:
42
42
  return Integer()
43
- elif py_type == float:
43
+ elif py_type == float or py_type is CReal:
44
44
  return Real()
45
- elif py_type == bool:
45
+ elif py_type == bool or py_type is CBool:
46
46
  return Bool()
47
47
  elif get_origin(py_type) == list:
48
48
  return ClassicalList(
49
49
  element_type=python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
50
50
  )
51
- elif get_origin(py_type) == Array:
51
+ elif get_origin(py_type) == CArray:
52
52
  array_args = version_portable_get_args(py_type)
53
- if len(array_args) != 2:
54
- raise ClassiqValueError(
55
- "Array accepts two generic parameters in the form 'Array[<element-type>, <size>]'"
53
+ if len(array_args) == 1:
54
+ return ClassicalList(
55
+ element_type=python_type_to_qmod(array_args[0], qmodule=qmodule)
56
56
  )
57
- return ClassicalArray(
58
- element_type=python_type_to_qmod(array_args[0], qmodule=qmodule),
59
- size=get_type_hint_expr(array_args[1]),
57
+ elif len(array_args) == 2:
58
+ return ClassicalArray(
59
+ element_type=python_type_to_qmod(array_args[0], qmodule=qmodule),
60
+ size=get_type_hint_expr(array_args[1]),
61
+ )
62
+ raise ClassiqValueError(
63
+ "CArray accepts one or two generic parameters in the form "
64
+ "`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
60
65
  )
61
- elif inspect.isclass(py_type) and issubclass(py_type, QStructBase):
66
+ elif inspect.isclass(py_type) and issubclass(py_type, CStructBase):
62
67
  _add_qmod_struct(py_type, qmodule=qmodule)
63
68
  return Struct(name=py_type.__name__)
64
69
  return None
65
70
 
66
71
 
67
72
  def _add_qmod_struct(
68
- py_type: Type[QStructBase], *, qmodule: ModelStateContainer
73
+ py_type: Type[CStructBase], *, qmodule: ModelStateContainer
69
74
  ) -> None:
70
75
  if (
71
76
  py_type.__name__ in StructDeclaration.BUILTIN_STRUCT_DECLARATIONS
@@ -85,9 +90,10 @@ def _add_qmod_struct(
85
90
  def _extract_param_decl(
86
91
  name: str, py_type: Any, *, qmodule: ModelStateContainer
87
92
  ) -> ClassicalParameterDeclaration:
88
- if len(get_args(py_type)) != 1:
89
- raise ClassiqValueError("QParam takes exactly one generic argument")
90
- py_type = get_args(py_type)[0]
93
+ if get_origin(py_type) is QParam:
94
+ if len(get_args(py_type)) != 1:
95
+ raise ClassiqValueError("QParam takes exactly one generic argument")
96
+ py_type = get_args(py_type)[0]
91
97
  return ClassicalParameterDeclaration(
92
98
  name=name, classical_type=python_type_to_qmod(py_type, qmodule=qmodule)
93
99
  )
@@ -128,7 +134,13 @@ def _extract_positional_args(
128
134
  if name == "return":
129
135
  continue
130
136
  name = unmangle_keyword(name)
131
- if get_origin(py_type) is QParam:
137
+ if (
138
+ inspect.isclass(py_type)
139
+ and issubclass(py_type, CParam)
140
+ or inspect.isclass(py_type)
141
+ and issubclass(py_type, CStructBase)
142
+ or get_origin(py_type) in (QParam, CArray)
143
+ ):
132
144
  result.append(_extract_param_decl(name, py_type, qmodule=qmodule))
133
145
  elif QVar.from_type_hint(py_type) is not None:
134
146
  result.append(_extract_port_decl(name, py_type))
@@ -5,6 +5,8 @@ from typing import Callable, Dict, List, Mapping, Type
5
5
 
6
6
  import numpy as np
7
7
 
8
+ from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
9
+
8
10
  from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
9
11
 
10
12
  IDENTIFIER = re.compile(r"[a-zA-Z_]\w*")
@@ -57,11 +59,10 @@ class ASTToQMODCode:
57
59
  return self.indent.join(self.ast_to_code(child) for child in node.body)
58
60
  elif isinstance(node, ast.Attribute):
59
61
  # Enum attribute access
60
- if not isinstance(node.value, ast.Name) or not isinstance(node.attr, str):
61
- raise AssertionError("Error parsing enum attribute access")
62
- if not (IDENTIFIER.match(node.value.id) and IDENTIFIER.match(node.attr)):
62
+ if not isinstance(node.attr, str):
63
63
  raise AssertionError("Error parsing enum attribute access")
64
- return f"{node.value.id!s}::{node.attr!s}"
64
+ access_operator = "." if node.attr in CLASSICAL_ATTRIBUTES else "::"
65
+ return f"{self.ast_to_code(node.value)!s}{access_operator}{node.attr!s}"
65
66
  elif isinstance(node, ast.Name):
66
67
  return node.id
67
68
  elif isinstance(node, ast.Num):
@@ -41,7 +41,6 @@ from classiq.interface.model.quantum_function_declaration import (
41
41
  QuantumFunctionDeclaration,
42
42
  QuantumOperandDeclaration,
43
43
  )
44
- from classiq.interface.model.quantum_if_operation import QuantumIf
45
44
  from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
46
45
  from classiq.interface.model.quantum_type import (
47
46
  QuantumBit,
@@ -213,17 +212,11 @@ class DSLPrettyPrinter(Visitor):
213
212
  )
214
213
  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"
215
214
 
216
- def visit_Control(self, control: Control) -> str:
217
- control_code = f"{self._indent}control ({self.visit(control.control)}) {{\n"
218
- control_code += self._visit_body(control.body)
219
- control_code += f"{self._indent}}}\n"
220
- return control_code
221
-
222
- def visit_QuantumIf(self, op: QuantumIf) -> str:
223
- quantum_if = f"{self._indent}quantum_if ({self.visit(op.expression)}) {{\n"
224
- quantum_if += self._visit_body(op.then)
225
- quantum_if += f"{self._indent}}}\n"
226
- return quantum_if
215
+ def visit_Control(self, op: Control) -> str:
216
+ control = f"{self._indent}control ({self.visit(op.expression)}) {{\n"
217
+ control += self._visit_body(op.body)
218
+ control += f"{self._indent}}}\n"
219
+ return control
227
220
 
228
221
  def visit_ClassicalIf(self, op: ClassicalIf) -> str:
229
222
  classical_if = f"{self._indent}if ({self.visit(op.condition)}) {{\n"
@@ -309,10 +302,10 @@ class DSLPrettyPrinter(Visitor):
309
302
  return var_ref.name
310
303
 
311
304
  def visit_SlicedHandleBinding(self, var_ref: SlicedHandleBinding) -> str:
312
- return str(var_ref)
305
+ return f"{var_ref.name}[{self.visit(var_ref.start)}:{self.visit(var_ref.end)}]"
313
306
 
314
307
  def visit_SubscriptHandleBinding(self, var_ref: SubscriptHandleBinding) -> str:
315
- return str(var_ref)
308
+ return f"{var_ref.name}[{self.visit(var_ref.index)}]"
316
309
 
317
310
  def visit_ArithmeticOperation(self, arith_op: ArithmeticOperation) -> str:
318
311
  op = "^=" if arith_op.inplace_result else "="
@@ -6,13 +6,13 @@ from classiq.interface.generator.expressions.expression import Expression
6
6
  from classiq.interface.generator.functions.classical_type import (
7
7
  ClassicalArray,
8
8
  ClassicalList,
9
- QStructBase,
9
+ CStructBase,
10
10
  )
11
11
 
12
12
  from classiq.exceptions import ClassiqError
13
13
  from classiq.qmod.declaration_inferrer import python_type_to_qmod
14
14
  from classiq.qmod.model_state_container import ModelStateContainer
15
- from classiq.qmod.qmod_parameter import QParam, QParamList, QParamStruct
15
+ from classiq.qmod.qmod_parameter import CParam, CParamList, CParamStruct
16
16
 
17
17
 
18
18
  class QConstant:
@@ -61,22 +61,22 @@ class QConstant:
61
61
  value=Expression(expr=expr),
62
62
  )
63
63
 
64
- def __getattr__(self, name: str) -> QParam:
64
+ def __getattr__(self, name: str) -> CParam:
65
65
  self.add_to_model()
66
66
 
67
67
  py_type = type(self._value)
68
68
  if (
69
69
  QConstant.CURRENT_QMODULE is None
70
70
  or not inspect.isclass(py_type)
71
- or not issubclass(py_type, QStructBase)
71
+ or not issubclass(py_type, CStructBase)
72
72
  ):
73
73
  return self.__getattribute__(name)
74
74
 
75
- return QParamStruct.get_field(
75
+ return CParamStruct.get_field(
76
76
  QConstant.CURRENT_QMODULE, self.name, py_type.__name__, name
77
77
  )
78
78
 
79
- def __getitem__(self, item: Any) -> QParam:
79
+ def __getitem__(self, item: Any) -> CParam:
80
80
  self.add_to_model()
81
81
 
82
82
  assert QConstant.CURRENT_QMODULE is not None
@@ -90,7 +90,7 @@ class QConstant:
90
90
  if not isinstance(qmod_type, (ClassicalList, ClassicalArray)):
91
91
  raise ClassiqError("Invalid subscript to non-list constant")
92
92
 
93
- return QParamList(
93
+ return CParamList(
94
94
  self.name,
95
95
  qmod_type,
96
96
  QConstant.CURRENT_QMODULE,