bloqade-circuit 0.1.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.
Potentially problematic release.
This version of bloqade-circuit might be problematic. Click here for more details.
- bloqade/analysis/__init__.py +0 -0
- bloqade/analysis/address/__init__.py +11 -0
- bloqade/analysis/address/analysis.py +60 -0
- bloqade/analysis/address/impls.py +228 -0
- bloqade/analysis/address/lattice.py +85 -0
- bloqade/noise/__init__.py +1 -0
- bloqade/noise/native/__init__.py +20 -0
- bloqade/noise/native/_dialect.py +3 -0
- bloqade/noise/native/_wrappers.py +34 -0
- bloqade/noise/native/model.py +347 -0
- bloqade/noise/native/rewrite.py +35 -0
- bloqade/noise/native/stmts.py +46 -0
- bloqade/pyqrack/__init__.py +18 -0
- bloqade/pyqrack/base.py +131 -0
- bloqade/pyqrack/noise/__init__.py +0 -0
- bloqade/pyqrack/noise/native.py +100 -0
- bloqade/pyqrack/qasm2/__init__.py +0 -0
- bloqade/pyqrack/qasm2/core.py +79 -0
- bloqade/pyqrack/qasm2/parallel.py +46 -0
- bloqade/pyqrack/qasm2/uop.py +247 -0
- bloqade/pyqrack/reg.py +109 -0
- bloqade/pyqrack/target.py +112 -0
- bloqade/qasm2/__init__.py +19 -0
- bloqade/qasm2/_wrappers.py +674 -0
- bloqade/qasm2/dialects/__init__.py +10 -0
- bloqade/qasm2/dialects/core/__init__.py +3 -0
- bloqade/qasm2/dialects/core/_dialect.py +3 -0
- bloqade/qasm2/dialects/core/_emit.py +68 -0
- bloqade/qasm2/dialects/core/_typeinfer.py +23 -0
- bloqade/qasm2/dialects/core/address.py +38 -0
- bloqade/qasm2/dialects/core/stmts.py +94 -0
- bloqade/qasm2/dialects/expr/__init__.py +3 -0
- bloqade/qasm2/dialects/expr/_dialect.py +3 -0
- bloqade/qasm2/dialects/expr/_emit.py +103 -0
- bloqade/qasm2/dialects/expr/_from_python.py +86 -0
- bloqade/qasm2/dialects/expr/_interp.py +75 -0
- bloqade/qasm2/dialects/expr/stmts.py +262 -0
- bloqade/qasm2/dialects/glob.py +45 -0
- bloqade/qasm2/dialects/indexing.py +64 -0
- bloqade/qasm2/dialects/inline.py +76 -0
- bloqade/qasm2/dialects/noise.py +16 -0
- bloqade/qasm2/dialects/parallel.py +110 -0
- bloqade/qasm2/dialects/uop/__init__.py +4 -0
- bloqade/qasm2/dialects/uop/_dialect.py +3 -0
- bloqade/qasm2/dialects/uop/_emit.py +211 -0
- bloqade/qasm2/dialects/uop/schedule.py +89 -0
- bloqade/qasm2/dialects/uop/stmts.py +325 -0
- bloqade/qasm2/emit/__init__.py +1 -0
- bloqade/qasm2/emit/base.py +72 -0
- bloqade/qasm2/emit/gate.py +102 -0
- bloqade/qasm2/emit/main.py +106 -0
- bloqade/qasm2/emit/target.py +165 -0
- bloqade/qasm2/glob.py +24 -0
- bloqade/qasm2/groups.py +120 -0
- bloqade/qasm2/parallel.py +48 -0
- bloqade/qasm2/parse/__init__.py +37 -0
- bloqade/qasm2/parse/ast.py +235 -0
- bloqade/qasm2/parse/build.py +289 -0
- bloqade/qasm2/parse/lowering.py +553 -0
- bloqade/qasm2/parse/parser.py +5 -0
- bloqade/qasm2/parse/print.py +293 -0
- bloqade/qasm2/parse/qasm2.lark +75 -0
- bloqade/qasm2/parse/visitor.py +16 -0
- bloqade/qasm2/parse/visitor.pyi +39 -0
- bloqade/qasm2/passes/__init__.py +5 -0
- bloqade/qasm2/passes/fold.py +94 -0
- bloqade/qasm2/passes/glob.py +119 -0
- bloqade/qasm2/passes/noise.py +61 -0
- bloqade/qasm2/passes/parallel.py +176 -0
- bloqade/qasm2/passes/py2qasm.py +63 -0
- bloqade/qasm2/passes/qasm2py.py +61 -0
- bloqade/qasm2/rewrite/__init__.py +12 -0
- bloqade/qasm2/rewrite/desugar.py +28 -0
- bloqade/qasm2/rewrite/glob.py +103 -0
- bloqade/qasm2/rewrite/heuristic_noise.py +247 -0
- bloqade/qasm2/rewrite/native_gates.py +447 -0
- bloqade/qasm2/rewrite/parallel_to_uop.py +83 -0
- bloqade/qasm2/rewrite/register.py +45 -0
- bloqade/qasm2/rewrite/uop_to_parallel.py +395 -0
- bloqade/qasm2/types.py +39 -0
- bloqade/qbraid/__init__.py +2 -0
- bloqade/qbraid/lowering.py +324 -0
- bloqade/qbraid/schema.py +252 -0
- bloqade/qbraid/simulation_result.py +99 -0
- bloqade/qbraid/target.py +86 -0
- bloqade/squin/__init__.py +2 -0
- bloqade/squin/analysis/__init__.py +0 -0
- bloqade/squin/analysis/nsites/__init__.py +8 -0
- bloqade/squin/analysis/nsites/analysis.py +52 -0
- bloqade/squin/analysis/nsites/impls.py +69 -0
- bloqade/squin/analysis/nsites/lattice.py +49 -0
- bloqade/squin/analysis/schedule.py +244 -0
- bloqade/squin/groups.py +38 -0
- bloqade/squin/op/__init__.py +132 -0
- bloqade/squin/op/_dialect.py +3 -0
- bloqade/squin/op/complex.py +6 -0
- bloqade/squin/op/stmts.py +220 -0
- bloqade/squin/op/traits.py +43 -0
- bloqade/squin/op/types.py +10 -0
- bloqade/squin/qubit.py +118 -0
- bloqade/squin/wire.py +103 -0
- bloqade/stim/__init__.py +6 -0
- bloqade/stim/_wrappers.py +186 -0
- bloqade/stim/dialects/__init__.py +5 -0
- bloqade/stim/dialects/aux/__init__.py +11 -0
- bloqade/stim/dialects/aux/_dialect.py +3 -0
- bloqade/stim/dialects/aux/emit.py +102 -0
- bloqade/stim/dialects/aux/interp.py +39 -0
- bloqade/stim/dialects/aux/lowering.py +40 -0
- bloqade/stim/dialects/aux/stmts/__init__.py +14 -0
- bloqade/stim/dialects/aux/stmts/annotate.py +47 -0
- bloqade/stim/dialects/aux/stmts/const.py +95 -0
- bloqade/stim/dialects/aux/types.py +19 -0
- bloqade/stim/dialects/collapse/__init__.py +3 -0
- bloqade/stim/dialects/collapse/_dialect.py +3 -0
- bloqade/stim/dialects/collapse/emit.py +68 -0
- bloqade/stim/dialects/collapse/stmts/__init__.py +3 -0
- bloqade/stim/dialects/collapse/stmts/measure.py +45 -0
- bloqade/stim/dialects/collapse/stmts/pp_measure.py +14 -0
- bloqade/stim/dialects/collapse/stmts/reset.py +26 -0
- bloqade/stim/dialects/gate/__init__.py +3 -0
- bloqade/stim/dialects/gate/_dialect.py +3 -0
- bloqade/stim/dialects/gate/emit.py +87 -0
- bloqade/stim/dialects/gate/stmts/__init__.py +14 -0
- bloqade/stim/dialects/gate/stmts/base.py +31 -0
- bloqade/stim/dialects/gate/stmts/clifford_1q.py +53 -0
- bloqade/stim/dialects/gate/stmts/clifford_2q.py +11 -0
- bloqade/stim/dialects/gate/stmts/control_2q.py +21 -0
- bloqade/stim/dialects/gate/stmts/pp.py +15 -0
- bloqade/stim/dialects/noise/__init__.py +3 -0
- bloqade/stim/dialects/noise/_dialect.py +3 -0
- bloqade/stim/dialects/noise/emit.py +66 -0
- bloqade/stim/dialects/noise/stmts.py +77 -0
- bloqade/stim/emit/__init__.py +1 -0
- bloqade/stim/emit/stim.py +54 -0
- bloqade/stim/groups.py +26 -0
- bloqade/test_utils.py +35 -0
- bloqade/types.py +24 -0
- bloqade/visual/__init__.py +1 -0
- bloqade/visual/animation/__init__.py +0 -0
- bloqade/visual/animation/animate.py +267 -0
- bloqade/visual/animation/base.py +346 -0
- bloqade/visual/animation/gate_event.py +24 -0
- bloqade/visual/animation/runtime/__init__.py +0 -0
- bloqade/visual/animation/runtime/aod.py +36 -0
- bloqade/visual/animation/runtime/atoms.py +55 -0
- bloqade/visual/animation/runtime/ppoly.py +50 -0
- bloqade/visual/animation/runtime/qpustate.py +119 -0
- bloqade/visual/animation/runtime/utils.py +43 -0
- bloqade_circuit-0.1.0.dist-info/METADATA +70 -0
- bloqade_circuit-0.1.0.dist-info/RECORD +153 -0
- bloqade_circuit-0.1.0.dist-info/WHEEL +4 -0
- bloqade_circuit-0.1.0.dist-info/licenses/LICENSE +234 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Union, Literal
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Node:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class Header(Node):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Kirin(Header):
|
|
19
|
+
dialects: list[str]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class OPENQASM(Header):
|
|
24
|
+
version: Version
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class MainProgram(Node):
|
|
29
|
+
header: Kirin | OPENQASM
|
|
30
|
+
statements: list[Statement]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class Version(Node):
|
|
35
|
+
major: int
|
|
36
|
+
minor: int
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class Statement(Node):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class Comment(Statement):
|
|
46
|
+
text: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class QReg(Statement):
|
|
51
|
+
name: str
|
|
52
|
+
size: int
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class CReg(Statement):
|
|
57
|
+
name: str
|
|
58
|
+
size: int
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class Gate(Statement):
|
|
63
|
+
name: str
|
|
64
|
+
cparams: list[str]
|
|
65
|
+
qparams: list[str]
|
|
66
|
+
body: list[UOp | Barrier]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass
|
|
70
|
+
class Opaque(Statement):
|
|
71
|
+
name: str
|
|
72
|
+
cparams: list[Expr]
|
|
73
|
+
qparams: list[Bit | Name]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class QOp(Statement):
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass
|
|
82
|
+
class IfStmt(Statement):
|
|
83
|
+
cond: Cmp
|
|
84
|
+
body: list[QOp]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class Barrier(Statement):
|
|
89
|
+
qargs: list[Bit | Name]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass
|
|
93
|
+
class Include(Statement):
|
|
94
|
+
filename: str
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass
|
|
98
|
+
class Measure(QOp):
|
|
99
|
+
qarg: Bit | Name
|
|
100
|
+
carg: Bit | Name
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dataclass
|
|
104
|
+
class Reset(QOp):
|
|
105
|
+
qarg: Bit | Name
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass
|
|
109
|
+
class UOp(QOp):
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass
|
|
114
|
+
class Instruction(UOp):
|
|
115
|
+
name: Name
|
|
116
|
+
params: list[Expr]
|
|
117
|
+
qargs: list[Bit | Name]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass
|
|
121
|
+
class UGate(UOp):
|
|
122
|
+
theta: Expr
|
|
123
|
+
phi: Expr
|
|
124
|
+
lam: Expr
|
|
125
|
+
qarg: Bit | Name
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@dataclass
|
|
129
|
+
class CXGate(UOp):
|
|
130
|
+
ctrl: Bit | Name
|
|
131
|
+
qarg: Bit | Name
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass
|
|
135
|
+
class Extension(UOp):
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass
|
|
140
|
+
class ParallelQArgs(Extension):
|
|
141
|
+
qargs: list[tuple[Bit | Name, ...]]
|
|
142
|
+
|
|
143
|
+
def __iter__(self):
|
|
144
|
+
return iter(self.qargs)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dataclass
|
|
148
|
+
class GlobUGate(Extension):
|
|
149
|
+
registers: list[Name]
|
|
150
|
+
theta: Expr
|
|
151
|
+
phi: Expr
|
|
152
|
+
lam: Expr
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@dataclass
|
|
156
|
+
class NoisePAULI1(Extension):
|
|
157
|
+
px: Expr
|
|
158
|
+
py: Expr
|
|
159
|
+
pz: Expr
|
|
160
|
+
qarg: Bit | Name
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass
|
|
164
|
+
class ParaU3Gate(Extension):
|
|
165
|
+
theta: Expr
|
|
166
|
+
phi: Expr
|
|
167
|
+
lam: Expr
|
|
168
|
+
qargs: ParallelQArgs
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass
|
|
172
|
+
class ParaRZGate(Extension):
|
|
173
|
+
theta: Expr
|
|
174
|
+
qargs: ParallelQArgs
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass
|
|
178
|
+
class ParaCZGate(Extension):
|
|
179
|
+
qargs: ParallelQArgs
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@dataclass
|
|
183
|
+
class Expr(Node):
|
|
184
|
+
pass
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@dataclass
|
|
188
|
+
class BinOp(Expr):
|
|
189
|
+
op: Literal["+", "-", "*", "/", "^"]
|
|
190
|
+
lhs: Expr
|
|
191
|
+
rhs: Expr
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@dataclass
|
|
195
|
+
class Cmp(Statement):
|
|
196
|
+
lhs: Expr
|
|
197
|
+
rhs: Expr
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@dataclass
|
|
201
|
+
class UnaryOp(Expr):
|
|
202
|
+
op: Literal["-", "+"]
|
|
203
|
+
operand: Expr
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@dataclass
|
|
207
|
+
class Call(Expr):
|
|
208
|
+
name: Literal["sin", "cos", "tan", "exp", "ln", "sqrt"]
|
|
209
|
+
args: list[Expr]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@dataclass
|
|
213
|
+
class Constant(Expr):
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@dataclass
|
|
218
|
+
class Number(Constant):
|
|
219
|
+
value: Union[int, float]
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@dataclass
|
|
223
|
+
class Pi(Constant):
|
|
224
|
+
pass
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@dataclass
|
|
228
|
+
class Name(Expr):
|
|
229
|
+
id: str
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@dataclass
|
|
233
|
+
class Bit(Expr):
|
|
234
|
+
name: Name
|
|
235
|
+
addr: int
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# type: ignore
|
|
2
|
+
from lark import Token
|
|
3
|
+
from lark.tree import ParseTree
|
|
4
|
+
|
|
5
|
+
from . import ast
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BuildError(Exception):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Build:
|
|
13
|
+
|
|
14
|
+
def build(self, tree: ParseTree) -> ast.Node:
|
|
15
|
+
return getattr(self, f"build_{tree.data}", self.build_generic)(tree)
|
|
16
|
+
|
|
17
|
+
def build_generic(self, tree: ParseTree) -> ast.Node:
|
|
18
|
+
raise NotImplementedError(f"No build_{tree.data} method")
|
|
19
|
+
|
|
20
|
+
def build_mainprogram(self, tree: ParseTree) -> ast.MainProgram:
|
|
21
|
+
header = self.build(tree.children[0])
|
|
22
|
+
return ast.MainProgram(
|
|
23
|
+
header=header,
|
|
24
|
+
statements=[self.build(stmt) for stmt in tree.children[1:]],
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def build_openqasm(self, tree: ParseTree) -> ast.OPENQASM:
|
|
28
|
+
return ast.OPENQASM(version=self.build(tree.children[0]))
|
|
29
|
+
|
|
30
|
+
def build_kirin(self, tree: ParseTree) -> ast.Kirin:
|
|
31
|
+
return ast.Kirin(dialects=[self.build_dialect(each) for each in tree.children])
|
|
32
|
+
|
|
33
|
+
def build_dialect(self, tree: ParseTree) -> str:
|
|
34
|
+
return ".".join(each.value for each in tree.children)
|
|
35
|
+
|
|
36
|
+
def build_version(self, tree: ParseTree) -> ast.Version:
|
|
37
|
+
return ast.Version(
|
|
38
|
+
int(tree.children[0].value),
|
|
39
|
+
int(tree.children[1].value),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def build_include(self, tree: ParseTree) -> ast.Include:
|
|
43
|
+
return ast.Include(filename=tree.children[0].value[1:-1])
|
|
44
|
+
|
|
45
|
+
def build_qreg(self, tree: ParseTree) -> ast.QReg:
|
|
46
|
+
return ast.QReg(name=tree.children[0].value, size=int(tree.children[1].value))
|
|
47
|
+
|
|
48
|
+
def build_creg(self, tree: ParseTree) -> ast.CReg:
|
|
49
|
+
return ast.CReg(name=tree.children[0].value, size=int(tree.children[1].value))
|
|
50
|
+
|
|
51
|
+
def build_cx_gate(self, tree: ParseTree) -> ast.Gate:
|
|
52
|
+
return ast.CXGate(
|
|
53
|
+
self.build_bit(tree.children[0]), self.build_bit(tree.children[1])
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def build_ugate(self, tree: ParseTree) -> ast.Gate:
|
|
57
|
+
return ast.UGate(
|
|
58
|
+
theta=self.build_expr(tree.children[0]),
|
|
59
|
+
phi=self.build_expr(tree.children[1]),
|
|
60
|
+
lam=self.build_expr(tree.children[2]),
|
|
61
|
+
qarg=self.build_bit(tree.children[3]),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def build_barrier(self, tree: ParseTree) -> ast.Barrier:
|
|
65
|
+
return ast.Barrier(qargs=self.build(tree.children[0]))
|
|
66
|
+
|
|
67
|
+
def build_inst(self, tree: ParseTree) -> ast.Instruction:
|
|
68
|
+
if tree.children[1] is None:
|
|
69
|
+
params = []
|
|
70
|
+
else:
|
|
71
|
+
params = self.build(tree.children[1])
|
|
72
|
+
return ast.Instruction(
|
|
73
|
+
name=ast.Name(tree.children[0].value),
|
|
74
|
+
params=params,
|
|
75
|
+
qargs=self.build(tree.children[2]),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def build_opaque(self, tree: ParseTree) -> ast.Opaque:
|
|
79
|
+
return ast.Opaque(
|
|
80
|
+
name=tree.children[0].value,
|
|
81
|
+
cparams=self.build(tree.children[1]) if tree.children[1] else [],
|
|
82
|
+
qparams=self.build(tree.children[2]) if tree.children[2] else [],
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def build_gate(self, tree: ParseTree) -> ast.Gate:
|
|
86
|
+
cparams = tree.children[1]
|
|
87
|
+
qparams = tree.children[2]
|
|
88
|
+
return ast.Gate(
|
|
89
|
+
name=tree.children[0].value,
|
|
90
|
+
cparams=self.build(cparams) if cparams else [],
|
|
91
|
+
qparams=self.build(qparams) if qparams else [],
|
|
92
|
+
body=[self.build(stmt) for stmt in tree.children[3:]],
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def build_noise_pauli1(self, tree: ParseTree) -> ast.NoisePAULI1:
|
|
96
|
+
return ast.NoisePAULI1(
|
|
97
|
+
px=self.build_expr(tree.children[0]),
|
|
98
|
+
py=self.build_expr(tree.children[1]),
|
|
99
|
+
pz=self.build_expr(tree.children[2]),
|
|
100
|
+
qarg=self.build_bit(tree.children[3]),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def build_glob_u_gate(self, tree: ParseTree) -> ast.GlobUGate:
|
|
104
|
+
return ast.GlobUGate(
|
|
105
|
+
[self.build_bit(each) for each in tree.children[3].children],
|
|
106
|
+
self.build_expr(tree.children[0]),
|
|
107
|
+
self.build_expr(tree.children[1]),
|
|
108
|
+
self.build_expr(tree.children[2]),
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def build_para_u_gate(self, tree: ParseTree) -> ast.ParaU3Gate:
|
|
112
|
+
return ast.ParaU3Gate(
|
|
113
|
+
self.build_expr(tree.children[0]),
|
|
114
|
+
self.build_expr(tree.children[1]),
|
|
115
|
+
self.build_expr(tree.children[2]),
|
|
116
|
+
self.build_parallel_body(tree.children[3]),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
def build_para_cz_gate(self, tree: ParseTree) -> ast.ParaCZGate:
|
|
120
|
+
return ast.ParaCZGate(
|
|
121
|
+
self.build_parallel_body(tree.children[0]),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def build_para_rz_gate(self, tree: ParseTree) -> ast.ParaRZGate:
|
|
125
|
+
return ast.ParaRZGate(
|
|
126
|
+
self.build_expr(tree.children[0]),
|
|
127
|
+
self.build_parallel_body(tree.children[1]),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def build_parallel_body(self, tree: ParseTree) -> ast.ParallelQArgs:
|
|
131
|
+
return ast.ParallelQArgs([self.build_task_args(each) for each in tree.children])
|
|
132
|
+
|
|
133
|
+
def build_task_args(self, tree: ParseTree) -> tuple[ast.Bit | ast.Name, ...]:
|
|
134
|
+
return tuple(self.build(each) for each in tree.children)
|
|
135
|
+
|
|
136
|
+
def build_measure(self, tree: ParseTree) -> ast.Measure:
|
|
137
|
+
return ast.Measure(
|
|
138
|
+
qarg=self.build_bit(tree.children[0]),
|
|
139
|
+
carg=self.build_bit(tree.children[1]),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def build_reset(self, tree: ParseTree) -> ast.Reset:
|
|
143
|
+
return ast.Reset(qarg=self.build_bit(tree.children[0]))
|
|
144
|
+
|
|
145
|
+
def build_ifstmt(self, tree: ParseTree) -> ast.IfStmt:
|
|
146
|
+
return ast.IfStmt(
|
|
147
|
+
cond=ast.Cmp(
|
|
148
|
+
lhs=self.build_expr(tree.children[0]),
|
|
149
|
+
rhs=self.build_expr(tree.children[1]),
|
|
150
|
+
),
|
|
151
|
+
body=self.build(tree.children[2]),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def build_ifbody(self, tree: ParseTree) -> list[ast.Node]:
|
|
155
|
+
return [self.build(stmt) for stmt in tree.children]
|
|
156
|
+
|
|
157
|
+
def build_qparams(self, tree: ParseTree) -> list[ast.Expr]:
|
|
158
|
+
return [param.value for param in tree.children]
|
|
159
|
+
|
|
160
|
+
def build_cparams(self, tree: ParseTree) -> list[ast.Expr]:
|
|
161
|
+
return [param.value for param in tree.children]
|
|
162
|
+
|
|
163
|
+
def build_qubits(self, tree: ParseTree) -> list[ast.Bit]:
|
|
164
|
+
return [self.build_bit(qubit) for qubit in tree.children]
|
|
165
|
+
|
|
166
|
+
def build_bit(self, tree: ParseTree) -> ast.Name | ast.Bit:
|
|
167
|
+
if isinstance(tree, Token) and tree.type == "IDENTIFIER":
|
|
168
|
+
return ast.Name(tree.value)
|
|
169
|
+
else:
|
|
170
|
+
return ast.Bit(
|
|
171
|
+
name=ast.Name(tree.children[0].value), addr=int(tree.children[1].value)
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
def build_params(self, tree: ParseTree) -> list[ast.Expr]:
|
|
175
|
+
return [self.build_expr(param) for param in tree.children]
|
|
176
|
+
|
|
177
|
+
def build_call(self, tree: ParseTree) -> ast.Call:
|
|
178
|
+
return ast.Call(
|
|
179
|
+
name=tree.children[0].value,
|
|
180
|
+
args=self.build(tree.children[1]),
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
def build_arglist(self, tree: ParseTree) -> list[ast.Expr]:
|
|
184
|
+
return [self.build_expr(arg) for arg in tree.children]
|
|
185
|
+
|
|
186
|
+
def build_expr(self, tree: ParseTree) -> ast.Expr:
|
|
187
|
+
if isinstance(tree, Token):
|
|
188
|
+
return self._build_token_expr(tree)
|
|
189
|
+
elif tree.data != "expr":
|
|
190
|
+
return self.build(tree)
|
|
191
|
+
|
|
192
|
+
if tree.children[1].type == "PLUS":
|
|
193
|
+
lhs = ast.BinOp(
|
|
194
|
+
op="+",
|
|
195
|
+
lhs=self.build_term(tree.children[0]),
|
|
196
|
+
rhs=self.build_term(tree.children[2]),
|
|
197
|
+
)
|
|
198
|
+
elif tree.children[1].type == "MINUS":
|
|
199
|
+
lhs = ast.BinOp(
|
|
200
|
+
op="-",
|
|
201
|
+
lhs=self.build_term(tree.children[0]),
|
|
202
|
+
rhs=self.build_term(tree.children[2]),
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
raise BuildError(f"Unsupported operator {tree.children[1].type}")
|
|
206
|
+
|
|
207
|
+
for i in range(3, len(tree.children), 2):
|
|
208
|
+
if tree.children[i].type == "PLUS":
|
|
209
|
+
lhs = ast.BinOp(
|
|
210
|
+
op="+",
|
|
211
|
+
lhs=lhs,
|
|
212
|
+
rhs=self.build_term(tree.children[i + 1]),
|
|
213
|
+
)
|
|
214
|
+
elif tree.children[i].type == "MINUS":
|
|
215
|
+
lhs = ast.BinOp(
|
|
216
|
+
op="-",
|
|
217
|
+
lhs=lhs,
|
|
218
|
+
rhs=self.build_term(tree.children[i + 1]),
|
|
219
|
+
)
|
|
220
|
+
else:
|
|
221
|
+
raise BuildError(f"Unsupported operator {tree.children[i].type}")
|
|
222
|
+
|
|
223
|
+
return lhs
|
|
224
|
+
|
|
225
|
+
def build_term(self, tree: ParseTree) -> ast.Expr:
|
|
226
|
+
if isinstance(tree, Token):
|
|
227
|
+
return self._build_token_expr(tree)
|
|
228
|
+
elif tree.data != "term":
|
|
229
|
+
return self.build(tree)
|
|
230
|
+
|
|
231
|
+
if tree.children[1].type == "TIMES":
|
|
232
|
+
lhs = ast.BinOp(
|
|
233
|
+
op="*",
|
|
234
|
+
lhs=self.build_factor(tree.children[0]),
|
|
235
|
+
rhs=self.build_factor(tree.children[2]),
|
|
236
|
+
)
|
|
237
|
+
elif tree.children[1].type == "DIVIDE":
|
|
238
|
+
lhs = ast.BinOp(
|
|
239
|
+
op="/",
|
|
240
|
+
lhs=self.build_factor(tree.children[0]),
|
|
241
|
+
rhs=self.build_factor(tree.children[2]),
|
|
242
|
+
)
|
|
243
|
+
else:
|
|
244
|
+
raise BuildError(f"Unsupported operator {tree.children[1].type}")
|
|
245
|
+
|
|
246
|
+
for i in range(3, len(tree.children), 2):
|
|
247
|
+
if tree.children[i].type == "TIMES":
|
|
248
|
+
lhs = ast.BinOp(
|
|
249
|
+
op="*",
|
|
250
|
+
lhs=lhs,
|
|
251
|
+
rhs=self.build_factor(tree.children[i + 1]),
|
|
252
|
+
)
|
|
253
|
+
elif tree.children[i].type == "DIVIDE":
|
|
254
|
+
lhs = ast.BinOp(
|
|
255
|
+
op="/",
|
|
256
|
+
lhs=lhs,
|
|
257
|
+
rhs=self.build_factor(tree.children[i + 1]),
|
|
258
|
+
)
|
|
259
|
+
else:
|
|
260
|
+
raise BuildError(f"Unsupported operator {tree.children[i].type}")
|
|
261
|
+
|
|
262
|
+
return lhs
|
|
263
|
+
|
|
264
|
+
def build_factor(self, tree: ParseTree) -> ast.Expr:
|
|
265
|
+
if isinstance(tree, Token):
|
|
266
|
+
return self._build_token_expr(tree)
|
|
267
|
+
elif tree.data != "factor":
|
|
268
|
+
return self.build(tree)
|
|
269
|
+
|
|
270
|
+
if tree.children[0].type == "PLUS":
|
|
271
|
+
return ast.UnaryOp(op="+", operand=self.build_expr(tree.children[1]))
|
|
272
|
+
elif tree.children[0].type == "MINUS":
|
|
273
|
+
return ast.UnaryOp(op="-", operand=self.build_expr(tree.children[1]))
|
|
274
|
+
else:
|
|
275
|
+
raise BuildError(f"Unsupported operator {tree.children[0].type}")
|
|
276
|
+
|
|
277
|
+
def _build_token_expr(self, token: Token) -> ast.Node:
|
|
278
|
+
if token.type == "NUMBER":
|
|
279
|
+
return ast.Number(float(token.value))
|
|
280
|
+
elif token.type == "IDENTIFIER":
|
|
281
|
+
return ast.Name(token.value)
|
|
282
|
+
elif token.type == "PI":
|
|
283
|
+
return ast.Pi()
|
|
284
|
+
elif token.type == "INT":
|
|
285
|
+
return ast.Number(int(token.value))
|
|
286
|
+
elif token.type == "FLOAT":
|
|
287
|
+
return ast.Number(float(token.value))
|
|
288
|
+
else:
|
|
289
|
+
raise BuildError(f"Unsupported token type {token.type}")
|