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
@@ -26,21 +26,54 @@ _T = TypeVar("_T")
26
26
 
27
27
 
28
28
  if TYPE_CHECKING:
29
+ SymbolicSuperclass = SymbolicExpr
30
+ else:
31
+ SymbolicSuperclass = Symbolic
29
32
 
30
- class QParam(SymbolicExpr, Generic[_T]):
31
- pass
32
33
 
33
- else:
34
+ class CParam(SymbolicSuperclass):
35
+ pass
36
+
37
+
38
+ class QParam(CParam, Generic[_T]):
39
+ pass
40
+
41
+
42
+ class CInt(CParam):
43
+ pass
44
+
45
+
46
+ class CReal(CParam):
47
+ pass
48
+
49
+
50
+ class CBool(CParam):
51
+ pass
52
+
53
+
54
+ _P = ParamSpec("_P")
55
+
56
+
57
+ class ArrayBase(Generic[_P]):
58
+ # Support comma-separated generic args in older Python versions
59
+ if sys.version_info[0:2] < (3, 10):
60
+
61
+ def __class_getitem__(cls, args) -> _GenericAlias:
62
+ return _GenericAlias(cls, args)
63
+
64
+
65
+ class CArray(CParam, ArrayBase[_P]):
66
+ if TYPE_CHECKING:
34
67
 
35
- class QParam(Symbolic, Generic[_T]):
36
- pass
68
+ @property
69
+ def len(self) -> int: ...
37
70
 
38
71
 
39
- class QParamScalar(QParam, SymbolicExpr):
72
+ class CParamScalar(CParam, SymbolicExpr):
40
73
  pass
41
74
 
42
75
 
43
- class QParamList(QParam):
76
+ class CParamList(CParam):
44
77
  def __init__(
45
78
  self,
46
79
  expr: str,
@@ -51,7 +84,7 @@ class QParamList(QParam):
51
84
  self._qmodule = qmodule
52
85
  self._list_type = list_type
53
86
 
54
- def __getitem__(self, key: Any) -> QParam:
87
+ def __getitem__(self, key: Any) -> CParam:
55
88
  return create_param(
56
89
  f"({self})[{key}]",
57
90
  self._list_type.element_type,
@@ -64,11 +97,11 @@ class QParamList(QParam):
64
97
  )
65
98
 
66
99
  @property
67
- def len(self) -> QParamScalar:
68
- return QParamScalar(f"len({self})")
100
+ def len(self) -> CParamScalar:
101
+ return CParamScalar(f"get_field({self}, 'len')")
69
102
 
70
103
 
71
- class QParamStruct(QParam):
104
+ class CParamStruct(CParam):
72
105
  def __init__(
73
106
  self, expr: str, struct_type: Struct, *, qmodule: ModelStateContainer
74
107
  ) -> None:
@@ -76,8 +109,8 @@ class QParamStruct(QParam):
76
109
  self._qmodule = qmodule
77
110
  self._struct_type = struct_type
78
111
 
79
- def __getattr__(self, field_name: str) -> QParam:
80
- return QParamStruct.get_field(
112
+ def __getattr__(self, field_name: str) -> CParam:
113
+ return CParamStruct.get_field(
81
114
  self._qmodule, str(self), self._struct_type.name, field_name
82
115
  )
83
116
 
@@ -87,7 +120,7 @@ class QParamStruct(QParam):
87
120
  variable_name: str,
88
121
  struct_name: str,
89
122
  field_name: str,
90
- ) -> QParam:
123
+ ) -> CParam:
91
124
  struct_decl = StructDeclaration.BUILTIN_STRUCT_DECLARATIONS.get(
92
125
  struct_name, qmodule.type_decls.get(struct_name)
93
126
  )
@@ -105,27 +138,15 @@ class QParamStruct(QParam):
105
138
  )
106
139
 
107
140
 
108
- _P = ParamSpec("_P")
109
-
110
-
111
- class ArrayBase(Generic[_P]):
112
- # Support comma-separated generic args in older Python versions
113
- if sys.version_info[0:2] < (3, 10):
114
-
115
- def __class_getitem__(cls, args) -> _GenericAlias:
116
- return _GenericAlias(cls, args)
117
-
118
-
119
- class Array(ArrayBase[_P]):
120
- pass
121
-
122
-
123
141
  def create_param(
124
142
  expr_str: str, ctype: ClassicalType, qmodule: ModelStateContainer
125
- ) -> QParam:
143
+ ) -> CParam:
126
144
  if isinstance(ctype, (ClassicalList, ClassicalArray)):
127
- return QParamList(expr_str, ctype, qmodule=qmodule)
145
+ return CParamList(expr_str, ctype, qmodule=qmodule)
128
146
  elif isinstance(ctype, Struct):
129
- return QParamStruct(expr_str, ctype, qmodule=qmodule)
147
+ return CParamStruct(expr_str, ctype, qmodule=qmodule)
130
148
  else:
131
- return QParamScalar(expr_str)
149
+ return CParamScalar(expr_str)
150
+
151
+
152
+ Array = CArray
@@ -3,7 +3,7 @@ from typing import Any, Type
3
3
 
4
4
  from typing_extensions import dataclass_transform
5
5
 
6
- from classiq.interface.generator.functions.classical_type import QStructBase
6
+ from classiq.interface.generator.functions.classical_type import CStructBase
7
7
 
8
8
 
9
9
  def _qmod_val_to_expr_str(val: Any) -> str:
@@ -30,7 +30,7 @@ def struct(user_class: Type) -> Type:
30
30
 
31
31
  user_dataclass = type(
32
32
  user_class.__name__,
33
- (QStructBase, dataclasses.dataclass(user_class)),
33
+ (CStructBase, dataclasses.dataclass(user_class)),
34
34
  dict(),
35
35
  )
36
36
  user_dataclass.__repr__ = _new_repr # type:ignore[assignment]
@@ -21,6 +21,7 @@ from typing import ( # type: ignore[attr-defined]
21
21
 
22
22
  from typing_extensions import Annotated, ParamSpec, Self, _AnnotatedAlias
23
23
 
24
+ from classiq.interface.ast_node import SourceReference
24
25
  from classiq.interface.generator.expressions.expression import Expression
25
26
  from classiq.interface.generator.functions.port_declaration import (
26
27
  PortDeclarationDirection,
@@ -45,11 +46,11 @@ from classiq.interface.model.quantum_type import (
45
46
  )
46
47
 
47
48
  from classiq.exceptions import ClassiqValueError
48
- from classiq.qmod.qmod_parameter import ArrayBase, QParam, QParamScalar
49
+ from classiq.qmod.qmod_parameter import ArrayBase, CBool, CInt, CParam, CParamScalar
49
50
  from classiq.qmod.quantum_callable import QCallable
50
51
  from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
51
52
  from classiq.qmod.symbolic_type import SymbolicTypes
52
- from classiq.qmod.utilities import version_portable_get_args
53
+ from classiq.qmod.utilities import get_source_ref, version_portable_get_args
53
54
 
54
55
  ILLEGAL_SLICING_STEP_MSG = "Slicing with a step of a quantum variable is not supported"
55
56
  SLICE_OUT_OF_BOUNDS_MSG = "Slice end index out of bounds"
@@ -82,8 +83,9 @@ def _no_current_expandable() -> Iterator[None]:
82
83
  QCallable.CURRENT_EXPANDABLE = current_expandable
83
84
 
84
85
 
85
- class QVar:
86
+ class QVar(Symbolic):
86
87
  def __init__(self, name: str) -> None:
88
+ super().__init__(name)
87
89
  self._name = name
88
90
  if QCallable.CURRENT_EXPANDABLE is not None:
89
91
  QCallable.CURRENT_EXPANDABLE.add_local_handle(
@@ -120,6 +122,9 @@ class QVar:
120
122
  assert type_hint == cls or get_origin(type_hint) == cls
121
123
  return PortDeclarationDirection.Inout
122
124
 
125
+ def __str__(self) -> str:
126
+ return str(self.get_handle_binding())
127
+
123
128
 
124
129
  _Q = TypeVar("_Q", bound=QVar)
125
130
  Output = Annotated[_Q, PortDeclarationDirection.Output]
@@ -131,7 +136,9 @@ class QScalar(QVar, SymbolicExpr):
131
136
  QVar.__init__(self, name)
132
137
  SymbolicExpr.__init__(self, name)
133
138
 
134
- def _insert_arith_operation(self, expr: SymbolicTypes, inplace: bool) -> None:
139
+ def _insert_arith_operation(
140
+ self, expr: SymbolicTypes, inplace: bool, source_ref: SourceReference
141
+ ) -> None:
135
142
  # Fixme: Arithmetic operations are not yet supported on slices (see CAD-12670)
136
143
  if TYPE_CHECKING:
137
144
  assert QCallable.CURRENT_EXPANDABLE is not None
@@ -140,16 +147,20 @@ class QScalar(QVar, SymbolicExpr):
140
147
  expression=Expression(expr=str(expr)),
141
148
  result_var=self.get_handle_binding(),
142
149
  inplace_result=inplace,
150
+ source_ref=source_ref,
143
151
  )
144
152
  )
145
153
 
146
- def _insert_amplitude_loading(self, expr: SymbolicTypes) -> None:
154
+ def _insert_amplitude_loading(
155
+ self, expr: SymbolicTypes, source_ref: SourceReference
156
+ ) -> None:
147
157
  if TYPE_CHECKING:
148
158
  assert QCallable.CURRENT_EXPANDABLE is not None
149
159
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
150
160
  AmplitudeLoadingOperation(
151
161
  expression=Expression(expr=str(expr)),
152
162
  result_var=self.get_handle_binding(),
163
+ source_ref=source_ref,
153
164
  )
154
165
  )
155
166
 
@@ -162,7 +173,7 @@ class QScalar(QVar, SymbolicExpr):
162
173
  f"Invalid argument {other!r} for out-of-place arithmetic operation"
163
174
  )
164
175
 
165
- self._insert_arith_operation(other, False)
176
+ self._insert_arith_operation(other, False, get_source_ref(sys._getframe(1)))
166
177
  return self
167
178
 
168
179
  def __ixor__(self, other: Any) -> Self:
@@ -171,7 +182,7 @@ class QScalar(QVar, SymbolicExpr):
171
182
  f"Invalid argument {other!r} for in-place arithmetic operation"
172
183
  )
173
184
 
174
- self._insert_arith_operation(other, True)
185
+ self._insert_arith_operation(other, True, get_source_ref(sys._getframe(1)))
175
186
  return self
176
187
 
177
188
  def __imul__(self, other: Any) -> Self:
@@ -180,7 +191,7 @@ class QScalar(QVar, SymbolicExpr):
180
191
  f"Invalid argument {other!r} for out of ampltiude encoding operation"
181
192
  )
182
193
 
183
- self._insert_amplitude_loading(other)
194
+ self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
184
195
  return self
185
196
 
186
197
 
@@ -207,18 +218,18 @@ class QNum(Generic[_P], QScalar):
207
218
  def __init__(
208
219
  self,
209
220
  name: str,
210
- size: Union[int, QParam[int]],
211
- is_signed: Union[bool, QParam[bool]],
212
- fraction_digits: Union[int, QParam[int]],
221
+ size: Union[int, CInt],
222
+ is_signed: Union[bool, CBool],
223
+ fraction_digits: Union[int, CInt],
213
224
  ):
214
225
  pass
215
226
 
216
227
  def __init__(
217
228
  self,
218
229
  name: str,
219
- size: Union[int, QParam[int], None] = None,
220
- is_signed: Union[bool, QParam[bool], None] = None,
221
- fraction_digits: Union[int, QParam[int], None] = None,
230
+ size: Union[int, CInt, None] = None,
231
+ is_signed: Union[bool, CBool, None] = None,
232
+ fraction_digits: Union[int, CInt, None] = None,
222
233
  ):
223
234
  if (
224
235
  size is None
@@ -244,8 +255,8 @@ class QNum(Generic[_P], QScalar):
244
255
  type_args = type_args[0]
245
256
  if len(type_args) != 3:
246
257
  raise ClassiqValueError(
247
- "QNum receives three type arguments: QNum[size: int | QParam[int], "
248
- "is_signed: bool | QParam[bool], fraction_digits: int | QParam[int]]"
258
+ "QNum receives three type arguments: QNum[size: int | CInt, "
259
+ "is_signed: bool | CBool, fraction_digits: int | CInt]"
249
260
  )
250
261
  return cls.QMOD_TYPE(
251
262
  size=Expression(expr=get_type_hint_expr(type_args[0])),
@@ -261,16 +272,16 @@ class QNum(Generic[_P], QScalar):
261
272
  )
262
273
 
263
274
  @property
264
- def size(self) -> QParamScalar:
265
- return QParamScalar(f"len({self._name})")
275
+ def size(self) -> CParamScalar:
276
+ return CParamScalar(f"get_field({self._name}, 'size')")
266
277
 
267
278
  @property
268
- def fraction_digits(self) -> QParamScalar:
269
- return QParamScalar(f"fraction_digits({self._name})")
279
+ def fraction_digits(self) -> CParamScalar:
280
+ return CParamScalar(f"get_field({self._name}, 'fraction_digits')")
270
281
 
271
282
  @property
272
- def is_signed(self) -> QParamScalar:
273
- return QParamScalar(f"is_signed({self._name})")
283
+ def is_signed(self) -> CParamScalar:
284
+ return CParamScalar(f"get_field({self._name}, 'is_signed')")
274
285
 
275
286
  # Support comma-separated generic args in older Python versions
276
287
  if sys.version_info[0:2] < (3, 10):
@@ -284,10 +295,10 @@ class QArray(ArrayBase[_P], QVar):
284
295
  self,
285
296
  name: str,
286
297
  element_type: _GenericAlias = QBit,
287
- length: Optional[Union[int, QParam[int]]] = None,
298
+ length: Optional[Union[int, CInt]] = None,
288
299
  # TODO [CAD-18620]: improve type hints
289
300
  slice_: Optional[Tuple[int, int]] = None,
290
- index_: Optional[Union[int, QParam[int]]] = None,
301
+ index_: Optional[Union[int, CInt]] = None,
291
302
  ) -> None:
292
303
  if element_type is not QBit:
293
304
  raise ClassiqValueError(UNSUPPORTED_ELEMENT_TYPE)
@@ -313,7 +324,7 @@ class QArray(ArrayBase[_P], QVar):
313
324
 
314
325
  return HandleBinding(name=self._name)
315
326
 
316
- def __getitem__(self, key: Union[slice, int, QParam]) -> "QArray":
327
+ def __getitem__(self, key: Union[slice, int, CInt]) -> "QArray":
317
328
  if self._index is not None:
318
329
  raise ClassiqValueError(QARRAY_ELEMENT_NOT_SUBSCRIPTABLE)
319
330
 
@@ -326,7 +337,7 @@ class QArray(ArrayBase[_P], QVar):
326
337
  new_slice = self._get_new_slice(key.start, key.stop)
327
338
 
328
339
  else:
329
- if isinstance(key, QParam) and not isinstance(key, QParamScalar):
340
+ if isinstance(key, CParam) and not isinstance(key, CParamScalar):
330
341
  raise ClassiqValueError("Non-classical parameter for slicing")
331
342
  new_slice = self._get_new_slice(key, key + 1)
332
343
  new_index = new_slice[0]
@@ -368,10 +379,10 @@ class QArray(ArrayBase[_P], QVar):
368
379
  else:
369
380
 
370
381
  @property
371
- def len(self) -> QParamScalar:
382
+ def len(self) -> CParamScalar:
372
383
  if self._length is not None:
373
- return QParamScalar(f"{self._length}")
374
- return QParamScalar(f"len({self._name})")
384
+ return CParamScalar(f"{self._length}")
385
+ return CParamScalar(f"get_field({self._name}, 'len')")
375
386
 
376
387
  @classmethod
377
388
  def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
@@ -12,6 +12,7 @@ from typing import ( # type: ignore[attr-defined]
12
12
 
13
13
  from typing_extensions import ParamSpec
14
14
 
15
+ from classiq.interface.ast_node import SourceReference
15
16
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
16
17
  from classiq.interface.model.quantum_function_declaration import (
17
18
  QuantumFunctionDeclaration,
@@ -19,7 +20,8 @@ from classiq.interface.model.quantum_function_declaration import (
19
20
  from classiq.interface.model.quantum_statement import QuantumStatement
20
21
  from classiq.interface.model.quantum_type import QuantumType
21
22
 
22
- from classiq.qmod.qmod_parameter import QParam
23
+ from classiq.qmod.qmod_parameter import CInt
24
+ from classiq.qmod.utilities import get_source_ref
23
25
 
24
26
  if TYPE_CHECKING:
25
27
  from classiq.qmod.quantum_expandable import QTerminalCallable
@@ -42,8 +44,9 @@ class QCallable(Generic[P], ABC):
42
44
 
43
45
  def __call__(self, *args: Any, **kwargs: Any) -> None:
44
46
  assert QCallable.CURRENT_EXPANDABLE is not None
47
+ source_ref = get_source_ref(sys._getframe(1))
45
48
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
46
- self.create_quantum_function_call(*args, **kwargs)
49
+ self.create_quantum_function_call(source_ref, *args, **kwargs)
47
50
  )
48
51
  return
49
52
 
@@ -60,7 +63,7 @@ class QCallable(Generic[P], ABC):
60
63
 
61
64
  @abstractmethod
62
65
  def create_quantum_function_call(
63
- self, *args: Any, **kwargs: Any
66
+ self, source_ref_: SourceReference, *args: Any, **kwargs: Any
64
67
  ) -> QuantumFunctionCall:
65
68
  raise NotImplementedError()
66
69
 
@@ -71,5 +74,5 @@ class QCallableList(QCallable, Generic[P], ABC):
71
74
  @property
72
75
  def len(self) -> int: ...
73
76
 
74
- def __getitem__(self, key: Union[slice, int, QParam]) -> "QTerminalCallable":
77
+ def __getitem__(self, key: Union[slice, int, CInt]) -> "QTerminalCallable":
75
78
  raise NotImplementedError()
@@ -17,6 +17,7 @@ from typing import (
17
17
 
18
18
  from typing_extensions import Self
19
19
 
20
+ from classiq.interface.ast_node import SourceReference
20
21
  from classiq.interface.generator.expressions.expression import Expression
21
22
  from classiq.interface.model.classical_parameter_declaration import (
22
23
  ClassicalParameterDeclaration,
@@ -42,12 +43,12 @@ from classiq.interface.model.variable_declaration_statement import (
42
43
  from classiq.exceptions import ClassiqValueError
43
44
  from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
44
45
  from classiq.qmod.qmod_constant import QConstant
45
- from classiq.qmod.qmod_parameter import QParam, QParamScalar, create_param
46
+ from classiq.qmod.qmod_parameter import CInt, CParam, CParamScalar, create_param
46
47
  from classiq.qmod.qmod_variable import QVar, create_qvar_for_port_decl
47
48
  from classiq.qmod.quantum_callable import QCallable, QExpandableInterface
48
49
  from classiq.qmod.utilities import mangle_keyword
49
50
 
50
- ArgType = Union[QParam, QVar, QCallable]
51
+ ArgType = Union[CParam, QVar, QCallable]
51
52
 
52
53
 
53
54
  class QExpandable(QCallable, QExpandableInterface, ABC):
@@ -109,9 +110,11 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
109
110
  return result
110
111
 
111
112
  def create_quantum_function_call(
112
- self, *args: Any, **kwargs: Any
113
+ self, source_ref_: SourceReference, *args: Any, **kwargs: Any
113
114
  ) -> QuantumFunctionCall:
114
- return _create_quantum_function_call(self.func_decl, None, *args, **kwargs)
115
+ return _create_quantum_function_call(
116
+ self.func_decl, None, source_ref_, *args, **kwargs
117
+ )
115
118
 
116
119
 
117
120
  class QLambdaFunction(QExpandable):
@@ -138,7 +141,7 @@ class QTerminalCallable(QCallable):
138
141
  def __init__(
139
142
  self,
140
143
  decl: QuantumFunctionDeclaration,
141
- index_: Optional[Union[int, QParamScalar]] = None,
144
+ index_: Optional[Union[int, CParamScalar]] = None,
142
145
  ) -> None:
143
146
  self._decl = decl
144
147
  self._index = index_
@@ -147,12 +150,12 @@ class QTerminalCallable(QCallable):
147
150
  def is_list(self) -> bool:
148
151
  return isinstance(self._decl, QuantumOperandDeclaration) and self._decl.is_list
149
152
 
150
- def __getitem__(self, key: Union[slice, int, QParam]) -> "QTerminalCallable":
153
+ def __getitem__(self, key: Union[slice, int, CInt]) -> "QTerminalCallable":
151
154
  if not self.is_list:
152
155
  raise ClassiqValueError("Cannot index a non-list operand")
153
156
  if isinstance(key, slice):
154
157
  raise NotImplementedError("Operand lists don't support slicing")
155
- if isinstance(key, QParam) and not isinstance(key, QParamScalar):
158
+ if isinstance(key, CParam) and not isinstance(key, CParamScalar):
156
159
  raise ClassiqValueError("Non-classical parameter for slicing")
157
160
  return QTerminalCallable(self._decl, key)
158
161
 
@@ -169,24 +172,24 @@ class QTerminalCallable(QCallable):
169
172
  else:
170
173
 
171
174
  @property
172
- def len(self) -> QParamScalar:
175
+ def len(self) -> CParamScalar:
173
176
  if not self.is_list:
174
177
  raise ClassiqValueError("Cannot get length of a non-list operand")
175
- return QParamScalar(f"len({self.func_decl.name})")
178
+ return CParamScalar(f"{self.func_decl.name}.len")
176
179
 
177
180
  @property
178
181
  def func_decl(self) -> QuantumFunctionDeclaration:
179
182
  return self._decl
180
183
 
181
184
  def create_quantum_function_call(
182
- self, *args: Any, **kwargs: Any
185
+ self, source_ref_: SourceReference, *args: Any, **kwargs: Any
183
186
  ) -> QuantumFunctionCall:
184
187
  if self.is_list and self._index is None:
185
188
  raise ClassiqValueError(
186
189
  f"Quantum operand {self.func_decl.name!r} is a list and must be indexed"
187
190
  )
188
191
  return _create_quantum_function_call(
189
- self.func_decl, self._index, *args, **kwargs
192
+ self.func_decl, self._index, source_ref_, *args, **kwargs
190
193
  )
191
194
 
192
195
 
@@ -278,7 +281,8 @@ def _prepare_args(
278
281
 
279
282
  def _create_quantum_function_call(
280
283
  decl_: QuantumFunctionDeclaration,
281
- index_: Optional[Union[QParamScalar, int]] = None,
284
+ index_: Optional[Union[CParamScalar, int]] = None,
285
+ source_ref_: Optional[SourceReference] = None,
282
286
  *args: Any,
283
287
  **kwargs: Any,
284
288
  ) -> QuantumFunctionCall:
@@ -306,4 +310,6 @@ def _create_quantum_function_call(
306
310
  index=Expression(expr=str(index_)), name=function_ident
307
311
  )
308
312
 
309
- return QuantumFunctionCall(function=function_ident, positional_args=prepared_args)
313
+ return QuantumFunctionCall(
314
+ function=function_ident, positional_args=prepared_args, source_ref=source_ref_
315
+ )
@@ -1,8 +1,11 @@
1
1
  import ast
2
2
  import functools
3
+ import warnings
4
+ from inspect import isclass
3
5
  from typing import Any, Callable, Dict, List, Optional, Tuple, get_origin
4
6
 
5
7
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
8
+ from classiq.interface.generator.functions.classical_type import CStructBase
6
9
  from classiq.interface.generator.model.constraints import Constraints
7
10
  from classiq.interface.generator.model.preferences.preferences import Preferences
8
11
  from classiq.interface.model.model import Model, SerializedModel
@@ -15,7 +18,7 @@ from classiq.exceptions import ClassiqError
15
18
  from classiq.qmod.classical_function import CFunc
16
19
  from classiq.qmod.declaration_inferrer import infer_func_decl
17
20
  from classiq.qmod.qmod_constant import QConstant
18
- from classiq.qmod.qmod_parameter import QParam
21
+ from classiq.qmod.qmod_parameter import CArray, CParam, QParam
19
22
  from classiq.qmod.qmod_variable import QVar
20
23
  from classiq.qmod.quantum_callable import QCallable, QCallableList
21
24
  from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
@@ -46,6 +49,18 @@ def create_model(
46
49
  class QFunc(QExpandable):
47
50
  def __init__(self, py_callable: Callable) -> None:
48
51
  _validate_no_gen_params(py_callable.__annotations__)
52
+ if any(
53
+ get_origin(annotation) == QParam
54
+ for annotation in py_callable.__annotations__.values()
55
+ ):
56
+ warnings.warn(
57
+ "QParam is deprecated and will be removed in a future release. Use the "
58
+ "new classical parameter types instead:\n * QParam[int] -> CInt\n * QParam[float] "
59
+ "-> CReal\n * QParam[bool] -> CBool\n * QParam[list[int]] -> "
60
+ "CArray[CInt]",
61
+ category=DeprecationWarning,
62
+ stacklevel=4,
63
+ )
49
64
  super().__init__(py_callable)
50
65
  functools.update_wrapper(self, py_callable)
51
66
 
@@ -144,7 +159,10 @@ ILLEGAL_PARAM_ERROR = "Unsupported type hint '{annotation}' for argument '{name}
144
159
 
145
160
 
146
161
  class IllegalParamsError(ClassiqError):
147
- _HINT = "\nNote - QMOD functions can declare classical parameters using the type hint 'QParam'."
162
+ _HINT = (
163
+ "\nNote - QMOD functions can declare classical parameters using the type hints "
164
+ "'CInt', 'CReal', 'CBool', and 'CArray'."
165
+ )
148
166
 
149
167
  def __init__(self, message: str) -> None:
150
168
  super().__init__(message + self._HINT)
@@ -157,6 +175,11 @@ def _validate_no_gen_params(annotations: Dict[str, Any]) -> None:
157
175
  if not (
158
176
  name == "return"
159
177
  or get_origin(annotation) is QParam
178
+ or isclass(annotation)
179
+ and issubclass(annotation, CParam)
180
+ or isclass(annotation)
181
+ and issubclass(annotation, CStructBase)
182
+ or get_origin(annotation) is CArray
160
183
  or (get_origin(annotation) or annotation) is QCallable
161
184
  or (get_origin(annotation) or annotation) is QCallableList
162
185
  or QVar.from_type_hint(annotation) is not None