Skip to content

Commit be262cd

Browse files
orpuente-MSidavis
authored andcommitted
Tidy up Display functions in QASM3 parser (#2209)
This PR doesn't change any behavior. It just touches the Display functions in the QASM3 parser to make unit tests easier to read.
1 parent 50b49e9 commit be262cd

31 files changed

+2873
-1637
lines changed

compiler/qsc_qasm3/src/ast.rs

+311-670
Large diffs are not rendered by default.
+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use std::fmt::{self, Display, Write};
5+
6+
/// Takes a unicode buffer or stream and wraps it with
7+
/// `indenter::Idented`. Which applies an indentation of 1
8+
/// each time you insert a new line.
9+
fn with_indentation<T>(f: &mut T) -> indenter::Indented<'_, T>
10+
where
11+
T: fmt::Write,
12+
{
13+
let indent = indenter::indented(f);
14+
set_indentation(indent, 1)
15+
}
16+
17+
/// Takes an `indenter::Idented` and changes its indentation level.
18+
fn set_indentation<T>(indent: indenter::Indented<'_, T>, level: usize) -> indenter::Indented<'_, T>
19+
where
20+
T: fmt::Write,
21+
{
22+
match level {
23+
0 => indent.with_str(""),
24+
1 => indent.with_str(" "),
25+
2 => indent.with_str(" "),
26+
3 => indent.with_str(" "),
27+
_ => unimplemented!("indentation level not supported"),
28+
}
29+
}
30+
31+
/// Writes a list of elements to the given buffer or stream.
32+
fn write_list<'write, 'itemref, 'item, T, I>(f: &'write mut impl Write, vals: I) -> fmt::Result
33+
where
34+
'item: 'itemref,
35+
T: Display + 'item,
36+
I: IntoIterator<Item = &'itemref T>,
37+
{
38+
let mut iter = vals.into_iter().peekable();
39+
if iter.peek().is_none() {
40+
write!(f, " <empty>")
41+
} else {
42+
for elt in iter {
43+
write!(f, "\n{elt}")?;
44+
}
45+
Ok(())
46+
}
47+
}
48+
49+
/// Writes a list of elements to the given buffer or stream
50+
/// with an additional indentation level.
51+
pub(super) fn write_indented_list<'write, 'itemref, 'item, T, I>(
52+
f: &'write mut impl Write,
53+
vals: I,
54+
) -> fmt::Result
55+
where
56+
'item: 'itemref,
57+
T: Display + 'item,
58+
I: IntoIterator<Item = &'itemref T>,
59+
{
60+
let mut iter = vals.into_iter().peekable();
61+
if iter.peek().is_none() {
62+
write!(f, " <empty>")
63+
} else {
64+
let mut indent = with_indentation(f);
65+
for elt in iter {
66+
write!(indent, "\n{elt}")?;
67+
}
68+
Ok(())
69+
}
70+
}
71+
72+
/// Writes the name and span of a structure to the given buffer or stream.
73+
pub(super) fn write_header(f: &mut impl Write, name: &str, span: super::Span) -> fmt::Result {
74+
write!(f, "{name} {span}:")
75+
}
76+
77+
/// Writes the name and span of a structure to the given buffer or stream.
78+
/// Inserts a newline afterwards.
79+
pub(super) fn writeln_header(f: &mut impl Write, name: &str, span: super::Span) -> fmt::Result {
80+
writeln!(f, "{name} {span}:")
81+
}
82+
83+
/// Writes a field of a structure to the given buffer
84+
/// or stream with an additional indententation level.
85+
pub(super) fn write_field<T: Display>(
86+
f: &mut impl Write,
87+
field_name: &str,
88+
val: &T,
89+
) -> fmt::Result {
90+
let mut indent = with_indentation(f);
91+
write!(indent, "{field_name}: {val}")
92+
}
93+
94+
/// Writes a field of a structure to the given buffer
95+
/// or stream with an additional indententation level.
96+
/// Inserts a newline afterwards.
97+
pub(super) fn writeln_field<T: Display>(
98+
f: &mut impl Write,
99+
field_name: &str,
100+
val: &T,
101+
) -> fmt::Result {
102+
write_field(f, field_name, val)?;
103+
writeln!(f)
104+
}
105+
106+
/// Writes an optional field of a structure to the given buffer
107+
/// or stream with an additional indententation level.
108+
pub(super) fn write_opt_field<T: Display>(
109+
f: &mut impl Write,
110+
field_name: &str,
111+
opt_val: Option<&T>,
112+
) -> fmt::Result {
113+
if let Some(val) = opt_val {
114+
write_field(f, field_name, val)
115+
} else {
116+
write_field(f, field_name, &"<none>")
117+
}
118+
}
119+
120+
/// Writes an optional field of a structure to the given buffer
121+
/// or stream with an additional indententation level.
122+
/// Inserts a newline afterwards.
123+
pub(super) fn writeln_opt_field<T: Display>(
124+
f: &mut impl Write,
125+
field_name: &str,
126+
opt_val: Option<&T>,
127+
) -> fmt::Result {
128+
write_opt_field(f, field_name, opt_val)?;
129+
writeln!(f)
130+
}
131+
132+
/// Writes an field of a structure to the given buffer
133+
/// or stream with an additional indententation level.
134+
/// The field must be an iterable.
135+
pub(super) fn write_list_field<'write, 'itemref, 'item, T, I>(
136+
f: &mut impl Write,
137+
field_name: &str,
138+
vals: I,
139+
) -> fmt::Result
140+
where
141+
'item: 'itemref,
142+
T: Display + 'item,
143+
I: IntoIterator<Item = &'itemref T>,
144+
{
145+
let mut indent = with_indentation(f);
146+
write!(indent, "{field_name}:")?;
147+
let mut indent = set_indentation(indent, 2);
148+
write_list(&mut indent, vals)
149+
}
150+
151+
/// Writes an field of a structure to the given buffer
152+
/// or stream with an additional indententation level.
153+
/// The field must be an iterable.
154+
/// Inserts a newline afterwards.
155+
pub(super) fn writeln_list_field<'write, 'itemref, 'item, T, I>(
156+
f: &mut impl Write,
157+
field_name: &str,
158+
vals: I,
159+
) -> fmt::Result
160+
where
161+
'item: 'itemref,
162+
T: Display + 'item,
163+
I: IntoIterator<Item = &'itemref T>,
164+
{
165+
write_list_field(f, field_name, vals)?;
166+
writeln!(f)
167+
}
168+
169+
/// Writes an optional field of a structure to the given buffer
170+
/// or stream with an additional indententation level.
171+
/// The field must be an iterable.
172+
pub(super) fn write_opt_list_field<'write, 'itemref, 'item, T, I>(
173+
f: &mut impl Write,
174+
field_name: &str,
175+
opt_vals: Option<I>,
176+
) -> fmt::Result
177+
where
178+
'item: 'itemref,
179+
T: Display + 'item,
180+
I: IntoIterator<Item = &'itemref T>,
181+
{
182+
if let Some(vals) = opt_vals {
183+
write_list_field(f, field_name, vals)
184+
} else {
185+
let mut indent = with_indentation(f);
186+
write!(indent, "{field_name}: <none>")
187+
}
188+
}
189+
190+
/// Writes an optional field of a structure to the given buffer
191+
/// or stream with an additional indententation level.
192+
/// The field must be an iterable.
193+
/// Inserts a newline afterwards.
194+
pub(super) fn writeln_opt_list_field<'write, 'itemref, 'item, T, I>(
195+
f: &mut impl Write,
196+
field_name: &str,
197+
opt_vals: Option<I>,
198+
) -> fmt::Result
199+
where
200+
'item: 'itemref,
201+
T: Display + 'item,
202+
I: IntoIterator<Item = &'itemref T>,
203+
{
204+
write_opt_list_field(f, field_name, opt_vals)?;
205+
writeln!(f)
206+
}

compiler/qsc_qasm3/src/parser/expr.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::{
1818
ast::{
1919
self, list_from_iter, AssignExpr, AssignOpExpr, BinOp, BinaryOpExpr, Cast, DiscreteSet,
2020
Expr, ExprKind, FunctionCall, GateOperand, HardwareQubit, Ident, IndexElement, IndexExpr,
21-
IndexSetItem, IndexedIdent, List, Lit, LiteralKind, MeasureExpr, RangeDefinition, TimeUnit,
22-
TypeDef, UnaryOp, ValueExpression, Version,
21+
IndexSet, IndexSetItem, IndexedIdent, List, Lit, LiteralKind, MeasureExpr, RangeDefinition,
22+
TimeUnit, TypeDef, UnaryOp, ValueExpression, Version,
2323
},
2424
keyword::Keyword,
2525
lex::{
@@ -291,7 +291,7 @@ fn lit_token(lexeme: &str, token: Token) -> Result<Option<Lit>> {
291291

292292
Ok(Some(Lit {
293293
span: token.span,
294-
kind: LiteralKind::Bitstring(value, width),
294+
kind: LiteralKind::Bitstring { value, width },
295295
}))
296296
}
297297
Literal::Imaginary => {
@@ -492,13 +492,13 @@ fn index_element(s: &mut ParserContext) -> Result<IndexElement> {
492492
Ok(Some(v)) => IndexElement::DiscreteSet(v),
493493
Err(err) => return Err(err),
494494
Ok(None) => {
495+
let lo = s.peek().span.lo;
495496
let (exprs, _) = seq(s, index_set_item)?;
496-
let exprs = exprs
497-
.into_iter()
498-
.map(Box::new)
499-
.collect::<Vec<_>>()
500-
.into_boxed_slice();
501-
IndexElement::IndexSet(exprs)
497+
let exprs = list_from_iter(exprs);
498+
IndexElement::IndexSet(IndexSet {
499+
span: s.span(lo),
500+
values: exprs,
501+
})
502502
}
503503
};
504504
Ok(index)
@@ -556,7 +556,7 @@ pub(crate) fn set_expr(s: &mut ParserContext) -> Result<DiscreteSet> {
556556
recovering_token(s, TokenKind::Close(Delim::Brace));
557557
Ok(DiscreteSet {
558558
span: s.span(lo),
559-
values: exprs.into_boxed_slice(),
559+
values: list_from_iter(exprs),
560560
})
561561
}
562562

0 commit comments

Comments
 (0)