classiq 0.63.1__py3-none-any.whl → 0.64.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 (42) hide show
  1. classiq/analyzer/url_utils.py +2 -3
  2. classiq/interface/_version.py +1 -1
  3. classiq/interface/analyzer/result.py +1 -2
  4. classiq/interface/executor/result.py +6 -3
  5. classiq/interface/helpers/datastructures.py +26 -0
  6. classiq/interface/interface_version.py +1 -1
  7. classiq/interface/model/handle_binding.py +11 -3
  8. classiq/interface/server/routes.py +4 -0
  9. classiq/model_expansions/atomic_expression_functions_defs.py +6 -6
  10. classiq/model_expansions/capturing/captured_vars.py +27 -10
  11. classiq/model_expansions/evaluators/arg_type_match.py +4 -7
  12. classiq/model_expansions/evaluators/quantum_type_utils.py +15 -8
  13. classiq/model_expansions/expression_evaluator.py +8 -2
  14. classiq/model_expansions/generative_functions.py +3 -3
  15. classiq/model_expansions/interpreters/__init__.py +0 -0
  16. classiq/model_expansions/{interpreter.py → interpreters/base_interpreter.py} +26 -137
  17. classiq/model_expansions/interpreters/generative_interpreter.py +108 -0
  18. classiq/model_expansions/model_tables.py +1 -92
  19. classiq/model_expansions/quantum_operations/__init__.py +0 -10
  20. classiq/model_expansions/quantum_operations/call_emitter.py +3 -3
  21. classiq/model_expansions/quantum_operations/emitter.py +2 -2
  22. classiq/model_expansions/quantum_operations/quantum_function_call.py +2 -2
  23. classiq/model_expansions/quantum_operations/shallow_emitter.py +2 -2
  24. classiq/model_expansions/scope_initialization.py +8 -0
  25. classiq/qmod/declaration_inferrer.py +0 -3
  26. classiq/qmod/generative.py +4 -4
  27. classiq/qmod/qfunc.py +4 -2
  28. classiq/qmod/qmod_variable.py +17 -10
  29. classiq/qmod/quantum_function.py +6 -4
  30. classiq/qmod/utilities.py +7 -1
  31. {classiq-0.63.1.dist-info → classiq-0.64.0.dist-info}/METADATA +1 -1
  32. {classiq-0.63.1.dist-info → classiq-0.64.0.dist-info}/RECORD +33 -39
  33. classiq/interface/helpers/dotdict.py +0 -18
  34. classiq/model_expansions/quantum_operations/control.py +0 -290
  35. classiq/model_expansions/quantum_operations/expression_operation.py +0 -103
  36. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +0 -535
  37. classiq/model_expansions/quantum_operations/invert.py +0 -36
  38. classiq/model_expansions/quantum_operations/phase.py +0 -187
  39. classiq/model_expansions/quantum_operations/power.py +0 -71
  40. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +0 -230
  41. classiq/model_expansions/quantum_operations/within_apply.py +0 -25
  42. {classiq-0.63.1.dist-info → classiq-0.64.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,5 @@
1
1
  import urllib
2
2
  from urllib.parse import urljoin
3
- from uuid import UUID
4
3
 
5
4
  from classiq.interface.server import routes
6
5
 
@@ -21,7 +20,7 @@ def versioned_url_params(circuit_version: str) -> str:
21
20
  )
22
21
 
23
22
 
24
- def circuit_page_uri(circuit_id: UUID, circuit_version: str) -> str:
25
- url = urljoin(f"{routes.ANALYZER_CIRCUIT_PAGE}/", str(circuit_id))
23
+ def circuit_page_uri(circuit_id: str, circuit_version: str) -> str:
24
+ url = urljoin(f"{routes.ANALYZER_CIRCUIT_PAGE}/", circuit_id)
26
25
  url += versioned_url_params(circuit_version=circuit_version)
27
26
  return url
@@ -3,5 +3,5 @@ from packaging.version import Version
3
3
  # This file was generated automatically
4
4
  # Please don't track in version control (DONTTRACK)
5
5
 
6
- SEMVER_VERSION = '0.63.1'
6
+ SEMVER_VERSION = '0.64.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -1,5 +1,4 @@
1
1
  from typing import Annotated, Literal, Optional, Union
2
- from uuid import UUID
3
2
 
4
3
  import pydantic
5
4
  from pydantic import Field
@@ -34,7 +33,7 @@ class RbResults(VersionedModel):
34
33
 
35
34
 
36
35
  class DataID(pydantic.BaseModel):
37
- id: UUID
36
+ id: str
38
37
 
39
38
 
40
39
  class QasmCode(pydantic.BaseModel):
@@ -20,7 +20,7 @@ from classiq.interface.generator.arith import number_utils
20
20
  from classiq.interface.generator.complex_type import Complex
21
21
  from classiq.interface.generator.functions.classical_type import QmodPyObject
22
22
  from classiq.interface.helpers.custom_pydantic_types import PydanticNonNegIntTuple
23
- from classiq.interface.helpers.dotdict import get_recursive_dotdict
23
+ from classiq.interface.helpers.datastructures import get_sdk_compatible_python_object
24
24
  from classiq.interface.helpers.versioned_model import VersionedModel
25
25
 
26
26
  _ILLEGAL_QUBIT_ERROR_MSG: str = "Illegal qubit index requested"
@@ -51,8 +51,11 @@ class SampledState(BaseModel):
51
51
 
52
52
  @pydantic.field_validator("state", mode="after")
53
53
  @classmethod
54
- def _convert_state_to_dotdict(cls, state: ParsedState) -> DotAccessParsedState:
55
- return {name: get_recursive_dotdict(value) for name, value in state.items()}
54
+ def _make_state_sdk_compatible(cls, state: ParsedState) -> DotAccessParsedState:
55
+ return {
56
+ name: get_sdk_compatible_python_object(value)
57
+ for name, value in state.items()
58
+ }
56
59
 
57
60
 
58
61
  ParsedCounts: TypeAlias = list[SampledState]
@@ -0,0 +1,26 @@
1
+ from typing import Any
2
+
3
+
4
+ class DotDict(dict):
5
+ def __getattr__(self, key: str) -> Any:
6
+ return super().get(key)
7
+
8
+ def __setattr__(self, key: str, value: Any) -> None:
9
+ super().__setitem__(key, value)
10
+
11
+ def __delattr__(self, key: str) -> None:
12
+ super().__delitem__(key)
13
+
14
+
15
+ class LenList(list):
16
+ @property
17
+ def len(self) -> int:
18
+ return len(self)
19
+
20
+
21
+ def get_sdk_compatible_python_object(obj: Any) -> Any:
22
+ if isinstance(obj, list):
23
+ return LenList([get_sdk_compatible_python_object(item) for item in obj])
24
+ if isinstance(obj, dict):
25
+ return DotDict({k: get_sdk_compatible_python_object(v) for k, v in obj.items()})
26
+ return obj
@@ -1 +1 @@
1
- INTERFACE_VERSION = "6"
1
+ INTERFACE_VERSION = "7"
@@ -243,15 +243,23 @@ class SlicedHandleBinding(NestedHandleBinding):
243
243
  def _get_collapsed_stop(self) -> Expression:
244
244
  if TYPE_CHECKING:
245
245
  assert isinstance(self.base_handle, SlicedHandleBinding)
246
- if self.end.is_evaluated() and self.base_handle.end.is_evaluated():
246
+ if self._is_evaluated() and self.base_handle.start.is_evaluated():
247
247
  return Expression(
248
- expr=str(self.base_handle.end.to_int_value() - self.end.to_int_value())
248
+ expr=str(
249
+ self.end.to_int_value()
250
+ - self.start.to_int_value()
251
+ + self.base_handle.start.to_int_value()
252
+ )
249
253
  )
250
- return Expression(expr=f"({self.base_handle.end})-({self.end})")
254
+ return Expression(
255
+ expr=f"({self.end})-({self.start})+({self.base_handle.start})"
256
+ )
251
257
 
252
258
  def replace_prefix(
253
259
  self, prefix: HandleBinding, replacement: HandleBinding
254
260
  ) -> HandleBinding:
261
+ if self == prefix:
262
+ return replacement
255
263
  if (
256
264
  isinstance(prefix, SlicedHandleBinding)
257
265
  and self.base_handle == prefix.base_handle
@@ -24,12 +24,16 @@ TASKS_SUFFIX = "/tasks"
24
24
  RB = "/rb"
25
25
  ANALYZER_DATA_TASK = f"{TASKS_SUFFIX}/data"
26
26
  ANALYZER_QASM_TASK = f"{TASKS_SUFFIX}/qasm"
27
+ ANALYZER_GET_VISUAL_MODEL = "/get_visual_model"
28
+ ANALYZER_GET_IDE_DATA = "/get_ide_data"
27
29
  IDE_EVENT_TASK = f"{TASKS_SUFFIX}/event"
28
30
  DATA_DOG_EVENT_TASK = f"{TASKS_SUFFIX}/data_dog_event"
29
31
 
30
32
  ANALYZER_DATA_TASK_UPLOAD_FILE = f"{TASKS_SUFFIX}/data/file_upload"
31
33
  ANALYZER_DATA_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_DATA_TASK}"
32
34
  ANALYZER_QASM_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_QASM_TASK}"
35
+ ANALYZER_GET_VISUAL_MODEL_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_GET_VISUAL_MODEL}"
36
+ ANALYZER_GET_IDE_DATA_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_GET_IDE_DATA}"
33
37
  IDE_EVENT_TASK_FULL_PATH = f"{ANALYZER_PREFIX}{IDE_EVENT_TASK}"
34
38
  DATA_DOG_EVENT_TASK_FULL_PATH = f"{ANALYZER_PREFIX}{DATA_DOG_EVENT_TASK}"
35
39
 
@@ -33,7 +33,6 @@ from classiq.interface.generator.functions.type_name import TypeName
33
33
  from classiq.model_expansions.model_tables import (
34
34
  HandleIdentifier,
35
35
  HandleTable,
36
- SymbolTable,
37
36
  )
38
37
  from classiq.model_expansions.sympy_conversion.arithmetics import (
39
38
  BitwiseAnd,
@@ -48,13 +47,14 @@ from classiq.model_expansions.sympy_conversion.expression_to_sympy import (
48
47
  from classiq.model_expansions.sympy_conversion.sympy_to_python import (
49
48
  sympy_to_python,
50
49
  )
50
+ from classiq.qmod.model_state_container import QMODULE
51
51
 
52
52
 
53
53
  def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
54
54
  if isinstance(qmod_type, TypeName):
55
55
  if (
56
56
  isinstance(val, QmodStructInstance)
57
- and val.struct_declaration == SymbolTable.type_table[qmod_type.name]
57
+ and val.struct_declaration == QMODULE.type_decls[qmod_type.name]
58
58
  ):
59
59
  return {
60
60
  field_name: qmod_val_to_python(val.fields[field_name], field_type)
@@ -97,10 +97,10 @@ def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
97
97
 
98
98
  def python_val_to_qmod(val: Any, qmod_type: ClassicalType) -> ExpressionValue:
99
99
  if isinstance(qmod_type, TypeName):
100
- if qmod_type.name in SymbolTable.enum_table:
100
+ if qmod_type.name in QMODULE.enum_decls:
101
101
  return val
102
102
 
103
- struct_decl = SymbolTable.type_table[qmod_type.name]
103
+ struct_decl = QMODULE.type_decls[qmod_type.name]
104
104
  if not isinstance(val, Mapping):
105
105
  raise ClassiqInternalExpansionError(
106
106
  f"Bad value for struct {struct_decl.name}"
@@ -138,7 +138,7 @@ def python_call_wrapper(func: Callable, *args: ExpressionValue) -> Any:
138
138
 
139
139
  def struct_literal(struct_type_symbol: Symbol, **kwargs: Any) -> QmodStructInstance:
140
140
  return QmodStructInstance(
141
- SymbolTable.type_table[struct_type_symbol.name],
141
+ QMODULE.type_decls[struct_type_symbol.name],
142
142
  {field: sympy_to_python(field_value) for field, field_value in kwargs.items()},
143
143
  )
144
144
 
@@ -179,7 +179,7 @@ def get_field(
179
179
 
180
180
 
181
181
  def get_type(struct_type: Symbol) -> TypeProxy:
182
- return TypeProxy(SymbolTable.type_table[struct_type.name])
182
+ return TypeProxy(QMODULE.type_decls[struct_type.name])
183
183
 
184
184
 
185
185
  def _unwrap_sympy_numeric(n: Any) -> Any:
@@ -34,6 +34,10 @@ if TYPE_CHECKING:
34
34
  from classiq.model_expansions.closure import FunctionClosure
35
35
 
36
36
 
37
+ ALREADY_ALLOCATED_MESSAGE = "Cannot allocate variable '{}', it is already initialized"
38
+ ALREADY_FREED_MESSAGE = "Cannot free variable '{}', it is already uninitialized"
39
+
40
+
37
41
  class PortDirection(StrEnum):
38
42
  Input = "input"
39
43
  Inout = "inout"
@@ -141,7 +145,14 @@ class CapturedVars:
141
145
  isinstance(captured_handle.handle, NestedHandleBinding)
142
146
  and captured_handle.direction != PortDirection.Inout
143
147
  ):
144
- raise ClassiqInternalExpansionError("Captured nested handles must be inout")
148
+ verb = (
149
+ "free"
150
+ if captured_handle.direction == PortDirection.Input
151
+ else "allocate"
152
+ )
153
+ raise ClassiqExpansionError(
154
+ f"Cannot partially {verb} variable {captured_handle.handle.name}"
155
+ )
145
156
 
146
157
  new_captured_handles = []
147
158
  for existing_captured_handle in self._captured_handles:
@@ -174,7 +185,9 @@ class CapturedVars:
174
185
  return captured_handle.change_direction(PortDirection.Inout)
175
186
  if captured_handle.direction == PortDirection.Outin:
176
187
  return captured_handle.change_direction(PortDirection.Input)
177
- raise ClassiqInternalExpansionError("Captured handle is already freed")
188
+ raise ClassiqExpansionError(
189
+ ALREADY_FREED_MESSAGE.format(captured_handle.handle)
190
+ )
178
191
  if existing_captured_handle.direction == PortDirection.Output:
179
192
  if captured_handle.direction == PortDirection.Input:
180
193
  return captured_handle.change_direction(PortDirection.Outin)
@@ -182,8 +195,8 @@ class CapturedVars:
182
195
  PortDirection.Output,
183
196
  PortDirection.Outin,
184
197
  ):
185
- raise ClassiqInternalExpansionError(
186
- "Captured handle is already allocated"
198
+ raise ClassiqExpansionError(
199
+ ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
187
200
  )
188
201
  return captured_handle.change_direction(PortDirection.Output)
189
202
  if existing_captured_handle.direction == PortDirection.Inout:
@@ -191,14 +204,16 @@ class CapturedVars:
191
204
  PortDirection.Output,
192
205
  PortDirection.Outin,
193
206
  ):
194
- raise ClassiqInternalExpansionError(
195
- "Captured handle is already allocated"
207
+ raise ClassiqExpansionError(
208
+ ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
196
209
  )
197
210
  elif captured_handle.direction in (
198
211
  PortDirection.Input,
199
212
  PortDirection.Inout,
200
213
  ):
201
- raise ClassiqInternalExpansionError("Captured handle is already freed")
214
+ raise ClassiqExpansionError(
215
+ ALREADY_FREED_MESSAGE.format(captured_handle.handle)
216
+ )
202
217
  return captured_handle
203
218
 
204
219
  def _intersect_handles(
@@ -211,7 +226,9 @@ class CapturedVars:
211
226
  PortDirection.Input,
212
227
  PortDirection.Outin,
213
228
  ):
214
- raise ClassiqInternalExpansionError("Captured handle is already freed")
229
+ raise ClassiqExpansionError(
230
+ ALREADY_FREED_MESSAGE.format(captured_handle.handle)
231
+ )
215
232
  return existing_captured_handle
216
233
 
217
234
  if existing_captured_handle.handle in captured_handle.handle:
@@ -219,8 +236,8 @@ class CapturedVars:
219
236
  PortDirection.Output,
220
237
  PortDirection.Outin,
221
238
  ):
222
- raise ClassiqInternalExpansionError(
223
- "Captured handle is already allocated"
239
+ raise ClassiqExpansionError(
240
+ ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
224
241
  )
225
242
  return captured_handle
226
243
 
@@ -25,8 +25,8 @@ from classiq.interface.model.quantum_function_declaration import (
25
25
 
26
26
  from classiq.model_expansions.closure import FunctionClosure
27
27
  from classiq.model_expansions.evaluators.type_type_match import check_signature_match
28
- from classiq.model_expansions.model_tables import SymbolTable
29
28
  from classiq.model_expansions.scope import Evaluated, QuantumSymbol
29
+ from classiq.qmod.model_state_container import QMODULE
30
30
  from classiq.qmod.qmod_parameter import CInt, get_qmod_type
31
31
 
32
32
 
@@ -122,11 +122,11 @@ def _check_classical_type_match(
122
122
  type_name = _resolve_type_name(classical_type)
123
123
  type_is_struct = (
124
124
  isinstance(classical_type, TypeName)
125
- and classical_type.name in SymbolTable.type_table
125
+ and classical_type.name in QMODULE.type_decls
126
126
  )
127
127
  type_is_enum = (
128
128
  isinstance(classical_type, TypeName)
129
- and classical_type.name in SymbolTable.enum_table
129
+ and classical_type.name in QMODULE.enum_decls
130
130
  )
131
131
  arg_is_qvar = isinstance(argument, QmodSizedProxy)
132
132
  arg_is_builtin = argument.__class__.__module__ == "builtins"
@@ -153,9 +153,6 @@ def _resolve_type_name(classical_type: ConcreteClassicalType) -> str:
153
153
  type_name = get_qmod_type(classical_type).__name__
154
154
  if not isinstance(classical_type, TypeName):
155
155
  return type_name
156
- if (
157
- type_name not in SymbolTable.type_table
158
- and type_name not in SymbolTable.enum_table
159
- ):
156
+ if type_name not in QMODULE.type_decls and type_name not in QMODULE.enum_decls:
160
157
  raise ClassiqExpansionError(f"Undefined type {type_name}")
161
158
  return type_name
@@ -10,10 +10,12 @@ from classiq.interface.generator.functions.type_name import (
10
10
  TypeName,
11
11
  )
12
12
  from classiq.interface.model.bind_operation import BindOperation
13
+ from classiq.interface.model.inplace_binary_operation import BinaryOperation
13
14
  from classiq.interface.model.quantum_type import (
14
15
  QuantumBit,
15
16
  QuantumBitvector,
16
17
  QuantumNumeric,
18
+ QuantumScalar,
17
19
  QuantumType,
18
20
  )
19
21
 
@@ -209,14 +211,19 @@ def validate_bind_targets(bind: BindOperation, scope: Scope) -> None:
209
211
  )
210
212
 
211
213
 
212
- def validate_inplace_binary_op_vars(
213
- value_var: QuantumSymbol, target_var: QuantumSymbol, operation_name: str
214
- ) -> None:
215
- if not isinstance(value_var.quantum_type, QuantumNumeric):
214
+ def get_inplace_op_scalar_as_numeric(
215
+ var: QuantumSymbol, operation: BinaryOperation, var_kind: str
216
+ ) -> QuantumNumeric:
217
+ if not isinstance(var.quantum_type, QuantumScalar):
216
218
  raise ClassiqExpansionError(
217
- f"Cannot perform `{operation_name}` operation with non numeric value {value_var.handle}"
219
+ f"Cannot perform inplace {operation.name.lower()} with non-scalar {var_kind} {var.handle}"
218
220
  )
219
- if not isinstance(target_var.quantum_type, QuantumNumeric):
220
- raise ClassiqExpansionError(
221
- f"Cannot perform `{operation_name}` operation with non numeric target {target_var.handle}"
221
+ if isinstance(var.quantum_type, QuantumNumeric):
222
+ return var.quantum_type
223
+ if isinstance(var.quantum_type, QuantumBit):
224
+ return QuantumNumeric(
225
+ size=Expression(expr="1"),
226
+ is_signed=Expression(expr="False"),
227
+ fraction_digits=Expression(expr="0"),
222
228
  )
229
+ raise ClassiqInternalExpansionError(f"Unexpected scalar type {var.quantum_type}")
@@ -24,12 +24,13 @@ from classiq.model_expansions.atomic_expression_functions_defs import (
24
24
  ATOMIC_EXPRESSION_FUNCTIONS,
25
25
  qmod_val_to_python,
26
26
  )
27
- from classiq.model_expansions.model_tables import SymbolTable
28
27
  from classiq.model_expansions.sympy_conversion.expression_to_sympy import (
29
28
  translate_to_sympy,
30
29
  )
31
30
  from classiq.model_expansions.sympy_conversion.sympy_to_python import sympy_to_python
32
31
  from classiq.qmod import symbolic
32
+ from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
33
+ from classiq.qmod.model_state_container import QMODULE
33
34
 
34
35
 
35
36
  def evaluate_constants(constants: list[Constant]) -> dict[str, EvaluatedExpression]:
@@ -56,7 +57,12 @@ def evaluate(
56
57
  ) -> EvaluatedExpression:
57
58
  model_locals: dict[str, ExpressionValue] = {}
58
59
  model_locals.update(ATOMIC_EXPRESSION_FUNCTIONS)
59
- model_locals.update(SymbolTable.enum_table.enums)
60
+ model_locals.update(
61
+ {
62
+ enum_decl.name: enum_decl.create_enum()
63
+ for enum_decl in (QMODULE.enum_decls | BUILTIN_ENUM_DECLARATIONS).values()
64
+ }
65
+ )
60
66
  # locals override builtin-functions
61
67
  model_locals.update({name: expr.value for name, expr in locals_dict.items()})
62
68
  uninitialized_locals = uninitialized_locals or set()
@@ -34,7 +34,7 @@ from classiq.qmod.semantics.static_semantics_visitor import resolve_function_cal
34
34
  from classiq.qmod.symbolic_expr import SymbolicExpr
35
35
 
36
36
  if TYPE_CHECKING:
37
- from classiq.model_expansions.interpreter import Interpreter
37
+ from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
38
38
 
39
39
 
40
40
  class LenList(list):
@@ -94,7 +94,7 @@ def translate_ast_arg_to_python_qmod(param: PositionalArg, evaluated: Evaluated)
94
94
 
95
95
 
96
96
  class _InterpreterExpandable(QFunc):
97
- def __init__(self, interpreter: "Interpreter"):
97
+ def __init__(self, interpreter: "BaseInterpreter"):
98
98
  super().__init__(lambda: None)
99
99
  self._interpreter = interpreter
100
100
 
@@ -137,7 +137,7 @@ class _InterpreterExpandable(QFunc):
137
137
 
138
138
 
139
139
  def emit_generative_statements(
140
- interpreter: "Interpreter",
140
+ interpreter: "BaseInterpreter",
141
141
  operation: GenerativeClosure,
142
142
  args: list[Evaluated],
143
143
  ) -> None:
File without changes
@@ -1,3 +1,4 @@
1
+ from abc import abstractmethod
1
2
  from collections import defaultdict
2
3
  from collections.abc import Sequence
3
4
  from contextlib import nullcontext
@@ -15,30 +16,15 @@ from classiq.interface.exceptions import (
15
16
  )
16
17
  from classiq.interface.generator.constant import Constant
17
18
  from classiq.interface.generator.expressions.expression import Expression
18
- from classiq.interface.generator.functions.builtins.internal_operators import (
19
- CONTROL_OPERATOR_NAME,
20
- INVERT_OPERATOR_NAME,
21
- WITHIN_APPLY_NAME,
22
- )
23
19
  from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
24
- from classiq.interface.model.bind_operation import BindOperation
25
- from classiq.interface.model.classical_if import ClassicalIf
26
- from classiq.interface.model.control import Control
27
20
  from classiq.interface.model.handle_binding import (
28
21
  FieldHandleBinding,
29
22
  HandleBinding,
30
23
  SlicedHandleBinding,
31
24
  SubscriptHandleBinding,
32
25
  )
33
- from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
34
- from classiq.interface.model.invert import Invert
35
26
  from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
36
27
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
37
- from classiq.interface.model.phase_operation import PhaseOperation
38
- from classiq.interface.model.power import Power
39
- from classiq.interface.model.quantum_expressions.quantum_expression import (
40
- QuantumAssignmentOperation,
41
- )
42
28
  from classiq.interface.model.quantum_function_call import (
43
29
  QuantumFunctionCall,
44
30
  )
@@ -51,11 +37,6 @@ from classiq.interface.model.quantum_lambda_function import (
51
37
  QuantumLambdaFunction,
52
38
  )
53
39
  from classiq.interface.model.quantum_statement import QuantumStatement
54
- from classiq.interface.model.repeat import Repeat
55
- from classiq.interface.model.variable_declaration_statement import (
56
- VariableDeclarationStatement,
57
- )
58
- from classiq.interface.model.within_apply_operation import WithinApply
59
40
 
60
41
  from classiq.model_expansions.closure import (
61
42
  Closure,
@@ -74,21 +55,6 @@ from classiq.model_expansions.function_builder import (
74
55
  OperationContext,
75
56
  )
76
57
  from classiq.model_expansions.generative_functions import emit_generative_statements
77
- from classiq.model_expansions.quantum_operations import (
78
- BindEmitter,
79
- ClassicalIfEmitter,
80
- ControlEmitter,
81
- InplaceBinaryOperationEmitter,
82
- InvertEmitter,
83
- PowerEmitter,
84
- QuantumAssignmentOperationEmitter,
85
- QuantumFunctionCallEmitter,
86
- RepeatEmitter,
87
- VariableDeclarationStatementEmitter,
88
- WithinApplyEmitter,
89
- )
90
- from classiq.model_expansions.quantum_operations.phase import PhaseEmitter
91
- from classiq.model_expansions.quantum_operations.shallow_emitter import ShallowEmitter
92
58
  from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
93
59
  from classiq.model_expansions.scope_initialization import (
94
60
  add_constants_to_scope,
@@ -96,25 +62,24 @@ from classiq.model_expansions.scope_initialization import (
96
62
  add_functions_to_scope,
97
63
  add_generative_functions_to_scope,
98
64
  get_main_renamer,
65
+ init_builtin_types,
99
66
  init_top_level_scope,
100
67
  )
101
68
  from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
69
+ from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
102
70
  from classiq.qmod.builtins.functions import permute
71
+ from classiq.qmod.builtins.structs import BUILTIN_STRUCT_DECLARATIONS
103
72
  from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
104
73
  from classiq.qmod.quantum_function import GenerativeQFunc
105
74
  from classiq.qmod.semantics.error_manager import ErrorManager
106
75
 
107
76
 
108
- class Interpreter:
77
+ class BaseInterpreter:
109
78
  def __init__(
110
79
  self,
111
80
  model: Model,
112
81
  generative_functions: Optional[list[GenerativeQFunc]] = None,
113
- is_normalizer: bool = False,
114
- is_shallow: bool = False,
115
82
  ) -> None:
116
- self._is_normalizer = is_normalizer
117
- self._is_shallow = is_shallow
118
83
  self._model = model
119
84
  self._top_level_scope = Scope()
120
85
  self._counted_name_allocator = CountedNameAllocator()
@@ -123,12 +88,8 @@ class Interpreter:
123
88
  )
124
89
  self._expanded_functions: dict[str, NativeFunctionDefinition] = {}
125
90
 
91
+ init_builtin_types()
126
92
  init_top_level_scope(model, generative_functions or [], self._top_level_scope)
127
- self._main_renamer: Optional[ExpressionRenamer] = (
128
- get_main_renamer(self._get_function_declarations())
129
- if self._is_normalizer
130
- else None
131
- )
132
93
  self._functions_compilation_metadata: dict[str, CompilationMetadata] = dict(
133
94
  self._model.functions_compilation_metadata
134
95
  )
@@ -138,6 +99,13 @@ class Interpreter:
138
99
  self._counted_name_allocator = CountedNameAllocator()
139
100
  self._error_manager: ErrorManager = ErrorManager()
140
101
 
102
+ @property
103
+ def is_shallow(self) -> bool:
104
+ return False
105
+
106
+ def get_main_renamer(self) -> Optional[ExpressionRenamer]:
107
+ return get_main_renamer(self._get_function_declarations())
108
+
141
109
  def _expand_main_func(self) -> None:
142
110
  main_func = self._top_level_scope[MAIN_FUNCTION_NAME].value
143
111
  closure_constructor: Any
@@ -153,7 +121,7 @@ class Interpreter:
153
121
  name=main_func.name,
154
122
  positional_arg_declarations=main_func.positional_arg_declarations,
155
123
  scope=Scope(parent=self._top_level_scope),
156
- expr_renamer=self._main_renamer,
124
+ expr_renamer=self.get_main_renamer(),
157
125
  _depth=0,
158
126
  **extra_args,
159
127
  )
@@ -189,8 +157,16 @@ class Interpreter:
189
157
  execution_preferences=self._model.execution_preferences,
190
158
  functions=list(self._expanded_functions.values()),
191
159
  constants=self._model.constants,
192
- enums=list(QMODULE.enum_decls.values()),
193
- types=list(QMODULE.type_decls.values()),
160
+ enums=[
161
+ enum_decl
162
+ for name, enum_decl in QMODULE.enum_decls.items()
163
+ if name not in BUILTIN_ENUM_DECLARATIONS
164
+ ],
165
+ types=[
166
+ struct_decl
167
+ for name, struct_decl in QMODULE.type_decls.items()
168
+ if name not in BUILTIN_STRUCT_DECLARATIONS
169
+ ],
194
170
  qstructs=list(QMODULE.qstruct_decls.values()),
195
171
  debug_info=self._model.debug_info,
196
172
  functions_compilation_metadata=self._expanded_functions_compilation_metadata,
@@ -282,96 +258,9 @@ class Interpreter:
282
258
  base_value = self.evaluate(field_access.base_handle)
283
259
  return Evaluated(value=base_value.value.fields[field_access.field])
284
260
 
285
- @singledispatchmethod
261
+ @abstractmethod
286
262
  def emit(self, statement: QuantumStatement) -> None:
287
- raise NotImplementedError(f"Cannot emit {statement!r}")
288
-
289
- @emit.register
290
- def emit_quantum_function_call(self, call: QuantumFunctionCall) -> None:
291
- QuantumFunctionCallEmitter(self).emit(call)
292
-
293
- @emit.register
294
- def emit_bind(self, bind: BindOperation) -> None:
295
- BindEmitter(self).emit(bind)
296
-
297
- @emit.register
298
- def emit_quantum_assignment_operation(self, op: QuantumAssignmentOperation) -> None:
299
- if self._is_normalizer:
300
- ShallowEmitter(
301
- self, "assignment_operation", components=["expression", "result_var"]
302
- ).emit(op)
303
- else:
304
- QuantumAssignmentOperationEmitter(self).emit(op)
305
-
306
- @emit.register
307
- def emit_inplace_binary_operation(self, op: InplaceBinaryOperation) -> None:
308
- if self._is_normalizer:
309
- ShallowEmitter(
310
- self, "inplace_binary_operation", components=["target", "value"]
311
- ).emit(op)
312
- else:
313
- InplaceBinaryOperationEmitter(self).emit(op)
314
-
315
- @emit.register
316
- def emit_variable_declaration(
317
- self, variable_declaration: VariableDeclarationStatement
318
- ) -> None:
319
- VariableDeclarationStatementEmitter(self).emit(variable_declaration)
320
-
321
- @emit.register
322
- def emit_classical_if(self, classical_if: ClassicalIf) -> None:
323
- ClassicalIfEmitter(self).emit(classical_if)
324
-
325
- @emit.register
326
- def emit_within_apply(self, within_apply: WithinApply) -> None:
327
- if self._is_normalizer:
328
- ShallowEmitter(
329
- self,
330
- WITHIN_APPLY_NAME,
331
- components=["within", "apply", "compute", "action"],
332
- ).emit(within_apply)
333
- else:
334
- WithinApplyEmitter(self).emit(within_apply)
335
-
336
- @emit.register
337
- def emit_invert(self, invert: Invert) -> None:
338
- if self._is_normalizer:
339
- ShallowEmitter(self, INVERT_OPERATOR_NAME, components=["body"]).emit(invert)
340
- else:
341
- InvertEmitter(self).emit(invert)
342
-
343
- @emit.register
344
- def emit_repeat(self, repeat: Repeat) -> None:
345
- RepeatEmitter(self).emit(repeat)
346
-
347
- @emit.register
348
- def emit_control(self, control: Control) -> None:
349
- if self._is_normalizer:
350
- ShallowEmitter(
351
- self,
352
- CONTROL_OPERATOR_NAME,
353
- components=["expression", "body", "else_block"],
354
- ).emit(control)
355
- else:
356
- ControlEmitter(self).emit(control)
357
-
358
- @emit.register
359
- def emit_power(self, power: Power) -> None:
360
- if self._is_normalizer:
361
- ShallowEmitter(
362
- self, CONTROL_OPERATOR_NAME, components=["power", "body"]
363
- ).emit(power)
364
- else:
365
- PowerEmitter(self).emit(power)
366
-
367
- @emit.register
368
- def emit_phase(self, phase: PhaseOperation) -> None:
369
- if self._is_normalizer:
370
- ShallowEmitter(self, "phase", components=["expression", "theta"]).emit(
371
- phase
372
- )
373
- else:
374
- PhaseEmitter(self).emit(phase)
263
+ pass
375
264
 
376
265
  def _expand_block(self, block: Sequence[QuantumStatement], block_name: str) -> None:
377
266
  with self._builder.block_context(block_name):