Skip to content

Commit e0461d6

Browse files
authored
Add gate calls and the AST items it depends on to the new QASM3 compiler (#2246)
This PR adds gate calls and the AST items it depends on to the new QASM3 compiler: - [x] Constant evaluation (needed for array sizes and type widths). - [x] Unit tests. - [x] QuantumDeclStmt - [x] IndexedAssignStmt. - [x] Bitarrays. - [x] MeasureExpr / MeasureStmt. - [x] Compilation to Result type (introduces `LiteralKind::Bit(bool)`) variant. - [x] GatecallStmt - [x] barrier - [x] reset
1 parent ce4ff3b commit e0461d6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+6279
-3102
lines changed

compiler/qsc_qasm3/src/compiler.rs

Lines changed: 255 additions & 57 deletions
Large diffs are not rendered by default.

compiler/qsc_qasm3/src/parser/ast.rs

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ impl WithSpan for Path {
147147
#[derive(Clone, Debug)]
148148
pub struct MeasureExpr {
149149
pub span: Span,
150+
pub measure_token_span: Span,
150151
pub operand: GateOperand,
151152
}
152153

@@ -248,29 +249,51 @@ impl Display for UnaryOp {
248249
}
249250

250251
#[derive(Clone, Debug, Default)]
251-
pub enum GateOperand {
252+
pub struct GateOperand {
253+
pub span: Span,
254+
pub kind: GateOperandKind,
255+
}
256+
257+
impl WithSpan for GateOperand {
258+
fn with_span(self, span: Span) -> Self {
259+
Self {
260+
span,
261+
kind: self.kind.with_span(span),
262+
}
263+
}
264+
}
265+
266+
impl Display for GateOperand {
267+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
268+
writeln_header(f, "GateOperand", self.span)?;
269+
write_field(f, "kind", &self.kind)
270+
}
271+
}
272+
273+
#[derive(Clone, Debug, Default)]
274+
pub enum GateOperandKind {
252275
IndexedIdent(Box<IndexedIdent>),
253276
HardwareQubit(Box<HardwareQubit>),
254277
#[default]
255278
Err,
256279
}
257280

258-
impl Display for GateOperand {
281+
impl Display for GateOperandKind {
259282
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
260283
match self {
261-
GateOperand::IndexedIdent(ident) => write!(f, "{ident}"),
262-
GateOperand::HardwareQubit(qubit) => write!(f, "{qubit}"),
263-
GateOperand::Err => write!(f, "Error"),
284+
Self::IndexedIdent(ident) => write!(f, "{ident}"),
285+
Self::HardwareQubit(qubit) => write!(f, "{qubit}"),
286+
Self::Err => write!(f, "Error"),
264287
}
265288
}
266289
}
267290

268-
impl WithSpan for GateOperand {
291+
impl WithSpan for GateOperandKind {
269292
fn with_span(self, span: Span) -> Self {
270293
match self {
271-
GateOperand::IndexedIdent(ident) => GateOperand::IndexedIdent(ident.with_span(span)),
272-
GateOperand::HardwareQubit(qubit) => GateOperand::HardwareQubit(qubit.with_span(span)),
273-
GateOperand::Err => GateOperand::Err,
294+
Self::IndexedIdent(ident) => Self::IndexedIdent(ident.with_span(span)),
295+
Self::HardwareQubit(qubit) => Self::HardwareQubit(qubit.with_span(span)),
296+
Self::Err => Self::Err,
274297
}
275298
}
276299
}
@@ -335,7 +358,7 @@ pub enum StmtKind {
335358
GPhase(GPhase),
336359
Include(IncludeStmt),
337360
IODeclaration(IODeclaration),
338-
Measure(MeasureStmt),
361+
Measure(MeasureArrowStmt),
339362
Pragma(Pragma),
340363
QuantumGateDefinition(QuantumGateDefinition),
341364
QuantumDecl(QubitDeclaration),
@@ -445,12 +468,14 @@ impl Display for BarrierStmt {
445468
#[derive(Clone, Debug)]
446469
pub struct ResetStmt {
447470
pub span: Span,
471+
pub reset_token_span: Span,
448472
pub operand: Box<GateOperand>,
449473
}
450474

451475
impl Display for ResetStmt {
452476
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
453477
writeln_header(f, "ResetStmt", self.span)?;
478+
writeln_field(f, "reset_token_span", &self.reset_token_span)?;
454479
write_field(f, "operand", &self.operand)
455480
}
456481
}
@@ -991,13 +1016,15 @@ impl Display for IncludeStmt {
9911016
#[derive(Clone, Debug)]
9921017
pub struct QubitDeclaration {
9931018
pub span: Span,
1019+
pub ty_span: Span,
9941020
pub qubit: Ident,
9951021
pub size: Option<Expr>,
9961022
}
9971023

9981024
impl Display for QubitDeclaration {
9991025
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
10001026
writeln_header(f, "QubitDeclaration", self.span)?;
1027+
writeln_field(f, "ty_span", &self.ty_span)?;
10011028
writeln_field(f, "ident", &self.qubit)?;
10021029
write_opt_field(f, "size", self.size.as_ref())
10031030
}
@@ -1110,15 +1137,15 @@ impl Display for BoxStmt {
11101137
}
11111138

11121139
#[derive(Clone, Debug)]
1113-
pub struct MeasureStmt {
1140+
pub struct MeasureArrowStmt {
11141141
pub span: Span,
11151142
pub measurement: MeasureExpr,
11161143
pub target: Option<Box<IndexedIdent>>,
11171144
}
11181145

1119-
impl Display for MeasureStmt {
1146+
impl Display for MeasureArrowStmt {
11201147
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1121-
writeln_header(f, "MeasureStmt", self.span)?;
1148+
writeln_header(f, "MeasureArrowStmt", self.span)?;
11221149
writeln_field(f, "measurement", &self.measurement)?;
11231150
write_opt_field(f, "target", self.target.as_ref())
11241151
}
@@ -1129,7 +1156,7 @@ pub struct ClassicalDeclarationStmt {
11291156
pub span: Span,
11301157
pub ty: Box<TypeDef>,
11311158
pub identifier: Ident,
1132-
pub init_expr: Option<Box<ValueExpression>>,
1159+
pub init_expr: Option<Box<ValueExpr>>,
11331160
}
11341161

11351162
impl Display for ClassicalDeclarationStmt {
@@ -1142,16 +1169,16 @@ impl Display for ClassicalDeclarationStmt {
11421169
}
11431170

11441171
#[derive(Clone, Debug)]
1145-
pub enum ValueExpression {
1172+
pub enum ValueExpr {
11461173
Expr(Expr),
11471174
Measurement(MeasureExpr),
11481175
}
11491176

1150-
impl Display for ValueExpression {
1177+
impl Display for ValueExpr {
11511178
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
11521179
match self {
1153-
ValueExpression::Expr(expr) => write!(f, "{expr}"),
1154-
ValueExpression::Measurement(measure) => write!(f, "{measure}"),
1180+
Self::Expr(expr) => write!(f, "{expr}"),
1181+
Self::Measurement(measure) => write!(f, "{measure}"),
11551182
}
11561183
}
11571184
}
@@ -1178,7 +1205,7 @@ pub struct ConstantDeclStmt {
11781205
pub span: Span,
11791206
pub ty: TypeDef,
11801207
pub identifier: Box<Ident>,
1181-
pub init_expr: Expr,
1208+
pub init_expr: ValueExpr,
11821209
}
11831210

11841211
impl Display for ConstantDeclStmt {
@@ -1339,7 +1366,7 @@ impl Display for DefStmt {
13391366
#[derive(Clone, Debug)]
13401367
pub struct ReturnStmt {
13411368
pub span: Span,
1342-
pub expr: Option<Box<ValueExpression>>,
1369+
pub expr: Option<Box<ValueExpr>>,
13431370
}
13441371

13451372
impl Display for ReturnStmt {
@@ -1470,7 +1497,7 @@ impl Display for ExprKind {
14701497
pub struct AssignStmt {
14711498
pub span: Span,
14721499
pub lhs: IndexedIdent,
1473-
pub rhs: Expr,
1500+
pub rhs: ValueExpr,
14741501
}
14751502

14761503
impl Display for AssignStmt {
@@ -1486,7 +1513,7 @@ pub struct AssignOpStmt {
14861513
pub span: Span,
14871514
pub op: BinOp,
14881515
pub lhs: IndexedIdent,
1489-
pub rhs: Expr,
1516+
pub rhs: ValueExpr,
14901517
}
14911518

14921519
impl Display for AssignOpStmt {

compiler/qsc_qasm3/src/parser/ast/display_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub(crate) fn writeln_opt_field<T: Display>(
129129
writeln!(f)
130130
}
131131

132-
/// Writes an field of a structure to the given buffer
132+
/// Writes a field of a structure to the given buffer
133133
/// or stream with an additional indententation level.
134134
/// The field must be an iterable.
135135
pub(crate) fn write_list_field<'write, 'itemref, 'item, T, I>(
@@ -148,7 +148,7 @@ where
148148
write_list(&mut indent, vals)
149149
}
150150

151-
/// Writes an field of a structure to the given buffer
151+
/// Writes a field of a structure to the given buffer
152152
/// or stream with an additional indententation level.
153153
/// The field must be an iterable.
154154
/// Inserts a newline afterwards.

compiler/qsc_qasm3/src/parser/expr.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ use crate::parser::Result;
2424
use super::{
2525
ast::{
2626
list_from_iter, BinOp, BinaryOpExpr, Cast, DiscreteSet, Expr, ExprKind, FunctionCall,
27-
GateOperand, HardwareQubit, Ident, IndexElement, IndexExpr, IndexSet, IndexSetItem,
28-
IndexedIdent, List, Lit, LiteralKind, MeasureExpr, RangeDefinition, TimeUnit, TypeDef,
29-
UnaryOp, UnaryOpExpr, ValueExpression, Version,
27+
GateOperand, GateOperandKind, HardwareQubit, Ident, IndexElement, IndexExpr, IndexSet,
28+
IndexSetItem, IndexedIdent, List, Lit, LiteralKind, MeasureExpr, RangeDefinition, TimeUnit,
29+
TypeDef, UnaryOp, UnaryOpExpr, ValueExpr, Version,
3030
},
3131
completion::WordKinds,
3232
error::{Error, ErrorKind},
@@ -708,9 +708,11 @@ fn lit_array_element(s: &mut ParserContext) -> Result<Expr> {
708708
lit_array(s)
709709
}
710710

711-
pub(super) fn value_expr(s: &mut ParserContext) -> Result<Box<ValueExpression>> {
711+
/// These are expressions allowed in classical declarations.
712+
/// Grammar: `arrayLiteral | expression | measureExpression`.
713+
pub(super) fn declaration_expr(s: &mut ParserContext) -> Result<ValueExpr> {
712714
if let Some(measurement) = opt(s, measure_expr)? {
713-
return Ok(Box::new(ValueExpression::Measurement(measurement)));
715+
return Ok(ValueExpr::Measurement(measurement));
714716
}
715717

716718
let expr = if let Some(expr) = opt(s, expr)? {
@@ -719,7 +721,17 @@ pub(super) fn value_expr(s: &mut ParserContext) -> Result<Box<ValueExpression>>
719721
lit_array(s)?
720722
};
721723

722-
Ok(Box::new(ValueExpression::Expr(expr)))
724+
Ok(ValueExpr::Expr(expr))
725+
}
726+
727+
/// These are expressions allowed in `Assign`, `AssignOp`, and return stmts.
728+
/// Grammar: `expression | measureExpression`.
729+
pub(super) fn expr_or_measurement(s: &mut ParserContext) -> Result<ValueExpr> {
730+
if let Some(measurement) = opt(s, measure_expr)? {
731+
return Ok(ValueExpr::Measurement(measurement));
732+
}
733+
734+
Ok(ValueExpr::Expr(expr(s)?))
723735
}
724736

725737
pub(crate) fn expr_list(s: &mut ParserContext) -> Result<Vec<Expr>> {
@@ -729,18 +741,28 @@ pub(crate) fn expr_list(s: &mut ParserContext) -> Result<Vec<Expr>> {
729741
pub(crate) fn measure_expr(s: &mut ParserContext) -> Result<MeasureExpr> {
730742
let lo = s.peek().span.lo;
731743
token(s, TokenKind::Measure)?;
744+
let measure_token_span = s.span(lo);
745+
let operand = gate_operand(s)?;
732746

733747
Ok(MeasureExpr {
734748
span: s.span(lo),
735-
operand: gate_operand(s)?,
749+
measure_token_span,
750+
operand,
736751
})
737752
}
738753

739754
pub(crate) fn gate_operand(s: &mut ParserContext) -> Result<GateOperand> {
740-
if let Some(indexed_ident) = opt(s, indexed_identifier)? {
741-
return Ok(GateOperand::IndexedIdent(Box::new(indexed_ident)));
742-
}
743-
Ok(GateOperand::HardwareQubit(Box::new(hardware_qubit(s)?)))
755+
let lo = s.peek().span.lo;
756+
let kind = if let Some(indexed_ident) = opt(s, indexed_identifier)? {
757+
GateOperandKind::IndexedIdent(Box::new(indexed_ident))
758+
} else {
759+
GateOperandKind::HardwareQubit(Box::new(hardware_qubit(s)?))
760+
};
761+
762+
Ok(GateOperand {
763+
span: s.span(lo),
764+
kind,
765+
})
744766
}
745767

746768
fn hardware_qubit(s: &mut ParserContext) -> Result<HardwareQubit> {

compiler/qsc_qasm3/src/parser/expr/tests.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,8 +1146,9 @@ fn measure_hardware_qubit() {
11461146
super::measure_expr,
11471147
"measure $12",
11481148
&expect![[r#"
1149-
MeasureExpr [0-7]:
1150-
operand: HardwareQubit [8-11]: 12"#]],
1149+
MeasureExpr [0-11]:
1150+
operand: GateOperand [8-11]:
1151+
kind: HardwareQubit [8-11]: 12"#]],
11511152
);
11521153
}
11531154

@@ -1157,17 +1158,18 @@ fn measure_indexed_identifier() {
11571158
super::measure_expr,
11581159
"measure qubits[1][2]",
11591160
&expect![[r#"
1160-
MeasureExpr [0-7]:
1161-
operand: IndexedIdent [8-20]:
1162-
name: Ident [8-14] "qubits"
1163-
index_span: [14-20]
1164-
indices:
1165-
IndexSet [15-16]:
1166-
values:
1167-
Expr [15-16]: Lit: Int(1)
1168-
IndexSet [18-19]:
1169-
values:
1170-
Expr [18-19]: Lit: Int(2)"#]],
1161+
MeasureExpr [0-20]:
1162+
operand: GateOperand [8-20]:
1163+
kind: IndexedIdent [8-20]:
1164+
name: Ident [8-14] "qubits"
1165+
index_span: [14-20]
1166+
indices:
1167+
IndexSet [15-16]:
1168+
values:
1169+
Expr [15-16]: Lit: Int(1)
1170+
IndexSet [18-19]:
1171+
values:
1172+
Expr [18-19]: Lit: Int(2)"#]],
11711173
);
11721174
}
11731175

0 commit comments

Comments
 (0)