Skip to content

Commit a6c9b5d

Browse files
authored
Merge pull request #15 from braised-babbage/allow-annotations-pragmas-in-cal-blocks
Allow annotations & pragmas in cal blocks
2 parents 5726a2a + 03fbf42 commit a6c9b5d

4 files changed

Lines changed: 104 additions & 31 deletions

File tree

source/grammar/openpulseParser.g4

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,32 @@ calibrationBlock: openpulseStatement*;
1515

1616
openpulseStatement:
1717
// Statements can be used in the cal or defcal body
18-
aliasDeclarationStatement
19-
| assignmentStatement
20-
| barrierStatement
21-
| boxStatement
22-
| breakStatement
23-
| classicalDeclarationStatement
24-
| constDeclarationStatement
25-
| continueStatement
26-
| defStatement
27-
| delayStatement
28-
| endStatement
29-
| expressionStatement
30-
| externStatement
31-
| forStatement
32-
| gateCallStatement
33-
| ifStatement
34-
| includeStatement
35-
| ioDeclarationStatement
36-
| quantumDeclarationStatement
37-
| resetStatement
38-
| returnStatement
39-
| whileStatement
40-
;
18+
pragma
19+
| annotation* (
20+
aliasDeclarationStatement
21+
| assignmentStatement
22+
| barrierStatement
23+
| boxStatement
24+
| breakStatement
25+
| classicalDeclarationStatement
26+
| constDeclarationStatement
27+
| continueStatement
28+
| defStatement
29+
| delayStatement
30+
| endStatement
31+
| expressionStatement
32+
| externStatement
33+
| forStatement
34+
| gateCallStatement
35+
| ifStatement
36+
| includeStatement
37+
| ioDeclarationStatement
38+
| quantumDeclarationStatement
39+
| resetStatement
40+
| returnStatement
41+
| whileStatement
42+
)
43+
;
4144

4245
/** In the following we extend existing OpenQASM nodes. Need to refresh whenever OpenQASM is updated. **/
4346
// We extend the scalarType with WAVEFORM, PORT and FRAME

source/openpulse/openpulse/ast.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from __future__ import annotations
1313

1414
from dataclasses import dataclass
15-
from typing import List, Optional
15+
from typing import List, Optional, Union
1616

1717
# Re-export the existing AST classes from openqasm3
1818
# pylint: disable=unused-import
@@ -22,6 +22,7 @@
2222
# pylint: disable=unused-import
2323
from openqasm3.ast import ExternArgument
2424

25+
2526
# From Pulse grammar
2627
class WaveformType(ClassicalType):
2728
"""
@@ -72,7 +73,7 @@ class CalibrationStatement(Statement):
7273
}
7374
"""
7475

75-
body: List[Statement]
76+
body: List[Union[Statement, Pragma]]
7677

7778

7879
# Override the class from openqasm3

source/openpulse/openpulse/parser.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ def visitReturnStatement(self, ctx: qasm3Parser.ReturnStatementContext):
216216
expression = None
217217
return ast.ReturnStatement(expression=expression)
218218

219+
@span
220+
def visitOpenpulseStatement(self, ctx: openpulseParser.OpenpulseStatementContext):
221+
if ctx.pragma():
222+
return self.visit(ctx.pragma())
223+
out = self.visit(ctx.getChild(-1))
224+
out.annotations = [self.visit(annotation) for annotation in ctx.annotation()]
225+
return out
226+
219227

220228
# Reuse some QASMNodeVisitor methods in OpenPulseNodeVisitor
221229
# The following methods are overridden in OpenPulseNodeVisitor and thus not imported:

source/openpulse/tests/test_openpulse_parser.py

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import dataclasses
22

33
import pytest
4-
5-
from openqasm3.visitor import QASMVisitor
6-
7-
from openpulse.parser import parse
84
from openpulse.ast import (
95
AngleType,
6+
Annotation,
107
ArrayLiteral,
118
ArrayType,
9+
AssignmentOperator,
1210
CalibrationDefinition,
1311
CalibrationStatement,
1412
ClassicalArgument,
13+
ClassicalAssignment,
1514
ClassicalDeclaration,
1615
ComplexType,
1716
DurationType,
@@ -21,21 +20,24 @@
2120
FloatLiteral,
2221
FloatType,
2322
ForInLoop,
23+
FrameType,
2424
FunctionCall,
2525
Identifier,
2626
IntegerLiteral,
2727
IntType,
28+
PortType,
29+
Pragma,
2830
Program,
2931
QASMNode,
3032
QuantumBarrier,
3133
RangeDefinition,
3234
ReturnStatement,
3335
UnaryExpression,
3436
UnaryOperator,
35-
FrameType,
36-
PortType,
3737
WaveformType,
3838
)
39+
from openpulse.parser import parse
40+
from openqasm3.visitor import QASMVisitor
3941

4042

4143
class SpanGuard(QASMVisitor):
@@ -268,6 +270,65 @@ def test_array():
268270
SpanGuard().visit(program)
269271

270272

273+
def test_annotation_in_cal_block():
274+
p = """
275+
cal {
276+
@word1
277+
int x = 10;
278+
279+
@word1 command1
280+
@word2 command2 32f%^&
281+
x = 0;
282+
283+
@word1 @not_a_separate_annotation uint x;
284+
z();
285+
}
286+
"""
287+
288+
xdecl = ClassicalDeclaration(
289+
type=IntType(),
290+
identifier=Identifier("x"),
291+
init_expression=IntegerLiteral(10),
292+
)
293+
xdecl.annotations = [Annotation("word1")]
294+
295+
xassign = ClassicalAssignment(Identifier("x"), AssignmentOperator["="], IntegerLiteral(0))
296+
xassign.annotations = [Annotation("word1", "command1"), Annotation("word2", "command2 32f%^&")]
297+
298+
zcall = ExpressionStatement(FunctionCall(Identifier("z"), []))
299+
zcall.annotations = [Annotation("word1", "@not_a_separate_annotation uint x;")]
300+
program = parse(p)
301+
expected = Program(statements=[CalibrationStatement(body=[xdecl, xassign, zcall])])
302+
303+
assert _remove_spans(program) == expected
304+
305+
306+
def test_pragma_in_cal_block():
307+
p = """
308+
cal {
309+
#pragma foo bar
310+
int x = 10;
311+
}
312+
"""
313+
314+
program = parse(p)
315+
expected = Program(
316+
statements=[
317+
CalibrationStatement(
318+
body=[
319+
Pragma(command="foo bar"),
320+
ClassicalDeclaration(
321+
type=IntType(),
322+
identifier=Identifier("x"),
323+
init_expression=IntegerLiteral(10),
324+
),
325+
]
326+
)
327+
]
328+
)
329+
assert _remove_spans(program) == expected
330+
331+
271332
@pytest.mark.parametrize(
272333
"p",
273334
[

0 commit comments

Comments
 (0)