microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billt/revert-mimalloc

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_hir/src/hir.rs

1432lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! The high-level intermediate representation for Q#. HIR is lowered from the AST.
5
6#![warn(missing_docs)]
7
8use crate::ty::{Arrow, FunctorSet, FunctorSetValue, GenericArg, GenericParam, Scheme, Ty, Udt};
9use indenter::{indented, Indented};
10use num_bigint::BigInt;
11use qsc_data_structures::{index_map::IndexMap, span::Span};
12use std::{
13 cmp::Ordering,
14 fmt::{self, Debug, Display, Formatter, Write},
15 hash::{Hash, Hasher},
16 rc::Rc,
17 result,
18 str::FromStr,
19};
20
21fn set_indentation<'a, 'b>(
22 indent: Indented<'a, Formatter<'b>>,
23 level: usize,
24) -> Indented<'a, Formatter<'b>> {
25 match level {
26 0 => indent.with_str(""),
27 1 => indent.with_str(" "),
28 2 => indent.with_str(" "),
29 _ => unimplemented!("intentation level not supported"),
30 }
31}
32
33/// A unique identifier for an HIR node.
34#[derive(Clone, Copy, Debug)]
35pub struct NodeId(u32);
36
37impl NodeId {
38 const DEFAULT_VALUE: u32 = u32::MAX;
39
40 /// The ID of the first node.
41 pub const FIRST: Self = Self(0);
42
43 /// The successor of this ID.
44 #[must_use]
45 pub fn successor(self) -> Self {
46 Self(self.0 + 1)
47 }
48
49 /// True if this is the default ID.
50 #[must_use]
51 pub fn is_default(self) -> bool {
52 self.0 == Self::DEFAULT_VALUE
53 }
54}
55
56impl Default for NodeId {
57 fn default() -> Self {
58 Self(Self::DEFAULT_VALUE)
59 }
60}
61
62impl Display for NodeId {
63 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
64 if self.is_default() {
65 f.write_str("_id_")
66 } else {
67 Display::fmt(&self.0, f)
68 }
69 }
70}
71
72impl From<NodeId> for usize {
73 fn from(value: NodeId) -> Self {
74 assert!(!value.is_default(), "default node ID should be replaced");
75 value.0 as usize
76 }
77}
78
79impl From<usize> for NodeId {
80 fn from(value: usize) -> Self {
81 Self(value.try_into().expect("NodeId value should fit into u32"))
82 }
83}
84
85impl PartialEq for NodeId {
86 fn eq(&self, other: &Self) -> bool {
87 assert!(!self.is_default(), "default node ID should be replaced");
88 self.0 == other.0
89 }
90}
91
92impl Eq for NodeId {}
93
94impl PartialOrd for NodeId {
95 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
96 Some(self.cmp(other))
97 }
98}
99
100impl Ord for NodeId {
101 fn cmp(&self, other: &Self) -> Ordering {
102 assert!(!self.is_default(), "default node ID should be replaced");
103 self.0.cmp(&other.0)
104 }
105}
106
107impl Hash for NodeId {
108 fn hash<H: Hasher>(&self, state: &mut H) {
109 self.0.hash(state);
110 }
111}
112
113/// A unique identifier for a package within a package store.
114#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
115pub struct PackageId(usize);
116
117impl PackageId {
118 /// The package ID of the core library.
119 pub const CORE: Self = Self(0);
120
121 /// The successor of this ID.
122 #[must_use]
123 pub fn successor(self) -> Self {
124 Self(self.0 + 1)
125 }
126}
127
128impl Display for PackageId {
129 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
130 Display::fmt(&self.0, f)
131 }
132}
133
134impl From<PackageId> for usize {
135 fn from(value: PackageId) -> Self {
136 value.0
137 }
138}
139
140impl From<usize> for PackageId {
141 fn from(value: usize) -> Self {
142 PackageId(value)
143 }
144}
145
146/// A unique identifier for an item within a package.
147#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
148pub struct LocalItemId(usize);
149
150impl LocalItemId {
151 /// The successor of this ID.
152 #[must_use]
153 pub fn successor(self) -> Self {
154 Self(self.0 + 1)
155 }
156}
157
158impl Display for LocalItemId {
159 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
160 Display::fmt(&self.0, f)
161 }
162}
163
164impl From<usize> for LocalItemId {
165 fn from(value: usize) -> Self {
166 Self(value)
167 }
168}
169
170impl From<LocalItemId> for usize {
171 fn from(value: LocalItemId) -> Self {
172 value.0
173 }
174}
175
176/// A unique identifier for an item within a package store.
177#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
178pub struct ItemId {
179 /// The package ID or `None` for the local package.
180 pub package: Option<PackageId>,
181 /// The item ID.
182 pub item: LocalItemId,
183}
184
185impl Display for ItemId {
186 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
187 match self.package {
188 None => write!(f, "Item {}", self.item),
189 Some(package) => write!(f, "Item {} (Package {package})", self.item),
190 }
191 }
192}
193
194/// The status of an item.
195#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
196pub enum ItemStatus {
197 /// The item is defined normally.
198 Available,
199 /// The item is marked as unimplemented and uses are disallowed.
200 Unimplemented,
201}
202
203impl ItemStatus {
204 /// Create an item status from the given attributes list.
205 #[must_use]
206 pub fn from_attrs(attrs: &[Attr]) -> Self {
207 for attr in attrs {
208 if *attr == Attr::Unimplemented {
209 return Self::Unimplemented;
210 }
211 }
212 Self::Available
213 }
214}
215
216/// A resolution. This connects a usage of a name with the declaration of that name by uniquely
217/// identifying the node that declared it.
218#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
219pub enum Res {
220 /// An invalid resolution.
221 Err,
222 /// A global item.
223 Item(ItemId),
224 /// A local variable.
225 Local(NodeId),
226}
227
228impl Res {
229 /// Returns an updated resolution with the given package ID.
230 #[must_use]
231 pub fn with_package(&self, package: PackageId) -> Self {
232 match self {
233 Res::Item(id) if id.package.is_none() => Res::Item(ItemId {
234 package: Some(package),
235 item: id.item,
236 }),
237 _ => *self,
238 }
239 }
240}
241
242impl Display for Res {
243 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
244 match self {
245 Res::Err => f.write_str("Err"),
246 Res::Item(item) => Display::fmt(item, f),
247 Res::Local(node) => write!(f, "Local {node}"),
248 }
249 }
250}
251
252/// The root node of the HIR.
253#[derive(Clone, Debug, Default)]
254pub struct Package {
255 /// The items in the package.
256 pub items: IndexMap<LocalItemId, Item>,
257 /// The top-level statements in the package.
258 pub stmts: Vec<Stmt>,
259 /// The entry expression for an executable package.
260 pub entry: Option<Expr>,
261}
262
263impl Display for Package {
264 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
265 let mut indent = set_indentation(indented(f), 0);
266 write!(indent, "Package:")?;
267 indent = set_indentation(indent, 1);
268 if let Some(e) = &self.entry {
269 write!(indent, "\nentry expression: {e}")?;
270 }
271 for item in self.items.values() {
272 write!(indent, "\n{item}")?;
273 }
274 for stmt in &self.stmts {
275 write!(indent, "\n{stmt}")?;
276 }
277 Ok(())
278 }
279}
280
281/// An item.
282#[derive(Clone, Debug, PartialEq)]
283pub struct Item {
284 /// The ID.
285 pub id: LocalItemId,
286 /// The span.
287 pub span: Span,
288 /// The parent item.
289 pub parent: Option<LocalItemId>,
290 /// The documentation.
291 pub doc: Rc<str>,
292 /// The attributes.
293 pub attrs: Vec<Attr>,
294 /// The visibility.
295 pub visibility: Visibility,
296 /// The item kind.
297 pub kind: ItemKind,
298}
299
300impl Display for Item {
301 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
302 let mut indent = set_indentation(indented(f), 0);
303 write!(
304 indent,
305 "Item {} {} ({:?}):",
306 self.id, self.span, self.visibility
307 )?;
308
309 indent = set_indentation(indent, 1);
310 if let Some(parent) = self.parent {
311 write!(indent, "\nParent: {parent}")?;
312 }
313
314 if !self.doc.is_empty() {
315 write!(indent, "\nDoc:")?;
316 indent = set_indentation(indent, 2);
317 write!(indent, "\n{}", self.doc)?;
318 indent = set_indentation(indent, 1);
319 }
320
321 for attr in &self.attrs {
322 write!(indent, "\n{attr:?}")?;
323 }
324
325 write!(indent, "\n{}", self.kind)?;
326 Ok(())
327 }
328}
329
330/// An item kind.
331#[derive(Clone, Debug, PartialEq)]
332pub enum ItemKind {
333 /// A `function` or `operation` declaration.
334 Callable(CallableDecl),
335 /// A `namespace` declaration.
336 Namespace(Ident, Vec<LocalItemId>),
337 /// A `newtype` declaration.
338 Ty(Ident, Udt),
339}
340
341impl Display for ItemKind {
342 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
343 match self {
344 ItemKind::Callable(decl) => write!(f, "{decl}"),
345 ItemKind::Namespace(name, items) => {
346 write!(f, "Namespace ({name}):")?;
347 let mut items = items.iter();
348 if let Some(item) = items.next() {
349 write!(f, " Item {item}")?;
350 for item in items {
351 write!(f, ", Item {item}")?;
352 }
353 Ok(())
354 } else {
355 write!(f, " <empty>")
356 }
357 }
358 ItemKind::Ty(name, udt) => write!(f, "Type ({name}): {udt}"),
359 }
360 }
361}
362
363/// A callable declaration header.
364#[derive(Clone, Debug, PartialEq)]
365pub struct CallableDecl {
366 /// The node ID.
367 pub id: NodeId,
368 /// The span.
369 pub span: Span,
370 /// The callable kind.
371 pub kind: CallableKind,
372 /// The name of the callable.
373 pub name: Ident,
374 /// The generic parameters to the callable.
375 pub generics: Vec<GenericParam>,
376 /// The input to the callable.
377 pub input: Pat,
378 /// The return type of the callable.
379 pub output: Ty,
380 /// The functors supported by the callable.
381 pub functors: FunctorSetValue,
382 /// The callable body.
383 pub body: SpecDecl,
384 /// The adjoint specialization.
385 pub adj: Option<SpecDecl>,
386 /// The controlled specialization.
387 pub ctl: Option<SpecDecl>,
388 /// The controlled adjoint specialization.
389 pub ctl_adj: Option<SpecDecl>,
390}
391
392impl CallableDecl {
393 /// The type scheme of the callable.
394 #[must_use]
395 pub fn scheme(&self) -> Scheme {
396 Scheme::new(
397 self.generics.clone(),
398 Box::new(Arrow {
399 kind: self.kind,
400 input: Box::new(self.input.ty.clone()),
401 output: Box::new(self.output.clone()),
402 functors: FunctorSet::Value(self.functors),
403 }),
404 )
405 }
406}
407
408impl Display for CallableDecl {
409 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
410 let mut indent = set_indentation(indented(f), 0);
411 write!(
412 indent,
413 "Callable {} {} ({}):",
414 self.id, self.span, self.kind
415 )?;
416 indent = set_indentation(indent, 1);
417 write!(indent, "\nname: {}", self.name)?;
418 if !self.generics.is_empty() {
419 write!(indent, "\ngenerics:")?;
420 indent = set_indentation(indent, 2);
421 for (ix, param) in self.generics.iter().enumerate() {
422 write!(indent, "\n{ix}: {param}")?;
423 }
424 indent = set_indentation(indent, 1);
425 }
426 write!(indent, "\ninput: {}", self.input)?;
427 write!(indent, "\noutput: {}", self.output)?;
428 write!(indent, "\nfunctors: {}", self.functors)?;
429 write!(indent, "\nbody: {}", self.body)?;
430 match &self.adj {
431 Some(spec) => write!(indent, "\nadj: {spec}")?,
432 None => write!(indent, "\nadj: <none>")?,
433 }
434 match &self.ctl {
435 Some(spec) => write!(indent, "\nctl: {spec}")?,
436 None => write!(indent, "\nctl: <none>")?,
437 }
438 match &self.ctl_adj {
439 Some(spec) => write!(indent, "\nctl-adj: {spec}")?,
440 None => write!(indent, "\nctl-adj: <none>")?,
441 }
442 Ok(())
443 }
444}
445
446/// A specialization declaration.
447#[derive(Clone, Debug, PartialEq)]
448pub struct SpecDecl {
449 /// The node ID.
450 pub id: NodeId,
451 /// The span.
452 pub span: Span,
453 /// The body of the specialization.
454 pub body: SpecBody,
455}
456
457impl Display for SpecDecl {
458 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
459 write!(f, "SpecDecl {} {}: {}", self.id, self.span, self.body)
460 }
461}
462
463/// The body of a specialization.
464#[derive(Clone, Debug, PartialEq)]
465pub enum SpecBody {
466 /// The strategy to use to automatically generate the specialization.
467 Gen(SpecGen),
468 /// A manual implementation of the specialization.
469 Impl(Option<Pat>, Block),
470}
471
472impl Display for SpecBody {
473 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
474 let mut indent = set_indentation(indented(f), 0);
475 match self {
476 SpecBody::Gen(sg) => write!(indent, "Gen: {sg:?}")?,
477 SpecBody::Impl(p, b) => {
478 write!(indent, "Impl:")?;
479 indent = set_indentation(indent, 1);
480 if let Some(p) = p {
481 write!(indent, "\n{p}")?;
482 }
483 write!(indent, "\n{b}")?;
484 }
485 }
486 Ok(())
487 }
488}
489
490/// A sequenced block of statements.
491#[derive(Clone, Debug, PartialEq)]
492pub struct Block {
493 /// The node ID.
494 pub id: NodeId,
495 /// The span.
496 pub span: Span,
497 /// The block type.
498 pub ty: Ty,
499 /// The statements in the block.
500 pub stmts: Vec<Stmt>,
501}
502
503impl Display for Block {
504 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
505 if self.stmts.is_empty() {
506 write!(f, "Block {} {}: <empty>", self.id, self.span)?;
507 } else {
508 let mut indent = set_indentation(indented(f), 0);
509 write!(
510 indent,
511 "Block {} {} [Type {}]:",
512 self.id, self.span, self.ty
513 )?;
514 indent = set_indentation(indent, 1);
515 for s in &self.stmts {
516 write!(indent, "\n{s}")?;
517 }
518 }
519 Ok(())
520 }
521}
522
523/// A statement.
524#[derive(Clone, Debug, PartialEq)]
525pub struct Stmt {
526 /// The node ID.
527 pub id: NodeId,
528 /// The span.
529 pub span: Span,
530 /// The statement kind.
531 pub kind: StmtKind,
532}
533
534impl Display for Stmt {
535 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
536 write!(f, "Stmt {} {}: {}", self.id, self.span, self.kind)
537 }
538}
539
540/// A statement kind.
541#[derive(Clone, Debug, PartialEq)]
542pub enum StmtKind {
543 /// An expression without a trailing semicolon.
544 Expr(Expr),
545 /// An item.
546 Item(LocalItemId),
547 /// A let or mutable binding: `let a = b;` or `mutable x = b;`.
548 Local(Mutability, Pat, Expr),
549 /// A use or borrow qubit allocation: `use a = b;` or `borrow a = b;`.
550 Qubit(QubitSource, Pat, QubitInit, Option<Block>),
551 /// An expression with a trailing semicolon.
552 Semi(Expr),
553}
554
555impl Display for StmtKind {
556 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
557 let mut indent = set_indentation(indented(f), 0);
558 match self {
559 StmtKind::Expr(e) => write!(indent, "Expr: {e}")?,
560 StmtKind::Item(item) => write!(indent, "Item: {item}")?,
561 StmtKind::Local(m, lhs, rhs) => {
562 write!(indent, "Local ({m:?}):")?;
563 indent = set_indentation(indent, 1);
564 write!(indent, "\n{lhs}")?;
565 write!(indent, "\n{rhs}")?;
566 }
567 StmtKind::Qubit(s, lhs, rhs, block) => {
568 write!(indent, "Qubit ({s:?})")?;
569 indent = set_indentation(indent, 1);
570 write!(indent, "\n{lhs}")?;
571 write!(indent, "\n{rhs}")?;
572 if let Some(b) = block {
573 write!(indent, "\n{b}")?;
574 }
575 }
576 StmtKind::Semi(e) => write!(indent, "Semi: {e}")?,
577 }
578 Ok(())
579 }
580}
581
582/// An expression.
583#[derive(Clone, Debug, Default, PartialEq)]
584pub struct Expr {
585 /// The node ID.
586 pub id: NodeId,
587 /// The span.
588 pub span: Span,
589 /// The expression type.
590 pub ty: Ty,
591 /// The expression kind.
592 pub kind: ExprKind,
593}
594
595impl Display for Expr {
596 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
597 write!(
598 f,
599 "Expr {} {} [Type {}]: {}",
600 self.id, self.span, self.ty, self.kind
601 )
602 }
603}
604
605/// An expression kind.
606#[derive(Clone, Debug, Default, PartialEq)]
607pub enum ExprKind {
608 /// An array: `[a, b, c]`.
609 Array(Vec<Expr>),
610 /// An array constructed by repeating a value: `[a, size = b]`.
611 ArrayRepeat(Box<Expr>, Box<Expr>),
612 /// An assignment: `set a = b`.
613 Assign(Box<Expr>, Box<Expr>),
614 /// An assignment with a compound operator. For example: `set a += b`.
615 AssignOp(BinOp, Box<Expr>, Box<Expr>),
616 /// An assignment with a compound field update operator: `set a w/= B <- c`.
617 AssignField(Box<Expr>, Field, Box<Expr>),
618 /// An assignment with a compound index update operator: `set a w/= b <- c`.
619 AssignIndex(Box<Expr>, Box<Expr>, Box<Expr>),
620 /// A binary operator.
621 BinOp(BinOp, Box<Expr>, Box<Expr>),
622 /// A block: `{ ... }`.
623 Block(Block),
624 /// A call: `a(b)`.
625 Call(Box<Expr>, Box<Expr>),
626 /// A closure that fixes the vector of local variables as arguments to the callable item.
627 Closure(Vec<NodeId>, LocalItemId),
628 /// A conjugation: `within { ... } apply { ... }`.
629 Conjugate(Block, Block),
630 /// A failure: `fail "message"`.
631 Fail(Box<Expr>),
632 /// A field accessor: `a::F`.
633 Field(Box<Expr>, Field),
634 /// A for loop: `for a in b { ... }`.
635 For(Pat, Box<Expr>, Block),
636 /// An unspecified expression, _, which may indicate partial application or a typed hole.
637 Hole,
638 /// An if expression with an optional else block: `if a { ... } else { ... }`.
639 ///
640 /// Note that, as a special case, `elif ...` is effectively parsed as `else if ...`, without a
641 /// block wrapping the `if`. This distinguishes `elif ...` from `else { if ... }`, which does
642 /// have a block.
643 If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
644 /// An index accessor: `a[b]`.
645 Index(Box<Expr>, Box<Expr>),
646 /// A literal.
647 Lit(Lit),
648 /// A range: `start..step..end`, `start..end`, `start...`, `...end`, or `...`.
649 Range(Option<Box<Expr>>, Option<Box<Expr>>, Option<Box<Expr>>),
650 /// A repeat-until loop with an optional fixup: `repeat { ... } until a fixup { ... }`.
651 Repeat(Block, Box<Expr>, Option<Block>),
652 /// A return: `return a`.
653 Return(Box<Expr>),
654 /// A string.
655 String(Vec<StringComponent>),
656 /// Update array index: `a w/ b <- c`.
657 UpdateIndex(Box<Expr>, Box<Expr>, Box<Expr>),
658 /// A tuple: `(a, b, c)`.
659 Tuple(Vec<Expr>),
660 /// A unary operator.
661 UnOp(UnOp, Box<Expr>),
662 /// A record field update: `a w/ B <- c`.
663 UpdateField(Box<Expr>, Field, Box<Expr>),
664 /// A variable and its generic arguments.
665 Var(Res, Vec<GenericArg>),
666 /// A while loop: `while a { ... }`.
667 While(Box<Expr>, Block),
668 /// An invalid expression.
669 #[default]
670 Err,
671}
672
673impl Display for ExprKind {
674 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
675 let mut indent = set_indentation(indented(f), 0);
676 match self {
677 ExprKind::Array(exprs) => display_array(indent, exprs)?,
678 ExprKind::ArrayRepeat(val, size) => display_array_repeat(indent, val, size)?,
679 ExprKind::Assign(lhs, rhs) => display_assign(indent, lhs, rhs)?,
680 ExprKind::AssignOp(op, lhs, rhs) => display_assign_op(indent, *op, lhs, rhs)?,
681 ExprKind::AssignField(record, field, replace) => {
682 display_assign_field(indent, record, field, replace)?;
683 }
684 ExprKind::AssignIndex(container, item, replace) => {
685 display_assign_index(indent, container, item, replace)?;
686 }
687 ExprKind::BinOp(op, lhs, rhs) => display_bin_op(indent, *op, lhs, rhs)?,
688 ExprKind::Block(block) => write!(indent, "Expr Block: {block}")?,
689 ExprKind::Call(callable, arg) => display_call(indent, callable, arg)?,
690 ExprKind::Closure(args, callable) => display_closure(indent, args, *callable)?,
691 ExprKind::Conjugate(within, apply) => display_conjugate(indent, within, apply)?,
692 ExprKind::Err => write!(indent, "Err")?,
693 ExprKind::Fail(e) => write!(indent, "Fail: {e}")?,
694 ExprKind::Field(expr, field) => display_field(indent, expr, field)?,
695 ExprKind::For(iter, iterable, body) => display_for(indent, iter, iterable, body)?,
696 ExprKind::Hole => write!(indent, "Hole")?,
697 ExprKind::If(cond, body, els) => display_if(indent, cond, body, els)?,
698 ExprKind::Index(array, index) => display_index(indent, array, index)?,
699 ExprKind::Lit(lit) => write!(indent, "Lit: {lit}")?,
700 ExprKind::Range(start, step, end) => display_range(indent, start, step, end)?,
701 ExprKind::Repeat(repeat, until, fixup) => display_repeat(indent, repeat, until, fixup)?,
702 ExprKind::Return(e) => write!(indent, "Return: {e}")?,
703 ExprKind::String(components) => display_string(indent, components)?,
704 ExprKind::UpdateIndex(expr1, expr2, expr3) => {
705 display_update_index(indent, expr1, expr2, expr3)?;
706 }
707 ExprKind::Tuple(exprs) => display_tuple(indent, exprs)?,
708 ExprKind::UnOp(op, expr) => display_un_op(indent, *op, expr)?,
709 ExprKind::UpdateField(record, field, replace) => {
710 display_update_field(indent, record, field, replace)?;
711 }
712 ExprKind::Var(res, args) => display_var(indent, *res, args)?,
713 ExprKind::While(cond, block) => display_while(indent, cond, block)?,
714 }
715 Ok(())
716 }
717}
718
719fn display_array(mut indent: Indented<Formatter>, exprs: &Vec<Expr>) -> fmt::Result {
720 write!(indent, "Array:")?;
721 indent = set_indentation(indent, 1);
722 for e in exprs {
723 write!(indent, "\n{e}")?;
724 }
725 Ok(())
726}
727
728fn display_array_repeat(mut indent: Indented<Formatter>, val: &Expr, size: &Expr) -> fmt::Result {
729 write!(indent, "ArrayRepeat:")?;
730 indent = set_indentation(indent, 1);
731 write!(indent, "\n{val}")?;
732 write!(indent, "\n{size}")?;
733 Ok(())
734}
735
736fn display_assign(mut indent: Indented<Formatter>, lhs: &Expr, rhs: &Expr) -> fmt::Result {
737 write!(indent, "Assign:")?;
738 indent = set_indentation(indent, 1);
739 write!(indent, "\n{lhs}")?;
740 write!(indent, "\n{rhs}")?;
741 Ok(())
742}
743
744fn display_assign_op(
745 mut indent: Indented<Formatter>,
746 op: BinOp,
747 lhs: &Expr,
748 rhs: &Expr,
749) -> fmt::Result {
750 write!(indent, "AssignOp ({op:?}):")?;
751 indent = set_indentation(indent, 1);
752 write!(indent, "\n{lhs}")?;
753 write!(indent, "\n{rhs}")?;
754 Ok(())
755}
756
757fn display_assign_field(
758 mut indent: Indented<Formatter>,
759 record: &Expr,
760 field: &Field,
761 replace: &Expr,
762) -> fmt::Result {
763 write!(indent, "AssignField:")?;
764 indent = set_indentation(indent, 1);
765 write!(indent, "\n{record}")?;
766 write!(indent, "\n{field}")?;
767 write!(indent, "\n{replace}")?;
768 Ok(())
769}
770
771fn display_assign_index(
772 mut indent: Indented<Formatter>,
773 array: &Expr,
774 index: &Expr,
775 replace: &Expr,
776) -> fmt::Result {
777 write!(indent, "AssignIndex:")?;
778 indent = set_indentation(indent, 1);
779 write!(indent, "\n{array}")?;
780 write!(indent, "\n{index}")?;
781 write!(indent, "\n{replace}")?;
782 Ok(())
783}
784
785fn display_bin_op(
786 mut indent: Indented<Formatter>,
787 op: BinOp,
788 lhs: &Expr,
789 rhs: &Expr,
790) -> fmt::Result {
791 write!(indent, "BinOp ({op:?}):")?;
792 indent = set_indentation(indent, 1);
793 write!(indent, "\n{lhs}")?;
794 write!(indent, "\n{rhs}")?;
795 Ok(())
796}
797
798fn display_call(mut indent: Indented<Formatter>, callable: &Expr, arg: &Expr) -> fmt::Result {
799 write!(indent, "Call:")?;
800 indent = set_indentation(indent, 1);
801 write!(indent, "\n{callable}")?;
802 write!(indent, "\n{arg}")?;
803 Ok(())
804}
805
806fn display_closure(
807 mut f: Indented<Formatter>,
808 args: &[NodeId],
809 callable: LocalItemId,
810) -> fmt::Result {
811 f.write_str("Closure([")?;
812 let mut args = args.iter();
813 if let Some(arg) = args.next() {
814 write!(f, "{arg}")?;
815 }
816 for arg in args {
817 write!(f, ", {arg}")?;
818 }
819 write!(f, "], {callable})")
820}
821
822fn display_conjugate(
823 mut indent: Indented<Formatter>,
824 within: &Block,
825 apply: &Block,
826) -> fmt::Result {
827 write!(indent, "Conjugate:")?;
828 indent = set_indentation(indent, 1);
829 write!(indent, "\n{within}")?;
830 write!(indent, "\n{apply}")?;
831 Ok(())
832}
833
834fn display_field(mut indent: Indented<Formatter>, expr: &Expr, field: &Field) -> fmt::Result {
835 write!(indent, "Field:")?;
836 indent = set_indentation(indent, 1);
837 write!(indent, "\n{expr}")?;
838 write!(indent, "\n{field:?}")?;
839 Ok(())
840}
841
842fn display_for(
843 mut indent: Indented<Formatter>,
844 iter: &Pat,
845 iterable: &Expr,
846 body: &Block,
847) -> fmt::Result {
848 write!(indent, "For:")?;
849 indent = set_indentation(indent, 1);
850 write!(indent, "\n{iter}")?;
851 write!(indent, "\n{iterable}")?;
852 write!(indent, "\n{body}")?;
853 Ok(())
854}
855
856fn display_if(
857 mut indent: Indented<Formatter>,
858 cond: &Expr,
859 body: &Expr,
860 els: &Option<Box<Expr>>,
861) -> fmt::Result {
862 write!(indent, "If:")?;
863 indent = set_indentation(indent, 1);
864 write!(indent, "\n{cond}")?;
865 write!(indent, "\n{body}")?;
866 if let Some(e) = els {
867 write!(indent, "\n{e}")?;
868 }
869 Ok(())
870}
871
872fn display_index(mut indent: Indented<Formatter>, array: &Expr, index: &Expr) -> fmt::Result {
873 write!(indent, "Index:")?;
874 indent = set_indentation(indent, 1);
875 write!(indent, "\n{array}")?;
876 write!(indent, "\n{index}")?;
877 Ok(())
878}
879
880fn display_range(
881 mut indent: Indented<Formatter>,
882 start: &Option<Box<Expr>>,
883 step: &Option<Box<Expr>>,
884 end: &Option<Box<Expr>>,
885) -> fmt::Result {
886 write!(indent, "Range:")?;
887 indent = set_indentation(indent, 1);
888 match start {
889 Some(e) => write!(indent, "\n{e}")?,
890 None => write!(indent, "\n<no start>")?,
891 }
892 match step {
893 Some(e) => write!(indent, "\n{e}")?,
894 None => write!(indent, "\n<no step>")?,
895 }
896 match end {
897 Some(e) => write!(indent, "\n{e}")?,
898 None => write!(indent, "\n<no end>")?,
899 }
900 Ok(())
901}
902
903fn display_repeat(
904 mut indent: Indented<Formatter>,
905 repeat: &Block,
906 until: &Expr,
907 fixup: &Option<Block>,
908) -> fmt::Result {
909 write!(indent, "Repeat:")?;
910 indent = set_indentation(indent, 1);
911 write!(indent, "\n{repeat}")?;
912 write!(indent, "\n{until}")?;
913 match fixup {
914 Some(b) => write!(indent, "\n{b}")?,
915 None => write!(indent, "\n<no fixup>")?,
916 }
917 Ok(())
918}
919
920fn display_string(mut indent: Indented<Formatter>, components: &[StringComponent]) -> fmt::Result {
921 write!(indent, "String:")?;
922 indent = set_indentation(indent, 1);
923 for component in components {
924 match component {
925 StringComponent::Expr(expr) => write!(indent, "\nExpr: {expr}")?,
926 StringComponent::Lit(str) => write!(indent, "\nLit: {str:?}")?,
927 }
928 }
929
930 Ok(())
931}
932
933fn display_update_index(
934 mut indent: Indented<Formatter>,
935 expr1: &Expr,
936 expr2: &Expr,
937 expr3: &Expr,
938) -> fmt::Result {
939 write!(indent, "UpdateIndex:")?;
940 indent = set_indentation(indent, 1);
941 write!(indent, "\n{expr1}")?;
942 write!(indent, "\n{expr2}")?;
943 write!(indent, "\n{expr3}")?;
944 Ok(())
945}
946
947fn display_tuple(mut indent: Indented<Formatter>, exprs: &Vec<Expr>) -> fmt::Result {
948 if exprs.is_empty() {
949 write!(indent, "Unit")?;
950 } else {
951 write!(indent, "Tuple:")?;
952 indent = set_indentation(indent, 1);
953 for e in exprs {
954 write!(indent, "\n{e}")?;
955 }
956 }
957 Ok(())
958}
959
960fn display_un_op(mut indent: Indented<Formatter>, op: UnOp, expr: &Expr) -> fmt::Result {
961 write!(indent, "UnOp ({op}):")?;
962 indent = set_indentation(indent, 1);
963 write!(indent, "\n{expr}")?;
964 Ok(())
965}
966
967fn display_update_field(
968 mut indent: Indented<Formatter>,
969 record: &Expr,
970 field: &Field,
971 replace: &Expr,
972) -> fmt::Result {
973 write!(indent, "UpdateField:")?;
974 indent = set_indentation(indent, 1);
975 write!(indent, "\n{record}")?;
976 write!(indent, "\n{field}")?;
977 write!(indent, "\n{replace}")?;
978 Ok(())
979}
980
981fn display_var(mut f: Indented<Formatter>, res: Res, args: &[GenericArg]) -> fmt::Result {
982 if args.is_empty() {
983 write!(f, "Var: {res}")
984 } else {
985 write!(f, "Var:")?;
986 f = set_indentation(f, 1);
987 write!(f, "\nres: {res}")?;
988 write!(f, "\ngenerics:")?;
989 f = set_indentation(f, 2);
990 for arg in args {
991 write!(f, "\n{arg}")?;
992 }
993 Ok(())
994 }
995}
996
997fn display_while(mut indent: Indented<Formatter>, cond: &Expr, block: &Block) -> fmt::Result {
998 write!(indent, "While:")?;
999 indent = set_indentation(indent, 1);
1000 write!(indent, "\n{cond}")?;
1001 write!(indent, "\n{block}")?;
1002 Ok(())
1003}
1004
1005/// A string component.
1006#[derive(Clone, Debug, PartialEq)]
1007pub enum StringComponent {
1008 /// An expression.
1009 Expr(Expr),
1010 /// A string literal.
1011 Lit(Rc<str>),
1012}
1013
1014/// A pattern.
1015#[derive(Clone, Debug, Eq, PartialEq)]
1016pub struct Pat {
1017 /// The node ID.
1018 pub id: NodeId,
1019 /// The span.
1020 pub span: Span,
1021 /// The pattern type.
1022 pub ty: Ty,
1023 /// The pattern kind.
1024 pub kind: PatKind,
1025}
1026
1027impl Display for Pat {
1028 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1029 write!(
1030 f,
1031 "Pat {} {} [Type {}]: {}",
1032 self.id, self.span, self.ty, self.kind
1033 )
1034 }
1035}
1036
1037/// A pattern kind.
1038#[derive(Clone, Debug, Eq, PartialEq)]
1039pub enum PatKind {
1040 /// A binding.
1041 Bind(Ident),
1042 /// A discarded binding, `_`.
1043 Discard,
1044 /// A tuple: `(a, b, c)`.
1045 Tuple(Vec<Pat>),
1046 /// An invalid pattern.
1047 Err,
1048}
1049
1050impl Display for PatKind {
1051 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1052 let mut indent = set_indentation(indented(f), 0);
1053 match self {
1054 PatKind::Bind(id) => {
1055 write!(indent, "Bind: {id}")?;
1056 }
1057 PatKind::Discard => write!(indent, "Discard")?,
1058 PatKind::Tuple(ps) => {
1059 if ps.is_empty() {
1060 write!(indent, "Unit")?;
1061 } else {
1062 write!(indent, "Tuple:")?;
1063 indent = set_indentation(indent, 1);
1064 for p in ps {
1065 write!(indent, "\n{p}")?;
1066 }
1067 }
1068 }
1069 PatKind::Err => write!(indent, "Err")?,
1070 }
1071 Ok(())
1072 }
1073}
1074
1075/// A qubit initializer.
1076#[derive(Clone, Debug, PartialEq)]
1077pub struct QubitInit {
1078 /// The node ID.
1079 pub id: NodeId,
1080 /// The span.
1081 pub span: Span,
1082 /// The qubit initializer type.
1083 pub ty: Ty,
1084 /// The qubit initializer kind.
1085 pub kind: QubitInitKind,
1086}
1087
1088impl Display for QubitInit {
1089 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1090 write!(
1091 f,
1092 "QubitInit {} {} [Type {}]: {}",
1093 self.id, self.span, self.ty, self.kind
1094 )
1095 }
1096}
1097
1098/// A qubit initializer kind.
1099#[derive(Clone, Debug, PartialEq)]
1100pub enum QubitInitKind {
1101 /// An array of qubits: `Qubit[a]`.
1102 Array(Box<Expr>),
1103 /// A single qubit: `Qubit()`.
1104 Single,
1105 /// A tuple: `(a, b, c)`.
1106 Tuple(Vec<QubitInit>),
1107 /// An invalid qubit initializer.
1108 Err,
1109}
1110
1111impl Display for QubitInitKind {
1112 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1113 let mut indent = set_indentation(indented(f), 0);
1114 match self {
1115 QubitInitKind::Array(e) => {
1116 write!(indent, "Array:")?;
1117 indent = set_indentation(indent, 1);
1118 write!(indent, "\n{e}")?;
1119 }
1120 QubitInitKind::Single => write!(indent, "Single")?,
1121 QubitInitKind::Tuple(qis) => {
1122 if qis.is_empty() {
1123 write!(indent, "Unit")?;
1124 } else {
1125 write!(indent, "Tuple:")?;
1126 indent = set_indentation(indent, 1);
1127 for qi in qis {
1128 write!(indent, "\n{qi}")?;
1129 }
1130 }
1131 }
1132 QubitInitKind::Err => write!(indent, "Err")?,
1133 }
1134 Ok(())
1135 }
1136}
1137
1138/// An identifier.
1139#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1140pub struct Ident {
1141 /// The node ID.
1142 pub id: NodeId,
1143 /// The span.
1144 pub span: Span,
1145 /// The identifier name.
1146 pub name: Rc<str>,
1147}
1148
1149impl Display for Ident {
1150 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1151 write!(f, "Ident {} {} \"{}\"", self.id, self.span, self.name)
1152 }
1153}
1154
1155/// An attribute.
1156#[derive(Clone, Debug, PartialEq)]
1157pub enum Attr {
1158 /// Provide pre-processing information about when an item should be included in compilation.
1159 Config,
1160 /// Indicates that a callable is an entry point to a program.
1161 EntryPoint,
1162 /// Indicates that an item does not have an implementation available for use.
1163 Unimplemented,
1164}
1165
1166impl FromStr for Attr {
1167 type Err = ();
1168
1169 fn from_str(s: &str) -> result::Result<Self, Self::Err> {
1170 match s {
1171 "Config" => Ok(Self::Config),
1172 "EntryPoint" => Ok(Self::EntryPoint),
1173 "Unimplemented" => Ok(Self::Unimplemented),
1174 _ => Err(()),
1175 }
1176 }
1177}
1178
1179/// A field.
1180#[derive(Clone, Debug, Eq, PartialEq)]
1181pub enum Field {
1182 /// A field path.
1183 Path(FieldPath),
1184 /// A primitive field for a built-in type.
1185 Prim(PrimField),
1186 /// An invalid field.
1187 Err,
1188}
1189
1190impl Display for Field {
1191 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1192 match self {
1193 Field::Path(path) => write!(f, "Path({:?})", path.indices),
1194 Field::Prim(prim) => write!(f, "Prim({prim:?}"),
1195 Field::Err => f.write_str("Err"),
1196 }
1197 }
1198}
1199
1200/// A path to a field in a tuple or user-defined type.
1201#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
1202pub struct FieldPath {
1203 /// The tuple item indices to follow in order from top to bottom.
1204 pub indices: Vec<usize>,
1205}
1206
1207/// A primitive field for a built-in type.
1208#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1209pub enum PrimField {
1210 /// The start of a range.
1211 Start,
1212 /// The step of a range.
1213 Step,
1214 /// The end of a range.
1215 End,
1216}
1217
1218impl FromStr for PrimField {
1219 type Err = ();
1220
1221 fn from_str(s: &str) -> result::Result<Self, <Self as FromStr>::Err> {
1222 match s {
1223 "Start" => Ok(Self::Start),
1224 "Step" => Ok(Self::Step),
1225 "End" => Ok(Self::End),
1226 _ => Err(()),
1227 }
1228 }
1229}
1230
1231/// The visibility of a declaration.
1232#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1233pub enum Visibility {
1234 /// Visible everywhere.
1235 Public,
1236 /// Visible within a package.
1237 Internal,
1238}
1239
1240/// A callable kind.
1241#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1242pub enum CallableKind {
1243 /// A function.
1244 Function,
1245 /// An operation.
1246 Operation,
1247}
1248
1249impl Display for CallableKind {
1250 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1251 match self {
1252 CallableKind::Function => f.write_str("function"),
1253 CallableKind::Operation => f.write_str("operation"),
1254 }
1255 }
1256}
1257
1258/// The mutability of a binding.
1259#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1260pub enum Mutability {
1261 /// An immutable binding.
1262 Immutable,
1263 /// A mutable binding.
1264 Mutable,
1265}
1266
1267/// The source of an allocated qubit.
1268#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1269pub enum QubitSource {
1270 /// A qubit initialized to the zero state.
1271 Fresh,
1272 /// A qubit borrowed from another part of the program that may be in any state, and is expected
1273 /// to be returned to that state before being released.
1274 Dirty,
1275}
1276
1277/// A literal.
1278#[derive(Clone, Debug, PartialEq)]
1279pub enum Lit {
1280 /// A big integer literal.
1281 BigInt(BigInt),
1282 /// A boolean literal.
1283 Bool(bool),
1284 /// A floating-point literal.
1285 Double(f64),
1286 /// An integer literal.
1287 Int(i64),
1288 /// A Pauli operator literal.
1289 Pauli(Pauli),
1290 /// A measurement result literal.
1291 Result(Result),
1292}
1293
1294impl Display for Lit {
1295 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1296 match self {
1297 Lit::BigInt(val) => write!(f, "BigInt({val})")?,
1298 Lit::Bool(val) => write!(f, "Bool({val})")?,
1299 Lit::Double(val) => write!(f, "Double({val})")?,
1300 Lit::Int(val) => write!(f, "Int({val})")?,
1301 Lit::Pauli(val) => write!(f, "Pauli({val:?})")?,
1302 Lit::Result(val) => write!(f, "Result({val:?})")?,
1303 }
1304 Ok(())
1305 }
1306}
1307
1308/// A measurement result.
1309#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1310pub enum Result {
1311 /// The zero eigenvalue.
1312 Zero,
1313 /// The one eigenvalue.
1314 One,
1315}
1316
1317/// A Pauli operator.
1318#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1319pub enum Pauli {
1320 /// The Pauli I operator.
1321 I,
1322 /// The Pauli X operator.
1323 X,
1324 /// The Pauli Y operator.
1325 Y,
1326 /// The Pauli Z operator.
1327 Z,
1328}
1329
1330/// A functor that may be applied to an operation.
1331#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1332pub enum Functor {
1333 /// The adjoint functor.
1334 Adj,
1335 /// The controlled functor.
1336 Ctl,
1337}
1338
1339impl Display for Functor {
1340 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1341 match self {
1342 Functor::Adj => f.write_str("Adj"),
1343 Functor::Ctl => f.write_str("Ctl"),
1344 }
1345 }
1346}
1347
1348/// A strategy for generating a specialization.
1349#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1350pub enum SpecGen {
1351 /// Choose a strategy automatically.
1352 Auto,
1353 /// Distributes controlled qubits.
1354 Distribute,
1355 /// A specialization implementation is not generated, but is instead left as an opaque
1356 /// declaration.
1357 Intrinsic,
1358 /// Inverts the order of operations.
1359 Invert,
1360 /// Uses the body specialization without modification.
1361 Slf,
1362}
1363
1364/// A unary operator.
1365#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1366pub enum UnOp {
1367 /// A functor application.
1368 Functor(Functor),
1369 /// Negation: `-`.
1370 Neg,
1371 /// Bitwise NOT: `~~~`.
1372 NotB,
1373 /// Logical NOT: `not`.
1374 NotL,
1375 /// A leading `+`.
1376 Pos,
1377 /// Unwrap a user-defined type: `!`.
1378 Unwrap,
1379}
1380
1381impl Display for UnOp {
1382 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1383 match self {
1384 UnOp::Functor(func) => write!(f, "Functor {func:?}")?,
1385 _ => fmt::Debug::fmt(self, f)?,
1386 }
1387 Ok(())
1388 }
1389}
1390
1391/// A binary operator.
1392#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1393pub enum BinOp {
1394 /// Addition: `+`.
1395 Add,
1396 /// Bitwise AND: `&&&`.
1397 AndB,
1398 /// Logical AND: `and`.
1399 AndL,
1400 /// Division: `/`.
1401 Div,
1402 /// Equality: `==`.
1403 Eq,
1404 /// Exponentiation: `^`.
1405 Exp,
1406 /// Greater than: `>`.
1407 Gt,
1408 /// Greater than or equal: `>=`.
1409 Gte,
1410 /// Less than: `<`.
1411 Lt,
1412 /// Less than or equal: `<=`.
1413 Lte,
1414 /// Modulus: `%`.
1415 Mod,
1416 /// Multiplication: `*`.
1417 Mul,
1418 /// Inequality: `!=`.
1419 Neq,
1420 /// Bitwise OR: `|||`.
1421 OrB,
1422 /// Logical OR: `or`.
1423 OrL,
1424 /// Shift left: `<<<`.
1425 Shl,
1426 /// Shift right: `>>>`.
1427 Shr,
1428 /// Subtraction: `-`.
1429 Sub,
1430 /// Bitwise XOR: `^^^`.
1431 XorB,
1432}
1433