classiq 0.82.0__py3-none-any.whl → 0.83.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.
- classiq/applications/chemistry/chemistry_model_constructor.py +2 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/generator/application_apis/finance_declarations.py +3 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +6 -2
- classiq/interface/generator/functions/type_modifier.py +41 -0
- classiq/interface/generator/generated_circuit_data.py +5 -8
- classiq/interface/generator/model/model.py +8 -0
- classiq/interface/generator/quantum_program.py +0 -13
- classiq/interface/generator/types/compilation_metadata.py +1 -1
- classiq/interface/helpers/model_normalizer.py +2 -2
- classiq/interface/model/port_declaration.py +27 -3
- classiq/model_expansions/capturing/captured_vars.py +21 -8
- classiq/model_expansions/evaluators/argument_types.py +2 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +16 -16
- classiq/model_expansions/transformers/model_renamer.py +10 -1
- classiq/model_expansions/transformers/{type_qualifier_inference.py → type_modifier_inference.py} +68 -72
- classiq/model_expansions/visitors/symbolic_param_inference.py +8 -4
- classiq/open_library/functions/state_preparation.py +1 -1
- classiq/qmod/__init__.py +2 -2
- classiq/qmod/builtins/functions/allocation.py +2 -2
- classiq/qmod/builtins/functions/arithmetic.py +16 -8
- classiq/qmod/builtins/functions/standard_gates.py +7 -7
- classiq/qmod/declaration_inferrer.py +5 -5
- classiq/qmod/native/pretty_printer.py +5 -5
- classiq/qmod/pretty_print/pretty_printer.py +6 -6
- classiq/qmod/qfunc.py +1 -1
- classiq/qmod/qmod_variable.py +10 -10
- classiq/qmod/semantics/validation/type_hints.py +9 -9
- classiq/synthesis.py +0 -2
- {classiq-0.82.0.dist-info → classiq-0.83.0.dist-info}/METADATA +1 -1
- {classiq-0.82.0.dist-info → classiq-0.83.0.dist-info}/RECORD +33 -33
- classiq/interface/generator/functions/type_qualifier.py +0 -22
- {classiq-0.82.0.dist-info → classiq-0.83.0.dist-info}/WHEEL +0 -0
@@ -21,7 +21,7 @@ from classiq.interface.generator.functions.classical_type import (
|
|
21
21
|
from classiq.interface.generator.functions.port_declaration import (
|
22
22
|
PortDeclarationDirection,
|
23
23
|
)
|
24
|
-
from classiq.interface.generator.functions.
|
24
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
25
25
|
from classiq.interface.model.allocate import Allocate
|
26
26
|
from classiq.interface.model.classical_parameter_declaration import (
|
27
27
|
ClassicalParameterDeclaration,
|
@@ -475,7 +475,7 @@ def _get_chemistry_quantum_main(
|
|
475
475
|
PortDeclaration(
|
476
476
|
name="qbv",
|
477
477
|
direction=PortDeclarationDirection.Output,
|
478
|
-
|
478
|
+
type_modifier=TypeModifier.Mutable,
|
479
479
|
)
|
480
480
|
],
|
481
481
|
body=body,
|
classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py
CHANGED
@@ -12,8 +12,8 @@ from classiq.interface.generator.functions.classical_type import (
|
|
12
12
|
from classiq.interface.generator.functions.port_declaration import (
|
13
13
|
PortDeclarationDirection,
|
14
14
|
)
|
15
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
15
16
|
from classiq.interface.generator.functions.type_name import Struct
|
16
|
-
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
17
17
|
from classiq.interface.model.allocate import Allocate
|
18
18
|
from classiq.interface.model.classical_parameter_declaration import (
|
19
19
|
ClassicalParameterDeclaration,
|
@@ -96,7 +96,7 @@ def construct_combi_opt_py_model(
|
|
96
96
|
length=Expression(expr=f"{len_hamiltonian}"),
|
97
97
|
),
|
98
98
|
direction=PortDeclarationDirection.Output,
|
99
|
-
|
99
|
+
type_modifier=TypeModifier.Mutable,
|
100
100
|
),
|
101
101
|
],
|
102
102
|
body=[
|
classiq/interface/_version.py
CHANGED
@@ -9,8 +9,8 @@ from classiq.interface.generator.functions.classical_type import Real
|
|
9
9
|
from classiq.interface.generator.functions.port_declaration import (
|
10
10
|
PortDeclarationDirection,
|
11
11
|
)
|
12
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
12
13
|
from classiq.interface.generator.functions.type_name import Struct
|
13
|
-
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
14
14
|
from classiq.interface.model.classical_parameter_declaration import (
|
15
15
|
ClassicalParameterDeclaration,
|
16
16
|
)
|
@@ -56,13 +56,13 @@ def _generate_finance_function(
|
|
56
56
|
)
|
57
57
|
),
|
58
58
|
direction=PortDeclarationDirection.Inout,
|
59
|
-
|
59
|
+
type_modifier=TypeModifier.Mutable,
|
60
60
|
),
|
61
61
|
PortDeclaration(
|
62
62
|
name=OBJECTIVE_PORT_NAME,
|
63
63
|
quantum_type=QuantumBit(),
|
64
64
|
direction=PortDeclarationDirection.Inout,
|
65
|
-
|
65
|
+
type_modifier=TypeModifier.Mutable,
|
66
66
|
),
|
67
67
|
],
|
68
68
|
)
|
@@ -11,14 +11,18 @@ CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS = {
|
|
11
11
|
"molecule_ground_state_solution_post_process",
|
12
12
|
}
|
13
13
|
|
14
|
-
|
15
|
-
*CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS,
|
14
|
+
CLASSIQ_EXPR_FUNCTIONS = {
|
16
15
|
"do_div",
|
17
16
|
"do_slice",
|
18
17
|
"do_subscript",
|
19
18
|
"get_type",
|
20
19
|
"struct_literal",
|
21
20
|
"get_field",
|
21
|
+
}
|
22
|
+
|
23
|
+
SUPPORTED_CLASSIQ_BUILTIN_FUNCTIONS = {
|
24
|
+
*CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS,
|
25
|
+
*CLASSIQ_EXPR_FUNCTIONS,
|
22
26
|
"mod_inverse",
|
23
27
|
}
|
24
28
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
from classiq.interface.enum_utils import StrEnum
|
2
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
3
|
+
|
4
|
+
|
5
|
+
class TypeQualifier(StrEnum):
|
6
|
+
Const = "const"
|
7
|
+
QFree = "qfree"
|
8
|
+
Quantum = "quantum"
|
9
|
+
Inferred = "inferred"
|
10
|
+
|
11
|
+
def to_modifier(self) -> "TypeModifier":
|
12
|
+
if self is TypeQualifier.Const:
|
13
|
+
return TypeModifier.Const
|
14
|
+
elif self is TypeQualifier.QFree:
|
15
|
+
return TypeModifier.Permutable
|
16
|
+
elif self is TypeQualifier.Quantum:
|
17
|
+
return TypeModifier.Mutable
|
18
|
+
elif self is TypeQualifier.Inferred:
|
19
|
+
return TypeModifier.Inferred
|
20
|
+
else:
|
21
|
+
raise ClassiqInternalExpansionError(f"Unexpected type qualifier: {self}")
|
22
|
+
|
23
|
+
|
24
|
+
class TypeModifier(StrEnum):
|
25
|
+
Const = "const"
|
26
|
+
Permutable = "permutable"
|
27
|
+
Mutable = "mutable"
|
28
|
+
Inferred = "inferred"
|
29
|
+
|
30
|
+
@staticmethod
|
31
|
+
def and_(first: "TypeModifier", second: "TypeModifier") -> "TypeModifier":
|
32
|
+
if second is TypeModifier.Inferred:
|
33
|
+
raise ClassiqInternalExpansionError
|
34
|
+
if first is TypeModifier.Mutable or second is TypeModifier.Mutable:
|
35
|
+
return TypeModifier.Mutable
|
36
|
+
elif first is TypeModifier.Permutable or second is TypeModifier.Permutable:
|
37
|
+
return TypeModifier.Permutable
|
38
|
+
else:
|
39
|
+
if first is not TypeModifier.Const and second is not TypeModifier.Const:
|
40
|
+
raise ClassiqInternalExpansionError("Unexpected type modifiers")
|
41
|
+
return TypeModifier.Const
|
@@ -202,8 +202,8 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
202
202
|
@property
|
203
203
|
def name(self) -> str:
|
204
204
|
generated_name = self.generated_function.name if self.generated_function else ""
|
205
|
-
# Temp fix for
|
206
|
-
if generated_name
|
205
|
+
# Temp fix for remaining old "supported" statements - power
|
206
|
+
if generated_name == StatementType.POWER:
|
207
207
|
return generated_name
|
208
208
|
|
209
209
|
back_ref = self.first_back_ref
|
@@ -243,8 +243,8 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
243
243
|
|
244
244
|
@property
|
245
245
|
def level(self) -> OperationLevel:
|
246
|
-
# Temp fix for
|
247
|
-
if self.name
|
246
|
+
# Temp fix for remaining old "supported" statements - power
|
247
|
+
if self.name == StatementType.POWER:
|
248
248
|
return OperationLevel.QMOD_STATEMENT
|
249
249
|
|
250
250
|
if self.first_back_ref is None:
|
@@ -275,15 +275,12 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
275
275
|
|
276
276
|
@property
|
277
277
|
def control_qubits(self) -> tuple[int, ...]:
|
278
|
-
control_states_names = {
|
279
|
-
control_state.name for control_state in self.control_states
|
280
|
-
}
|
281
278
|
return tuple(
|
282
279
|
qubit
|
283
280
|
for register in self.registers
|
284
281
|
for qubit in register.qubit_indexes_absolute
|
285
282
|
if register.role is RegisterRole.INPUT
|
286
|
-
and register.name
|
283
|
+
and register.name == self.control_variable
|
287
284
|
)
|
288
285
|
|
289
286
|
def propagate_absolute_qubits(self) -> "FunctionDebugInfoInterface":
|
@@ -11,6 +11,9 @@ from classiq.interface.generator.types.qstruct_declaration import QStructDeclara
|
|
11
11
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
12
12
|
from classiq.interface.helpers.validation_helpers import is_list_unique
|
13
13
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
14
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
15
|
+
ClassicalParameterDeclaration,
|
16
|
+
)
|
14
17
|
from classiq.interface.model.quantum_type import RegisterQuantumTypeDict
|
15
18
|
|
16
19
|
TYPE_LIBRARY_DUPLICATED_TYPE_NAMES = (
|
@@ -71,3 +74,8 @@ class ExecutionModel(ClassiqBaseModel):
|
|
71
74
|
register_filter_bitstrings: dict[str, list[str]] = pydantic.Field(
|
72
75
|
default_factory=dict,
|
73
76
|
)
|
77
|
+
|
78
|
+
circuit_execution_params: dict[str, ClassicalParameterDeclaration] = pydantic.Field(
|
79
|
+
default_factory=dict,
|
80
|
+
description="Mapping between a execution parameter name and its declaration",
|
81
|
+
)
|
@@ -166,19 +166,6 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
166
166
|
with open(filename, "w") as file:
|
167
167
|
file.write(self.model_dump_json(indent=4))
|
168
168
|
|
169
|
-
@classmethod
|
170
|
-
def from_qprog(cls, qprog: "QuantumProgram") -> "QuantumProgram":
|
171
|
-
"""
|
172
|
-
Creates a `QuantumProgram` instance from a raw quantum program string.
|
173
|
-
|
174
|
-
Args:
|
175
|
-
qprog: The raw quantum program in string format.
|
176
|
-
|
177
|
-
Returns:
|
178
|
-
QuantumProgram: The `QuantumProgram` instance.
|
179
|
-
"""
|
180
|
-
return qprog
|
181
|
-
|
182
169
|
@property
|
183
170
|
def _can_use_transpiled_code(self) -> bool:
|
184
171
|
return self.data.execution_data is None
|
@@ -8,7 +8,7 @@ class CompilationMetadata(BaseModel):
|
|
8
8
|
unchecked: list[str] = Field(default_factory=list)
|
9
9
|
atomic_qualifiers: list[str] = Field(
|
10
10
|
default_factory=list, exclude=True
|
11
|
-
) # TODO remove after deprecation https://classiq.atlassian.net/browse/CLS-2671
|
11
|
+
) # TODO remove after deprecation https://classiq.atlassian.net/browse/CLS-2671
|
12
12
|
|
13
13
|
@property
|
14
14
|
def occupation_number(self) -> NonNegativeInt:
|
@@ -5,7 +5,7 @@ from classiq.interface.ast_node import ASTNode
|
|
5
5
|
from classiq.interface.debug_info.debug_info import DebugInfoCollection
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
7
7
|
from classiq.interface.generator.functions.classical_type import ClassicalType
|
8
|
-
from classiq.interface.generator.functions.
|
8
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
9
9
|
from classiq.interface.generator.visitor import Transformer, Visitor
|
10
10
|
from classiq.interface.model.model import Model
|
11
11
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
@@ -32,7 +32,7 @@ class ModelNormalizer(Visitor):
|
|
32
32
|
expr.expr = ast.unparse(ExprNormalizer().visit(ast.parse(expr.expr)))
|
33
33
|
|
34
34
|
def visit_AnonPortDeclaration(self, decl: AnonPortDeclaration) -> None:
|
35
|
-
decl.
|
35
|
+
decl.type_modifier = TypeModifier.Mutable
|
36
36
|
|
37
37
|
|
38
38
|
class ClearModelInternals(Transformer):
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any, Literal
|
1
|
+
from typing import Any, Literal, Optional
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
from pydantic_core.core_schema import ValidationInfo
|
@@ -8,7 +8,10 @@ from classiq.interface.generator.functions.concrete_types import ConcreteQuantum
|
|
8
8
|
from classiq.interface.generator.functions.port_declaration import (
|
9
9
|
PortDeclarationDirection,
|
10
10
|
)
|
11
|
-
from classiq.interface.generator.functions.
|
11
|
+
from classiq.interface.generator.functions.type_modifier import (
|
12
|
+
TypeModifier,
|
13
|
+
TypeQualifier,
|
14
|
+
)
|
12
15
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
13
16
|
from classiq.interface.model.parameter import Parameter
|
14
17
|
|
@@ -16,14 +19,35 @@ from classiq.interface.model.parameter import Parameter
|
|
16
19
|
class AnonPortDeclaration(Parameter):
|
17
20
|
quantum_type: ConcreteQuantumType
|
18
21
|
direction: PortDeclarationDirection
|
19
|
-
type_qualifier: TypeQualifier
|
22
|
+
type_qualifier: Optional[TypeQualifier] = pydantic.Field(
|
23
|
+
default=None, exclude=True
|
24
|
+
) # TODO remove after BWC breaking release https://classiq.atlassian.net/browse/CLS-2777
|
20
25
|
kind: Literal["PortDeclaration"]
|
26
|
+
type_modifier: TypeModifier = pydantic.Field(default=None)
|
21
27
|
|
22
28
|
@pydantic.model_validator(mode="before")
|
23
29
|
@classmethod
|
24
30
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
25
31
|
return values_with_discriminator(values, "kind", "PortDeclaration")
|
26
32
|
|
33
|
+
@pydantic.model_validator(mode="before")
|
34
|
+
@classmethod
|
35
|
+
def _set_type_modifier(cls, values: Any) -> dict[str, Any]:
|
36
|
+
if values.get("type_modifier") is None:
|
37
|
+
type_qualifier = values.get("type_qualifier")
|
38
|
+
if type_qualifier is not None:
|
39
|
+
if isinstance(type_qualifier, TypeQualifier):
|
40
|
+
values["type_modifier"] = type_qualifier.to_modifier()
|
41
|
+
elif isinstance(type_qualifier, str):
|
42
|
+
values["type_modifier"] = TypeQualifier(
|
43
|
+
type_qualifier
|
44
|
+
).to_modifier()
|
45
|
+
else:
|
46
|
+
raise pydantic.ValidationError("Missing a type modifier")
|
47
|
+
else:
|
48
|
+
raise pydantic.ValidationError("Missing a type modifier")
|
49
|
+
return values
|
50
|
+
|
27
51
|
@pydantic.field_validator("direction", mode="before")
|
28
52
|
@classmethod
|
29
53
|
def _direction_validator(
|
@@ -10,6 +10,9 @@ from classiq.interface.exceptions import (
|
|
10
10
|
ClassiqExpansionError,
|
11
11
|
ClassiqInternalExpansionError,
|
12
12
|
)
|
13
|
+
from classiq.interface.generator.expressions.evaluated_expression import (
|
14
|
+
EvaluatedExpression,
|
15
|
+
)
|
13
16
|
from classiq.interface.generator.expressions.expression import Expression
|
14
17
|
from classiq.interface.generator.functions.classical_type import (
|
15
18
|
CLASSICAL_ATTRIBUTES_TYPES,
|
@@ -18,7 +21,7 @@ from classiq.interface.generator.functions.classical_type import (
|
|
18
21
|
from classiq.interface.generator.functions.port_declaration import (
|
19
22
|
PortDeclarationDirection,
|
20
23
|
)
|
21
|
-
from classiq.interface.generator.functions.
|
24
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
22
25
|
from classiq.interface.helpers.text_utils import are, readable_list, s, they
|
23
26
|
from classiq.interface.model.classical_parameter_declaration import (
|
24
27
|
ClassicalParameterDeclaration,
|
@@ -56,6 +59,14 @@ INITIALIZED_VAR_MESSAGE = "Variable '{}' should be uninitialized here"
|
|
56
59
|
UNINITIALIZED_VAR_MESSAGE = "Variable '{}' should be initialized here"
|
57
60
|
|
58
61
|
|
62
|
+
def _get_symbol_expr(symbol: str, classical_type: ClassicalType) -> Expression:
|
63
|
+
expr = Expression(expr=symbol)
|
64
|
+
expr._evaluated_expr = EvaluatedExpression(
|
65
|
+
value=classical_type.get_classical_proxy(handle=HandleBinding(name=symbol))
|
66
|
+
)
|
67
|
+
return expr
|
68
|
+
|
69
|
+
|
59
70
|
class PortDirection(StrEnum):
|
60
71
|
Input = "input"
|
61
72
|
Inout = "inout"
|
@@ -138,7 +149,7 @@ class _CapturedHandle(_Captured):
|
|
138
149
|
name=self.mangled_name,
|
139
150
|
quantum_type=self.quantum_type,
|
140
151
|
direction=self.direction.dump(),
|
141
|
-
|
152
|
+
type_modifier=TypeModifier.Inferred,
|
142
153
|
)
|
143
154
|
|
144
155
|
def is_same_var(self, other: "_CapturedHandle") -> bool:
|
@@ -556,24 +567,26 @@ class CapturedVars:
|
|
556
567
|
def get_captured_args(self, current_function: "FunctionClosure") -> list[ArgValue]:
|
557
568
|
args: list[ArgValue]
|
558
569
|
args = [
|
559
|
-
|
560
|
-
|
570
|
+
_get_symbol_expr(
|
571
|
+
(
|
561
572
|
captured_classical_var.name
|
562
573
|
if _same_closure(
|
563
574
|
current_function, captured_classical_var.defining_function
|
564
575
|
)
|
565
576
|
else captured_classical_var.mangled_name
|
566
|
-
)
|
577
|
+
),
|
578
|
+
captured_classical_var.classical_type,
|
567
579
|
)
|
568
580
|
for captured_classical_var in self._captured_classical_vars
|
569
581
|
]
|
570
582
|
args += [
|
571
|
-
|
572
|
-
|
583
|
+
_get_symbol_expr(
|
584
|
+
(
|
573
585
|
str(captured_qta.handle)
|
574
586
|
if _same_closure(current_function, captured_qta.defining_function)
|
575
587
|
else captured_qta.mangled_name
|
576
|
-
)
|
588
|
+
),
|
589
|
+
captured_qta.classical_type,
|
577
590
|
)
|
578
591
|
for captured_qta in self._captured_quantum_type_attributes
|
579
592
|
]
|
@@ -3,7 +3,7 @@ from collections.abc import Sequence
|
|
3
3
|
from classiq.interface.generator.functions.port_declaration import (
|
4
4
|
PortDeclarationDirection,
|
5
5
|
)
|
6
|
-
from classiq.interface.generator.functions.
|
6
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
7
7
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
8
8
|
from classiq.interface.model.quantum_function_declaration import AnonPositionalArg
|
9
9
|
from classiq.interface.model.quantum_type import QuantumNumeric
|
@@ -56,7 +56,7 @@ def handle_args_numeric_bounds(
|
|
56
56
|
|
57
57
|
if (
|
58
58
|
parameter.direction != PortDeclarationDirection.Output
|
59
|
-
and parameter.
|
59
|
+
and parameter.type_modifier != TypeModifier.Const
|
60
60
|
and isinstance(argument_as_quantum_symbol.quantum_type, QuantumNumeric)
|
61
61
|
):
|
62
62
|
argument_as_quantum_symbol.quantum_type.reset_bounds()
|
@@ -28,7 +28,7 @@ from classiq.interface.generator.expressions.proxies.classical.qmod_struct_insta
|
|
28
28
|
from classiq.interface.generator.functions.port_declaration import (
|
29
29
|
PortDeclarationDirection,
|
30
30
|
)
|
31
|
-
from classiq.interface.generator.functions.
|
31
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
32
32
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
33
33
|
from classiq.interface.helpers.backward_compatibility import zip_strict
|
34
34
|
from classiq.interface.helpers.text_utils import are, readable_list, s
|
@@ -80,8 +80,8 @@ from classiq.model_expansions.scope import (
|
|
80
80
|
QuantumVariable,
|
81
81
|
Scope,
|
82
82
|
)
|
83
|
-
from classiq.model_expansions.transformers.
|
84
|
-
|
83
|
+
from classiq.model_expansions.transformers.type_modifier_inference import (
|
84
|
+
TypeModifierValidation,
|
85
85
|
)
|
86
86
|
from classiq.model_expansions.transformers.var_splitter import VarSplitter
|
87
87
|
from classiq.qmod.pretty_print.expression_to_python import transform_expression
|
@@ -291,7 +291,7 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
291
291
|
context = self._expand_operation(function)
|
292
292
|
function_context = cast(FunctionContext, context)
|
293
293
|
function_def = self._create_function_definition(function_context, args)
|
294
|
-
self.
|
294
|
+
self._validate_type_modifiers(function_context, function_def)
|
295
295
|
self._expanded_functions[cache_key] = function_def
|
296
296
|
self._top_level_scope[function_def.name] = Evaluated(
|
297
297
|
value=function_context.closure.with_new_declaration(function_def)
|
@@ -415,29 +415,29 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
415
415
|
if var_state and param.direction == PortDeclarationDirection.Output:
|
416
416
|
raise ClassiqExpansionError(INITIALIZED_VAR_MESSAGE.format(var_name))
|
417
417
|
|
418
|
-
def
|
418
|
+
def _validate_type_modifiers(
|
419
419
|
self, func_context: FunctionContext, func_def: NativeFunctionDefinition
|
420
420
|
) -> None:
|
421
|
-
if self.
|
422
|
-
self.
|
421
|
+
if self._should_override_type_modifiers(func_context):
|
422
|
+
self._override_type_modifiers(func_def)
|
423
423
|
|
424
424
|
unchecked = self._functions_compilation_metadata.get(
|
425
425
|
func_context.name, CompilationMetadata()
|
426
426
|
).unchecked
|
427
|
-
|
427
|
+
TypeModifierValidation(
|
428
428
|
skip_validation=self._interpreter.skip_type_modifier_validation
|
429
429
|
).run(func_def.port_declarations, func_def.body, unchecked)
|
430
430
|
|
431
431
|
@staticmethod
|
432
|
-
def
|
432
|
+
def _should_override_type_modifiers(func_context: FunctionContext) -> bool:
|
433
433
|
"""
|
434
|
-
The type
|
434
|
+
The type modifier can be changed according to the operand passed to the
|
435
435
|
function. For example,
|
436
|
-
apply_to_all(X, q) --> q will be
|
436
|
+
apply_to_all(X, q) --> q will be Permutable after expansion
|
437
437
|
apply_to_all(H, q) --> q will be Quantum after expansion
|
438
438
|
This also holds for the intermediate lambda created during the expansion.
|
439
439
|
|
440
|
-
We don't override the type
|
440
|
+
We don't override the type modifier if it's explicitly specified (Permutable or
|
441
441
|
Const), neither in the function declaration nor in the operand declaration.
|
442
442
|
"""
|
443
443
|
|
@@ -461,8 +461,8 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
461
461
|
)
|
462
462
|
|
463
463
|
@staticmethod
|
464
|
-
def
|
465
|
-
# only override the
|
464
|
+
def _override_type_modifiers(func_def: NativeFunctionDefinition) -> None:
|
465
|
+
# only override the modifier if it's unspecified (not Permutable or Const)
|
466
466
|
for port in func_def.port_declarations:
|
467
|
-
if port.
|
468
|
-
port.
|
467
|
+
if port.type_modifier is TypeModifier.Mutable:
|
468
|
+
port.type_modifier = TypeModifier.Inferred
|
@@ -6,7 +6,13 @@ from functools import cmp_to_key
|
|
6
6
|
from typing import TypeVar, cast
|
7
7
|
|
8
8
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
9
|
+
from classiq.interface.generator.expressions.evaluated_expression import (
|
10
|
+
EvaluatedExpression,
|
11
|
+
)
|
9
12
|
from classiq.interface.generator.expressions.expression import Expression
|
13
|
+
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
14
|
+
AnyClassicalValue,
|
15
|
+
)
|
10
16
|
from classiq.interface.generator.visitor import NodeType
|
11
17
|
from classiq.interface.model.handle_binding import HandleBinding
|
12
18
|
from classiq.interface.model.model_visitor import ModelTransformer
|
@@ -99,7 +105,10 @@ def _rewrite_expression(
|
|
99
105
|
new_expr_str = _replace_full_word(str(handle), str(new_handle), new_expr_str)
|
100
106
|
|
101
107
|
new_expr = Expression(expr=new_expr_str)
|
102
|
-
|
108
|
+
if not new_expr.is_evaluated():
|
109
|
+
new_expr._evaluated_expr = EvaluatedExpression(
|
110
|
+
value=AnyClassicalValue(new_expr_str)
|
111
|
+
)
|
103
112
|
return new_expr
|
104
113
|
|
105
114
|
|