microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.29.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/compiler/qsc_codegen/src/qsharp.rs

862lines · modeblame

8bcde035Ian Davis2 years ago1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#[cfg(test)]
5mod spec_decls;
6
7#[cfg(test)]
8mod tests;
9
10#[cfg(test)]
83aa5c2bIan Davis1 years ago11pub mod test_utils;
8bcde035Ian Davis2 years ago12
13use std::io::Write;
14use std::vec;
15
16use qsc_ast::ast::{
29145c51Mine Starks1 years ago17self, Attr, BinOp, Block, CallableBody, CallableDecl, CallableKind, Expr, ExprKind,
d5fc73f5Mine Starks1 years ago18FieldAccess, Functor, FunctorExpr, FunctorExprKind, Ident, Idents, ImportKind,
19ImportOrExportItem, Item, ItemKind, Lit, Mutability, Pat, PatKind, Path, PathKind, Pauli,
20QubitInit, QubitInitKind, QubitSource, SetOp, SpecBody, SpecDecl, SpecGen, Stmt, StmtKind,
21StringComponent, TernOp, TopLevelNode, Ty, TyDef, TyDefKind, TyKind, UnOp,
8bcde035Ian Davis2 years ago22};
23use qsc_ast::ast::{Namespace, Package};
24use qsc_ast::visit::Visitor;
25use qsc_formatter::formatter::format_str;
26use qsc_frontend::compile::PackageStore;
27
28fn write<W: Write>(output: W, packages: &[&Package]) {
e938e457orpuente-MS1 years ago29let mut r#gen = QSharpGen::new(output);
8bcde035Ian Davis2 years ago30for package in packages {
e938e457orpuente-MS1 years ago31r#gen.visit_package(package);
8bcde035Ian Davis2 years ago32}
33}
34
35pub fn write_store<W: Write>(output: W, store: &PackageStore) {
e938e457orpuente-MS1 years ago36let mut r#gen = QSharpGen::new(output);
8bcde035Ian Davis2 years ago37for (_, unit) in store {
e938e457orpuente-MS1 years ago38r#gen.visit_package(&unit.ast.package);
8bcde035Ian Davis2 years ago39}
40}
41
42#[must_use]
43pub fn write_store_string(store: &PackageStore) -> Vec<String> {
44let mut package_strings: Vec<_> = vec![];
45for (_, unit) in store {
46package_strings.push(write_package_string(&unit.ast.package));
47}
48package_strings
49}
50
51#[must_use]
52pub fn write_package_string(package: &Package) -> String {
53let mut output = Vec::new();
54write(&mut output, &[package]);
55let s = match std::str::from_utf8(&output) {
56Ok(v) => v.to_owned(),
57Err(e) => format!("Invalid UTF-8 sequence: {e}"),
58};
59
60output.clear();
61format_str(&s)
62}
63
83aa5c2bIan Davis1 years ago64#[must_use]
65pub fn write_stmt_string(stmt: &ast::Stmt) -> String {
66let mut output = Vec::new();
e938e457orpuente-MS1 years ago67let mut r#gen = QSharpGen::new(&mut output);
68r#gen.visit_stmt(stmt);
83aa5c2bIan Davis1 years ago69let s = match std::str::from_utf8(&output) {
70Ok(v) => v.to_owned(),
71Err(e) => format!("Invalid UTF-8 sequence: {e}"),
72};
73
74output.clear();
75format_str(&s)
76}
77
8bcde035Ian Davis2 years ago78struct QSharpGen<W: Write> {
79pub(crate) output: W,
80}
81
82impl<W> QSharpGen<W>
83where
84W: Write,
85{
86pub fn new(output: W) -> Self {
87Self { output }
88}
89
90pub fn write(&mut self, args: &str) {
91write!(&mut self.output, "{args}").expect("write failed");
92}
93
94pub fn writeln(&mut self, args: &str) {
95self.write(args);
96self.write("\n");
97}
98
99/// special case for tuple with one element
100/// otherwise we are changing the semantics of the program
101fn ensure_trailing_comma_for_arity_one_tuples<T>(&mut self, most: &[T]) {
102if most.is_empty() {
103self.write(",");
104}
105}
106}
107
108impl<W: Write> Visitor<'_> for QSharpGen<W> {
109fn visit_package(&mut self, package: &'_ Package) {
110package.nodes.iter().for_each(|n| match n {
111TopLevelNode::Namespace(ns) => {
112self.visit_namespace(ns);
113}
114TopLevelNode::Stmt(stmt) => self.visit_stmt(stmt),
115});
116package.entry.iter().for_each(|e| self.visit_expr(e));
117}
118
119fn visit_namespace(&mut self, namespace: &'_ Namespace) {
120self.write("namespace ");
82fc78d1Alex Hansen2 years ago121self.visit_idents(&namespace.name);
8bcde035Ian Davis2 years ago122self.writeln("{");
123namespace.items.iter().for_each(|i| {
124self.visit_item(i);
125});
126self.write("}");
127}
128
129fn visit_item(&mut self, item: &'_ Item) {
130item.attrs.iter().for_each(|a| self.visit_attr(a));
131match &*item.kind {
132ItemKind::Err => {
133unreachable!()
134}
135ItemKind::Callable(decl) => self.visit_callable_decl(decl),
136ItemKind::Open(ns, alias) => {
137self.write("open ");
74c488b9Mine Starks1 years ago138self.visit_path_kind(ns);
8bcde035Ian Davis2 years ago139if let Some(alias) = alias {
140self.write(" as ");
141self.visit_ident(alias);
142}
143self.writeln(";");
144}
145ItemKind::Ty(ident, def) => {
146self.write("newtype ");
147self.visit_ident(ident);
148self.write(" = ");
149self.visit_ty_def(def);
150self.writeln(";");
151}
eaa558a0Scott Carda2 years ago152ItemKind::Struct(decl) => self.visit_struct_decl(decl),
522206d3Alex Hansen2 years ago153ItemKind::ImportOrExport(decl) => {
154if decl.is_export() {
155self.write("export ");
156} else {
157self.write("import ");
158}
159
160for (
161ix,
162ImportOrExportItem {
74c488b9Mine Starks1 years ago163span: _,
e938e457orpuente-MS1 years ago164path,
d5fc73f5Mine Starks1 years ago165kind,
522206d3Alex Hansen2 years ago166},
167) in decl.items.iter().enumerate()
168{
169let is_last = ix == decl.items.len() - 1;
74c488b9Mine Starks1 years ago170self.visit_path_kind(path);
7f6e3027Alex Hansen1 years ago171
d5fc73f5Mine Starks1 years ago172if let ImportKind::Wildcard = kind {
522206d3Alex Hansen2 years ago173self.write(".*");
174}
7f6e3027Alex Hansen1 years ago175
d5fc73f5Mine Starks1 years ago176if let ImportKind::Direct { alias: Some(alias) } = kind {
7f6e3027Alex Hansen1 years ago177self.write(&format!(" as {}", alias.name));
178}
179
522206d3Alex Hansen2 years ago180if !is_last {
181self.write(", ");
1fcdcc84Stefan J. Wernli1 years ago182}
522206d3Alex Hansen2 years ago183}
7f6e3027Alex Hansen1 years ago184
522206d3Alex Hansen2 years ago185self.write(";");
186}
8bcde035Ian Davis2 years ago187}
188}
189
190fn visit_attr(&mut self, attr: &'_ Attr) {
191self.write("@");
192self.visit_ident(&attr.name);
193self.visit_expr(&attr.arg);
194self.writeln("");
195}
196
197fn visit_ty_def(&mut self, def: &'_ TyDef) {
198match &*def.kind {
da72d57fStefan J. Wernli6 months ago199TyDefKind::Field(name, ty, _) => {
a5a7a903orpuente-MS2 years ago200if let Some(n) = name {
8bcde035Ian Davis2 years ago201self.visit_ident(n);
202self.write(": ");
203}
204self.visit_ty(ty);
205}
206TyDefKind::Paren(def) => self.visit_ty_def(def),
207TyDefKind::Tuple(defs) => {
208self.write("(");
209if let Some((last, most)) = defs.split_last() {
210for i in most {
211self.visit_ty_def(i);
212self.write(", ");
213}
214self.visit_ty_def(last);
215self.ensure_trailing_comma_for_arity_one_tuples(most);
216}
217self.write(")");
218}
219TyDefKind::Err => {}
220}
221}
222
223fn visit_callable_decl(&mut self, decl: &'_ CallableDecl) {
224match decl.kind {
225CallableKind::Function => self.write("function "),
226CallableKind::Operation => self.write("operation "),
227}
228self.visit_ident(&decl.name);
229if !decl.generics.is_empty() {
230self.write("<");
231if let Some((last, most)) = decl.generics.split_last() {
232for i in most {
97385cd1Alex Hansen1 years ago233self.visit_ident(&i.ty);
8bcde035Ian Davis2 years ago234self.write(", ");
235}
97385cd1Alex Hansen1 years ago236self.visit_ident(&last.ty);
8bcde035Ian Davis2 years ago237}
238
239self.write(">");
240}
241
242self.visit_pat(&decl.input);
243self.write(" : ");
244self.visit_ty(&decl.output);
245if let Some(functors) = decl.functors.as_deref() {
246self.write(" is ");
247self.visit_functor_expr(functors);
248}
249
250match &*decl.body {
251CallableBody::Block(block) => {
252self.visit_block(block);
253}
254CallableBody::Specs(specs) => {
255self.writeln("{");
256specs.iter().for_each(|s| self.visit_spec_decl(s));
257self.writeln("}");
258}
259}
260}
261
eaa558a0Scott Carda2 years ago262fn visit_struct_decl(&mut self, decl: &'_ ast::StructDecl) {
263self.write("struct ");
264self.visit_ident(&decl.name);
265self.writeln(" {");
266if let Some((last, most)) = decl.fields.split_last() {
267for i in most {
268self.visit_field_def(i);
269self.write(", ");
270}
271self.visit_field_def(last);
272}
273self.writeln("}");
274}
275
276fn visit_field_def(&mut self, def: &'_ ast::FieldDef) {
277self.visit_ident(&def.name);
278self.write(" : ");
279self.visit_ty(&def.ty);
280}
281
8bcde035Ian Davis2 years ago282fn visit_spec_decl(&mut self, decl: &'_ SpecDecl) {
283match decl.spec {
284ast::Spec::Body => self.write("body "),
285ast::Spec::Adj => self.write("adjoint "),
286ast::Spec::Ctl => self.write("controlled "),
287ast::Spec::CtlAdj => self.write("controlled adjoint "),
288}
289match &decl.body {
290SpecBody::Gen(spec) => match spec {
291SpecGen::Auto => self.writeln("auto;"),
292SpecGen::Distribute => self.writeln("distribute;"),
293SpecGen::Intrinsic => self.writeln("intrinsic;"),
294SpecGen::Invert => self.writeln("invert;"),
295SpecGen::Slf => self.writeln("self;"),
296},
297SpecBody::Impl(pat, block) => {
298self.visit_pat(pat);
299self.visit_block(block);
300}
301}
302}
303
304fn visit_functor_expr(&mut self, expr: &'_ FunctorExpr) {
305match &*expr.kind {
306FunctorExprKind::BinOp(op, lhs, rhs) => {
307self.visit_functor_expr(lhs);
308match op {
309SetOp::Union => self.write(" + "),
310SetOp::Intersect => self.write(" * "),
311}
312self.visit_functor_expr(rhs);
313}
314FunctorExprKind::Lit(functor) => match functor {
315Functor::Adj => self.write("Adj"),
316Functor::Ctl => self.write("Ctl"),
317},
318FunctorExprKind::Paren(expr) => {
319self.write("(");
320self.visit_functor_expr(expr);
321self.write(")");
322}
323}
324}
325
326fn visit_ty(&mut self, ty: &'_ Ty) {
327match &*ty.kind {
328TyKind::Array(item) => {
329self.visit_ty(item);
330self.write("[]");
331}
332TyKind::Arrow(kind, lhs, rhs, functors) => {
333self.visit_ty(lhs);
334match kind {
335CallableKind::Function => self.write(" -> "),
336CallableKind::Operation => self.write(" => "),
337}
338self.visit_ty(rhs);
339if let Some(functors) = functors.as_deref() {
340self.write(" is ");
341self.visit_functor_expr(functors);
342}
343}
344TyKind::Hole => self.write("_"),
345TyKind::Paren(ty) => {
346self.write("(");
347self.visit_ty(ty);
348self.write(")");
349}
74c488b9Mine Starks1 years ago350TyKind::Path(path) => self.visit_path_kind(path),
97385cd1Alex Hansen1 years ago351TyKind::Param(name) => self.visit_ident(&name.ty),
8bcde035Ian Davis2 years ago352TyKind::Tuple(tys) => {
353if tys.is_empty() {
354self.write("()");
355} else {
356self.write("(");
357if let Some((last, most)) = tys.split_last() {
358for t in most {
359self.visit_ty(t);
360self.write(", ");
361}
362self.visit_ty(last);
363self.ensure_trailing_comma_for_arity_one_tuples(most);
364}
365self.write(")");
366}
367}
368TyKind::Err => unreachable!(),
369}
370}
371
372fn visit_block(&mut self, block: &'_ Block) {
373self.writeln(" {");
374block.stmts.iter().for_each(|s| {
375self.visit_stmt(s);
376});
377self.writeln("}");
378}
379
380fn visit_stmt(&mut self, stmt: &'_ Stmt) {
381match &*stmt.kind {
382StmtKind::Empty | StmtKind::Err => {}
383StmtKind::Semi(expr) => {
384self.visit_expr(expr);
385self.writeln(";");
386}
387StmtKind::Expr(expr) => {
388self.visit_expr(expr);
389}
390StmtKind::Item(item) => self.visit_item(item),
391StmtKind::Local(mutability, pat, value) => {
392match mutability {
393Mutability::Mutable => self.write("mutable "),
394Mutability::Immutable => self.write("let "),
395}
396self.visit_pat(pat);
397self.write(" = ");
398self.visit_expr(value);
399self.writeln(";");
400}
401StmtKind::Qubit(source, pat, init, block) => {
402match source {
403QubitSource::Dirty => self.write("borrow "),
404QubitSource::Fresh => self.write("use "),
405}
406self.visit_pat(pat);
407self.write(" = ");
408self.visit_qubit_init(init);
409if let Some(b) = block {
410self.visit_block(b);
411} else {
412self.writeln(";");
413}
414}
415}
416}
417
418#[allow(clippy::too_many_lines)]
419fn visit_expr(&mut self, expr: &'_ Expr) {
420match &*expr.kind {
421ExprKind::Array(exprs) => {
422self.write("[");
423if let Some((last, most)) = exprs.split_last() {
424for e in most {
425self.visit_expr(e);
426self.write(", ");
427}
428self.visit_expr(last);
429}
430self.write("]");
431}
432ExprKind::ArrayRepeat(item, size) => {
433self.write("[");
434self.visit_expr(item);
435self.write(", size = ");
436self.visit_expr(size);
437self.write("]");
438}
439ExprKind::Assign(lhs, rhs) => {
440self.write("set ");
441self.visit_expr(lhs);
442self.write(" = ");
443self.visit_expr(rhs);
444}
445ExprKind::AssignOp(op, lhs, rhs) => {
446self.write("set ");
447self.visit_expr(lhs);
448self.write(" ");
449let op_str = binop_as_str(op);
450self.write(op_str);
451self.write("= ");
452self.visit_expr(rhs);
453}
454ExprKind::BinOp(op, lhs, rhs) => {
455self.visit_expr(lhs);
456self.write(" ");
457let op_str = binop_as_str(op);
458self.write(op_str);
459self.write(" ");
460self.visit_expr(rhs);
461}
462ExprKind::AssignUpdate(record, index, value) => {
463self.write("set ");
464self.visit_expr(record);
465self.write(" w/= ");
466self.visit_expr(index);
467self.write(" <- ");
468self.visit_expr(value);
469}
470ExprKind::Block(block) => self.visit_block(block),
471ExprKind::Call(callee, arg) => {
472self.visit_expr(callee);
473self.visit_expr(arg);
474}
475ExprKind::Conjugate(within, apply) => {
476self.write("within");
477self.visit_block(within);
478self.write("apply");
479self.visit_block(apply);
480}
481ExprKind::Fail(msg) => {
482self.write("fail ");
483self.visit_expr(msg);
484}
29145c51Mine Starks1 years ago485ExprKind::Field(record, ast::FieldAccess::Ok(name)) => {
8bcde035Ian Davis2 years ago486self.visit_expr(record);
843e7b54Scott Carda2 years ago487self.write(".");
8bcde035Ian Davis2 years ago488self.visit_ident(name);
489}
490ExprKind::For(pat, iter, block) => {
491self.write("for ");
492self.visit_pat(pat);
493self.write(" in ");
494self.visit_expr(iter);
495self.write(" ");
496self.visit_block(block);
497}
498ExprKind::If(cond, body, otherwise) => {
499self.write("if ");
500self.visit_expr(cond);
501self.write(" ");
502self.visit_block(body);
a5a7a903orpuente-MS2 years ago503if let Some(expr) = otherwise {
8bcde035Ian Davis2 years ago504if matches!(*expr.kind, ExprKind::If(..)) {
505// visiting expr as if writes 'if' to make 'elif'
506self.write(" el");
507} else {
508self.write(" else ");
509}
510self.visit_expr(expr);
511}
512}
513ExprKind::Index(array, index) => {
514self.visit_expr(array);
515self.write("[");
516self.visit_expr(index);
517self.write("]");
518}
519ExprKind::Interpolate(components) => {
520self.write("$\"");
521for component in components.as_ref() {
522match component {
523StringComponent::Expr(expr) => {
524self.write("{");
525self.visit_expr(expr.as_ref());
526self.write("}");
527}
528StringComponent::Lit(lit) => {
529self.write(lit);
530}
531}
532}
533self.write("\"");
534}
535ExprKind::Lambda(kind, pat, expr) => {
536self.visit_pat(pat);
537match kind {
538CallableKind::Function => self.write(" -> "),
539CallableKind::Operation => self.write(" => "),
540}
541self.visit_expr(expr);
542}
543ExprKind::Paren(expr) => {
544self.write("(");
545self.visit_expr(expr);
546self.write(")");
547}
548ExprKind::Return(expr) => {
549self.write("return ");
550self.visit_expr(expr);
551}
74c488b9Mine Starks1 years ago552ExprKind::Struct(PathKind::Ok(path), copy, assigns) => {
eaa558a0Scott Carda2 years ago553self.write("new ");
74c488b9Mine Starks1 years ago554self.visit_path(path);
eaa558a0Scott Carda2 years ago555self.writeln(" {");
556if let Some(copy) = copy {
557self.write("...");
558self.visit_expr(copy);
559if !assigns.is_empty() {
560self.writeln(",");
561}
562}
563if let Some((last, most)) = assigns.split_last() {
564for assign in most {
565self.visit_field_assign(assign);
566self.writeln(",");
567}
568self.visit_field_assign(last);
569self.writeln("");
570}
571self.writeln("}");
572}
8bcde035Ian Davis2 years ago573ExprKind::UnOp(op, expr) => {
574let op_str = unop_as_str(op);
575if op == &UnOp::Unwrap {
576self.visit_expr(expr);
577self.write(op_str);
578} else {
579self.write(op_str);
580self.visit_expr(expr);
581}
582}
74c488b9Mine Starks1 years ago583ExprKind::Path(PathKind::Ok(path)) => self.visit_path(path),
8bcde035Ian Davis2 years ago584ExprKind::Range(start, step, end) => {
585// A range: `start..step..end`, `start..end`, `start...`, `...end`, or `...`.
586match (start, step, end) {
587(None, None, None) => {
588self.write("...");
589}
590(None, None, Some(end)) => {
591self.write("...");
592self.visit_expr(end);
593}
594(None, Some(step), None) => {
595self.write("...");
596self.visit_expr(step);
597self.write("...");
598}
599(None, Some(step), Some(end)) => {
600self.write("...");
601self.visit_expr(step);
602self.write("..");
603self.visit_expr(end);
604}
605(Some(start), None, None) => {
606self.visit_expr(start);
607self.write("...");
608}
609(Some(start), None, Some(end)) => {
610self.visit_expr(start);
611self.write("..");
612self.visit_expr(end);
613}
614(Some(start), Some(step), None) => {
615self.visit_expr(start);
616self.write("..");
617self.visit_expr(step);
618self.write("...");
619}
620(Some(start), Some(step), Some(end)) => {
621self.visit_expr(start);
622self.write("..");
623self.visit_expr(step);
624self.write("..");
625self.visit_expr(end);
626}
627}
628}
629ExprKind::Repeat(body, until, fixup) => {
630self.write("repeat ");
631self.visit_block(body);
632self.write("until ");
633self.visit_expr(until);
a5a7a903orpuente-MS2 years ago634if let Some(fixup) = fixup {
8bcde035Ian Davis2 years ago635self.write(" fixup ");
636self.visit_block(fixup);
637}
638}
639ExprKind::TernOp(op, e1, e2, e3) => {
640match op {
641TernOp::Cond => {
642// Conditional: `a ? b | c`.
643self.visit_expr(e1);
644self.write(" ? ");
645self.visit_expr(e2);
646self.write(" | ");
647self.visit_expr(e3);
648}
649TernOp::Update => {
650// Aggregate update: `a w/ b <- c`.
651self.visit_expr(e1);
652self.write(" w/ ");
653self.visit_expr(e2);
654self.write(" <- ");
655self.visit_expr(e3);
656}
657}
658}
659ExprKind::Tuple(exprs) => {
660self.write("(");
661if let Some((last, most)) = exprs.split_last() {
662for e in most {
663self.visit_expr(e);
664self.write(", ");
665}
666self.visit_expr(last);
667self.ensure_trailing_comma_for_arity_one_tuples(most);
668}
669self.write(")");
670}
671ExprKind::While(cond, block) => {
672self.write("while ");
673self.visit_expr(cond);
674self.visit_block(block);
675}
676ExprKind::Lit(lit) => match lit.as_ref() {
677Lit::BigInt(value) => {
678self.write(value.to_string().as_str());
679self.write("L");
680}
681Lit::Bool(value) => {
682if *value {
683self.write("true");
684} else {
685self.write("false");
686}
687}
688Lit::Double(value) => {
689let num_str = if value.fract() == 0.0 {
690format!("{value}.")
691} else {
692format!("{value}")
693};
694self.write(&num_str);
695}
9284f425Stefan J. Wernli10 months ago696Lit::Imaginary(value) => {
697let num_str = if value.fract() == 0.0 {
698format!("{value}.i")
699} else {
700format!("{value}i")
701};
702self.write(&num_str);
703}
8bcde035Ian Davis2 years ago704Lit::Int(value) => self.write(&value.to_string()),
705Lit::Pauli(value) => match value {
706Pauli::I => self.write("PauliI"),
707Pauli::X => self.write("PauliX"),
708Pauli::Y => self.write("PauliY"),
709Pauli::Z => self.write("PauliZ"),
710},
711Lit::Result(value) => match value {
712ast::Result::One => self.write("One"),
713ast::Result::Zero => self.write("Zero"),
714},
715Lit::String(value) => {
716self.write("\"");
717self.write(value.as_ref());
718self.write("\"");
719}
720},
721ExprKind::Hole => {
722self.write("_");
723}
e67f7688Ian Davis1 years ago724ExprKind::Err => {}
725ExprKind::Path(PathKind::Err(_))
29145c51Mine Starks1 years ago726| ExprKind::Struct(PathKind::Err(_), ..)
727| ExprKind::Field(_, FieldAccess::Err) => {
8bcde035Ian Davis2 years ago728unreachable!();
729}
730}
731}
732
eaa558a0Scott Carda2 years ago733fn visit_field_assign(&mut self, assign: &'_ ast::FieldAssign) {
734self.visit_ident(&assign.field);
735self.write(" = ");
736self.visit_expr(&assign.value);
737}
738
8bcde035Ian Davis2 years ago739fn visit_pat(&mut self, pat: &'_ Pat) {
740match &*pat.kind {
741PatKind::Bind(name, ty) => {
742self.visit_ident(name);
743
a5a7a903orpuente-MS2 years ago744if let Some(t) = ty {
8bcde035Ian Davis2 years ago745self.write(": ");
746self.visit_ty(t);
747}
748}
749PatKind::Discard(ty) => {
750self.write("_");
a5a7a903orpuente-MS2 years ago751if let Some(t) = ty {
8bcde035Ian Davis2 years ago752self.write(": ");
753self.visit_ty(t);
754}
755}
756PatKind::Elided => {
757self.write("...");
758}
759PatKind::Paren(pat) => {
760self.write("(");
761self.visit_pat(pat);
762self.write(")");
763}
764PatKind::Tuple(pats) => {
765self.write("(");
766if let Some((last, most)) = pats.split_last() {
767for pat in most {
768self.visit_pat(pat);
769self.write(", ");
770}
771self.visit_pat(last);
772self.ensure_trailing_comma_for_arity_one_tuples(most);
773}
774self.write(")");
775}
776PatKind::Err => {
777unreachable!();
778}
779}
780}
781
782fn visit_qubit_init(&mut self, init: &'_ QubitInit) {
783match &*init.kind {
784QubitInitKind::Array(len) => {
785self.write("Qubit[");
786self.visit_expr(len);
787self.write("]");
788}
789QubitInitKind::Paren(init) => self.visit_qubit_init(init),
790QubitInitKind::Single => {
791self.write("Qubit()");
792}
793QubitInitKind::Tuple(inits) => {
794self.write("(");
795if let Some((last, most)) = inits.split_last() {
796for init in most {
797self.visit_qubit_init(init);
798self.write(", ");
799}
800self.visit_qubit_init(last);
801self.ensure_trailing_comma_for_arity_one_tuples(most);
802}
803self.write(")");
804}
805QubitInitKind::Err => unreachable!(),
806}
807}
808
809fn visit_path(&mut self, path: &'_ Path) {
843e7b54Scott Carda2 years ago810if let Some(parts) = &path.segments {
811self.visit_idents(parts);
8bcde035Ian Davis2 years ago812self.write(".");
813}
814self.visit_ident(&path.name);
815}
816
817fn visit_ident(&mut self, id: &'_ Ident) {
818self.write(&id.name);
819}
82fc78d1Alex Hansen2 years ago820
74c488b9Mine Starks1 years ago821fn visit_idents(&mut self, idents: &'_ [Ident]) {
822self.write(&idents.full_name());
82fc78d1Alex Hansen2 years ago823}
8bcde035Ian Davis2 years ago824}
825
826fn binop_as_str(op: &BinOp) -> &str {
827match op {
828BinOp::Add => "+",
829BinOp::AndB => "&&&",
830BinOp::AndL => "and",
831BinOp::Div => "/",
832BinOp::Eq => "==",
833BinOp::Exp => "^",
834BinOp::Gt => ">",
835BinOp::Gte => ">=",
836BinOp::Lt => "<",
837BinOp::Lte => "<=",
838BinOp::Mod => "%",
839BinOp::Mul => "*",
840BinOp::Neq => "!=",
841BinOp::OrB => "|||",
842BinOp::OrL => "or",
843BinOp::Shl => "<<<",
844BinOp::Shr => ">>>",
845BinOp::Sub => "-",
846BinOp::XorB => "^^^",
847}
848}
849
850fn unop_as_str(op: &UnOp) -> &str {
851match op {
852UnOp::Functor(functor) => match functor {
853Functor::Adj => "Adjoint ",
854Functor::Ctl => "Controlled ",
855},
856UnOp::Neg => "-",
857UnOp::NotB => "~~~",
858UnOp::NotL => "not ",
859UnOp::Pos => "+",
860UnOp::Unwrap => "!",
861}
862}