bloqade-circuit 0.4.1__py3-none-any.whl → 0.4.2__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.
@@ -2,9 +2,9 @@ from typing import Any
2
2
  from dataclasses import field, dataclass
3
3
 
4
4
  from kirin import ir, types, lowering
5
- from kirin.dialects import cf, func, ilist
5
+ from kirin.dialects import cf, scf, func, ilist
6
6
 
7
- from bloqade.qasm2.types import CRegType, QRegType
7
+ from bloqade.qasm2.types import CRegType, QRegType, QubitType
8
8
  from bloqade.qasm2.dialects import uop, core, expr, glob, noise, parallel
9
9
 
10
10
  from . import ast
@@ -101,6 +101,13 @@ class QASM2(lowering.LoweringABC[ast.Node]):
101
101
  def lower_global(
102
102
  self, state: lowering.State[ast.Node], node: ast.Node
103
103
  ) -> lowering.LoweringABC.Result:
104
+ if isinstance(node, ast.Name):
105
+ # NOTE: might be a lookup for a gate function invoke
106
+ try:
107
+ return lowering.LoweringABC.Result(state.current_frame.globals[node.id])
108
+ except KeyError:
109
+ pass
110
+
104
111
  raise lowering.BuildError("Global variables are not supported in QASM 2.0")
105
112
 
106
113
  def visit_MainProgram(self, state: lowering.State[ast.Node], node: ast.MainProgram):
@@ -171,7 +178,6 @@ class QASM2(lowering.LoweringABC[ast.Node]):
171
178
  def visit_Reset(self, state: lowering.State[ast.Node], node: ast.Reset):
172
179
  state.current_frame.push(core.Reset(qarg=state.lower(node.qarg).expect_one()))
173
180
 
174
- # TODO: clean this up? copied from cf dialect with a small modification
175
181
  def visit_IfStmt(self, state: lowering.State[ast.Node], node: ast.IfStmt):
176
182
  cond_stmt = core.CRegEq(
177
183
  lhs=state.lower(node.cond.lhs).expect_one(),
@@ -179,84 +185,23 @@ class QASM2(lowering.LoweringABC[ast.Node]):
179
185
  )
180
186
  cond = state.current_frame.push(cond_stmt).result
181
187
  frame = state.current_frame
182
- before_block = frame.curr_block
183
188
 
184
- with state.frame(node.body, region=frame.curr_region) as if_frame:
189
+ with state.frame(node.body) as if_frame:
185
190
  true_cond = if_frame.entr_block.args.append_from(types.Bool, cond.name)
186
191
  if cond.name:
187
192
  if_frame.defs[cond.name] = true_cond
188
193
 
194
+ # NOTE: pass in definitions from outer scope (usually just for the qreg)
195
+ if_frame.defs.update(frame.defs)
196
+
189
197
  if_frame.exhaust()
190
- self.branch_next_if_not_terminated(if_frame)
191
198
 
192
- with state.frame([], region=frame.curr_region) as else_frame:
193
- true_cond = else_frame.entr_block.args.append_from(types.Bool, cond.name)
194
- if cond.name:
195
- else_frame.defs[cond.name] = true_cond
196
- else_frame.exhaust()
197
- self.branch_next_if_not_terminated(else_frame)
198
-
199
- with state.frame(frame.stream.split(), region=frame.curr_region) as after_frame:
200
- after_frame.defs.update(frame.defs)
201
- phi: set[str] = set()
202
- for name in if_frame.defs.keys():
203
- if frame.get(name):
204
- phi.add(name)
205
- elif name in else_frame.defs:
206
- phi.add(name)
207
-
208
- for name in else_frame.defs.keys():
209
- if frame.get(name): # not defined in if_frame
210
- phi.add(name)
211
-
212
- for name in phi:
213
- after_frame.defs[name] = after_frame.entr_block.args.append_from(
214
- types.Any, name
215
- )
199
+ # NOTE: qasm2 can never yield anything from if
200
+ if_frame.push(scf.Yield())
216
201
 
217
- after_frame.exhaust()
218
- self.branch_next_if_not_terminated(after_frame)
219
- after_frame.next_block.stmts.append(
220
- cf.Branch(arguments=(), successor=frame.next_block)
221
- )
202
+ then_body = if_frame.curr_region
222
203
 
223
- if_args = []
224
- for name in phi:
225
- if value := if_frame.get(name):
226
- if_args.append(value)
227
- else:
228
- raise lowering.BuildError(f"undefined variable {name} in if branch")
229
-
230
- else_args = []
231
- for name in phi:
232
- if value := else_frame.get(name):
233
- else_args.append(value)
234
- else:
235
- raise lowering.BuildError(f"undefined variable {name} in else branch")
236
-
237
- if_frame.next_block.stmts.append(
238
- cf.Branch(
239
- arguments=tuple(if_args),
240
- successor=after_frame.entr_block,
241
- )
242
- )
243
- else_frame.next_block.stmts.append(
244
- cf.Branch(
245
- arguments=tuple(else_args),
246
- successor=after_frame.entr_block,
247
- )
248
- )
249
- before_block.stmts.append(
250
- cf.ConditionalBranch(
251
- cond=cond,
252
- then_arguments=(cond,),
253
- then_successor=if_frame.entr_block,
254
- else_arguments=(cond,),
255
- else_successor=else_frame.entr_block,
256
- )
257
- )
258
- frame.defs.update(after_frame.defs)
259
- frame.jump_next_block()
204
+ state.current_frame.push(scf.IfElse(cond, then_body=then_body))
260
205
 
261
206
  def branch_next_if_not_terminated(self, frame: lowering.Frame):
262
207
  """Branch to the next block if the current block is not terminated.
@@ -430,7 +375,56 @@ class QASM2(lowering.LoweringABC[ast.Node]):
430
375
  raise lowering.BuildError(f"Include {node.filename} not found")
431
376
 
432
377
  def visit_Gate(self, state: lowering.State[ast.Node], node: ast.Gate):
433
- raise NotImplementedError("Gate lowering not supported")
378
+ arg_names = node.cparams + node.qparams
379
+ arg_types = [types.Float for _ in node.cparams] + [
380
+ QubitType for _ in node.qparams
381
+ ]
382
+
383
+ with state.frame(
384
+ stmts=node.body,
385
+ finalize_next=False,
386
+ ) as body_frame:
387
+ # NOTE: insert _self as arg
388
+ body_frame.curr_block.args.append_from(
389
+ types.Generic(
390
+ ir.Method, types.Tuple.where(tuple(arg_types)), types.NoneType
391
+ ),
392
+ name=node.name + "_self",
393
+ )
394
+
395
+ for arg_type, arg_name in zip(arg_types, arg_names):
396
+ # NOTE: append args as block arguments
397
+ block_arg = body_frame.curr_block.args.append_from(
398
+ arg_type, name=arg_name
399
+ )
400
+
401
+ # NOTE: add arguments as definitions to frame
402
+ body_frame.defs[arg_name] = block_arg
403
+
404
+ body_frame.exhaust()
405
+
406
+ # NOTE: append none as return value
407
+ return_val = func.ConstantNone()
408
+ body_frame.push(return_val)
409
+ body_frame.push(func.Return(return_val))
410
+
411
+ body = body_frame.curr_region
412
+
413
+ gate_func = expr.GateFunction(
414
+ sym_name=node.name,
415
+ signature=func.Signature(inputs=tuple(arg_types), output=types.NoneType),
416
+ body=body,
417
+ )
418
+
419
+ mt = ir.Method(
420
+ mod=None,
421
+ py_func=None,
422
+ sym_name=node.name,
423
+ dialects=self.dialects,
424
+ arg_names=[*node.cparams, *node.qparams],
425
+ code=gate_func,
426
+ )
427
+ state.current_frame.globals[node.name] = mt
434
428
 
435
429
  def visit_Instruction(self, state: lowering.State[ast.Node], node: ast.Instruction):
436
430
  params = [state.lower(param).expect_one() for param in node.params]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bloqade-circuit
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: The software development toolkit for neutral atom arrays.
5
5
  Author-email: Roger-luo <rluo@quera.com>, kaihsin <khwu@quera.com>, weinbe58 <pweinberg@quera.com>, johnzl-777 <jlong@quera.com>
6
6
  License-File: LICENSE
@@ -74,7 +74,7 @@ bloqade/qasm2/emit/impls/noise.py,sha256=-N9PmCbz8MwC6xtd55GOpjDoWMyJPJBMVDWT3G8
74
74
  bloqade/qasm2/parse/__init__.py,sha256=01tlLfrR015nAAPWw3i_Cs9IXsShpXMnJMagcJ_Vuik,986
75
75
  bloqade/qasm2/parse/ast.py,sha256=a48ssf0D_xaE-27PsyeBD5lBvwN2Dojj-RWIBhy7jJE,2904
76
76
  bloqade/qasm2/parse/build.py,sha256=2CibD1ZRX3_aknmhb5XvFQcI2sBOn97DlQHomb9CMEw,10621
77
- bloqade/qasm2/parse/lowering.py,sha256=CwwCdaatbc5CiSmVcltGko2kblX60COuJDzqQtv-L4E,21274
77
+ bloqade/qasm2/parse/lowering.py,sha256=VRFhdDsgAeALVzJxmDtlRI3L1xLrAGnz_Zh-qNOChhM,20844
78
78
  bloqade/qasm2/parse/parser.py,sha256=fxqp65dv8NnXE-Ie7ryLESfSH3Xr0unx1EBQysctiHM,121
79
79
  bloqade/qasm2/parse/print.py,sha256=PaigQ5RbcfhOteWvDdQHoKsTE3tcNefpVfh1sp5eZEI,8973
80
80
  bloqade/qasm2/parse/qasm2.lark,sha256=IYrBydUoVLn1VCNDPP5uNN5BHDET3fQ2yG11cOy900k,2238
@@ -191,7 +191,7 @@ bloqade/visual/animation/runtime/atoms.py,sha256=EmjxhujLiHHPS_HtH_B-7TiqeHgvW5u
191
191
  bloqade/visual/animation/runtime/ppoly.py,sha256=JB9IP53N1w6adBJEue6J5Nmj818Id9JvrlgrmiQTU1I,1385
192
192
  bloqade/visual/animation/runtime/qpustate.py,sha256=rlmxQeJSvaohXrTpXQL5y-NJcpvfW33xPaYM1slv7cc,4270
193
193
  bloqade/visual/animation/runtime/utils.py,sha256=ju9IzOWX-vKwfpqUjlUKu3Ssr_UFPFFq-tzH_Nqyo_c,1212
194
- bloqade_circuit-0.4.1.dist-info/METADATA,sha256=53teyQGCbiQ0-uxPqwBrNAKdeLcpe7h3Aj7fgVq26HU,3683
195
- bloqade_circuit-0.4.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
196
- bloqade_circuit-0.4.1.dist-info/licenses/LICENSE,sha256=S5GIJwR6QCixPA9wryYb44ZEek0Nz4rt_zLUqP05UbU,13160
197
- bloqade_circuit-0.4.1.dist-info/RECORD,,
194
+ bloqade_circuit-0.4.2.dist-info/METADATA,sha256=DtKJN5tKb8MKEyvu-no-QZuQNFsgHxhw1NUQiojpFe4,3683
195
+ bloqade_circuit-0.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
196
+ bloqade_circuit-0.4.2.dist-info/licenses/LICENSE,sha256=S5GIJwR6QCixPA9wryYb44ZEek0Nz4rt_zLUqP05UbU,13160
197
+ bloqade_circuit-0.4.2.dist-info/RECORD,,