microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.18.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/compiler/qsc_fir/src/fir.rs

1769lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! The flattened intermediate representation for Q#. FIR is lowered from the HIR.
5//! The blocks, exprs, pats, and stmts from HIR are replaced with IDs that index into
6//! the corresponding lookups in the package. This allows for traversal without
7//! leaking references to the FIR nodes.
8
9#![warn(missing_docs)]
10
11use crate::ty::{Arrow, FunctorSet, FunctorSetValue, GenericArg, Scheme, Ty, TypeParameter, Udt};
12use indenter::{indented, Indented};
13use num_bigint::BigInt;
14use qsc_data_structures::{
15 index_map::{IndexMap, Iter},
16 span::Span,
17};
18use std::{
19 cmp::Ordering,
20 fmt::{self, Debug, Display, Formatter, Write},
21 hash::{Hash, Hasher},
22 ops,
23 rc::Rc,
24 result,
25 str::FromStr,
26};
27
28fn set_indentation<'a, 'b>(
29 indent: Indented<'a, Formatter<'b>>,
30 level: usize,
31) -> Indented<'a, Formatter<'b>> {
32 match level {
33 0 => indent.with_str(""),
34 1 => indent.with_str(" "),
35 2 => indent.with_str(" "),
36 _ => unimplemented!("intentation level not supported"),
37 }
38}
39
40/// A unique identifier for an FIR node.
41#[derive(Clone, Copy, Debug)]
42pub struct NodeId(u32);
43
44impl NodeId {
45 /// The ID of the first node.
46 pub const FIRST: Self = Self(0);
47
48 /// The successor of this ID.
49 #[must_use]
50 pub fn successor(self) -> Self {
51 Self(self.0 + 1)
52 }
53}
54
55impl Display for NodeId {
56 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
57 Display::fmt(&self.0, f)
58 }
59}
60
61impl From<NodeId> for usize {
62 fn from(value: NodeId) -> Self {
63 value.0 as usize
64 }
65}
66
67impl From<usize> for NodeId {
68 fn from(value: usize) -> Self {
69 NodeId(
70 value
71 .try_into()
72 .expect("Type Node ID does not fit into u32"),
73 )
74 }
75}
76
77impl From<NodeId> for u32 {
78 fn from(value: NodeId) -> Self {
79 value.0
80 }
81}
82
83impl From<u32> for NodeId {
84 fn from(value: u32) -> Self {
85 NodeId(value)
86 }
87}
88
89impl PartialEq for NodeId {
90 fn eq(&self, other: &Self) -> bool {
91 self.0 == other.0
92 }
93}
94
95impl Eq for NodeId {}
96
97impl PartialOrd for NodeId {
98 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
99 Some(self.cmp(other))
100 }
101}
102
103impl Ord for NodeId {
104 fn cmp(&self, other: &Self) -> Ordering {
105 self.0.cmp(&other.0)
106 }
107}
108
109impl Hash for NodeId {
110 fn hash<H: Hasher>(&self, state: &mut H) {
111 self.0.hash(state);
112 }
113}
114
115macro_rules! fir_id {
116 ($id:ident) => {
117 /// A unique identifier for an FIR node.
118 #[derive(Debug, Clone, Copy)]
119 pub struct $id(pub u32);
120
121 impl $id {
122 /// The successor of this ID.
123 #[must_use]
124 pub fn successor(self) -> Self {
125 Self(self.0 + 1)
126 }
127 }
128
129 impl Default for $id {
130 fn default() -> Self {
131 Self(0)
132 }
133 }
134
135 impl From<NodeId> for $id {
136 fn from(val: NodeId) -> Self {
137 $id(val.into())
138 }
139 }
140
141 impl From<$id> for NodeId {
142 fn from(val: $id) -> Self {
143 NodeId(val.into())
144 }
145 }
146
147 impl From<u32> for $id {
148 fn from(val: u32) -> Self {
149 $id(val)
150 }
151 }
152
153 impl From<$id> for u32 {
154 fn from(id: $id) -> Self {
155 id.0
156 }
157 }
158
159 impl From<$id> for usize {
160 fn from(value: $id) -> Self {
161 value.0 as usize
162 }
163 }
164
165 impl From<usize> for $id {
166 fn from(value: usize) -> Self {
167 $id(value.try_into().expect(&format!(
168 "Value, {}, does not fit into {}",
169 value,
170 stringify!($id)
171 )))
172 }
173 }
174
175 impl PartialEq for $id {
176 fn eq(&self, other: &Self) -> bool {
177 self.0 == other.0
178 }
179 }
180
181 impl Eq for $id {}
182
183 impl PartialOrd for $id {
184 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
185 Some(self.cmp(other))
186 }
187 }
188
189 impl Ord for $id {
190 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
191 self.0.cmp(&other.0)
192 }
193 }
194
195 impl std::hash::Hash for $id {
196 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
197 self.0.hash(state);
198 }
199 }
200
201 impl Display for $id {
202 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
203 Display::fmt(&self.0, f)
204 }
205 }
206 };
207}
208
209fir_id!(BlockId);
210fir_id!(ExprId);
211fir_id!(PatId);
212fir_id!(StmtId);
213fir_id!(LocalVarId);
214
215/// A unique identifier for a package within a package store.
216#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
217pub struct PackageId(usize);
218
219impl PackageId {
220 /// The package ID of the core library.
221 pub const CORE: Self = Self(0);
222
223 /// The successor of this ID.
224 #[must_use]
225 pub fn successor(self) -> Self {
226 Self(self.0 + 1)
227 }
228}
229
230impl Display for PackageId {
231 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
232 Display::fmt(&self.0, f)
233 }
234}
235
236impl From<PackageId> for usize {
237 fn from(value: PackageId) -> Self {
238 value.0
239 }
240}
241
242impl From<usize> for PackageId {
243 fn from(value: usize) -> Self {
244 PackageId(value)
245 }
246}
247
248/// A unique identifier for an item within a package.
249#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
250pub struct LocalItemId(usize);
251
252impl LocalItemId {
253 /// The successor of this ID.
254 #[must_use]
255 pub fn successor(self) -> Self {
256 Self(self.0 + 1)
257 }
258}
259
260impl Display for LocalItemId {
261 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
262 Display::fmt(&self.0, f)
263 }
264}
265
266impl From<usize> for LocalItemId {
267 fn from(value: usize) -> Self {
268 Self(value)
269 }
270}
271
272impl From<LocalItemId> for usize {
273 fn from(value: LocalItemId) -> Self {
274 value.0
275 }
276}
277
278/// A unique identifier for an item within a package store.
279#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
280pub struct ItemId {
281 /// The package ID or `None` for the local package.
282 pub package: Option<PackageId>,
283 /// The item ID.
284 pub item: LocalItemId,
285}
286
287impl Display for ItemId {
288 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
289 match self.package {
290 None => write!(f, "Item {}", self.item),
291 Some(package) => write!(f, "Item {} (Package {package})", self.item),
292 }
293 }
294}
295
296/// A resolution. This connects a usage of a name with the declaration of that name by uniquely
297/// identifying the node that declared it.
298#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
299pub enum Res {
300 /// An invalid resolution.
301 Err,
302 /// A global item.
303 Item(ItemId),
304 /// A local variable.
305 Local(LocalVarId),
306}
307
308impl Display for Res {
309 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
310 match self {
311 Res::Err => f.write_str("Err"),
312 Res::Item(item) => Display::fmt(item, f),
313 Res::Local(node) => write!(f, "Local {node}"),
314 }
315 }
316}
317
318/// A global item.
319pub enum Global<'a> {
320 /// A global callable.
321 Callable(&'a CallableDecl),
322 /// A global user-defined type.
323 Udt,
324}
325
326/// A unique identifier for an item within a package store.
327#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
328pub struct StoreItemId {
329 /// The package ID.
330 pub package: PackageId,
331 /// The item ID.
332 pub item: LocalItemId,
333}
334
335impl Display for StoreItemId {
336 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
337 write!(f, "<item {} in package {}>", self.item, self.package)
338 }
339}
340
341impl From<(PackageId, LocalItemId)> for StoreItemId {
342 fn from(tuple: (PackageId, LocalItemId)) -> Self {
343 Self {
344 package: tuple.0,
345 item: tuple.1,
346 }
347 }
348}
349
350/// A unique identifier for a block within a package store.
351#[derive(Clone, Copy, Debug, PartialEq)]
352pub struct StoreBlockId {
353 /// The package ID.
354 pub package: PackageId,
355 /// The item ID.
356 pub block: BlockId,
357}
358
359impl Display for StoreBlockId {
360 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
361 write!(f, "<block {} in package {}>", self.block, self.package)
362 }
363}
364
365impl From<(PackageId, BlockId)> for StoreBlockId {
366 fn from(tuple: (PackageId, BlockId)) -> Self {
367 Self {
368 package: tuple.0,
369 block: tuple.1,
370 }
371 }
372}
373
374/// A unique identifier for an expression within a package store.
375#[derive(Clone, Copy, Debug, PartialEq)]
376pub struct StoreExprId {
377 /// The package ID.
378 pub package: PackageId,
379 /// The expression ID.
380 pub expr: ExprId,
381}
382
383impl Display for StoreExprId {
384 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
385 write!(f, "<expression {} in package {}>", self.expr, self.package)
386 }
387}
388
389impl From<(PackageId, ExprId)> for StoreExprId {
390 fn from(tuple: (PackageId, ExprId)) -> Self {
391 Self {
392 package: tuple.0,
393 expr: tuple.1,
394 }
395 }
396}
397
398/// A unique identifier for a pattern within a package store.
399#[derive(Clone, Copy, Debug, PartialEq)]
400pub struct StorePatId {
401 /// The package ID.
402 pub package: PackageId,
403 /// The pat ID.
404 pub pat: PatId,
405}
406
407impl Display for StorePatId {
408 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
409 write!(f, "<pattern {} in package {}>", self.pat, self.package)
410 }
411}
412
413impl From<(PackageId, PatId)> for StorePatId {
414 fn from(tuple: (PackageId, PatId)) -> Self {
415 Self {
416 package: tuple.0,
417 pat: tuple.1,
418 }
419 }
420}
421
422/// A unique identifier for a statement within a package store.
423#[derive(Clone, Copy, Debug, PartialEq)]
424pub struct StoreStmtId {
425 /// The package ID.
426 pub package: PackageId,
427 /// The statement ID.
428 pub stmt: StmtId,
429}
430
431impl Display for StoreStmtId {
432 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
433 write!(f, "<pattern {} in package {}>", self.stmt, self.package)
434 }
435}
436
437impl From<(PackageId, StmtId)> for StoreStmtId {
438 fn from(tuple: (PackageId, StmtId)) -> Self {
439 Self {
440 package: tuple.0,
441 stmt: tuple.1,
442 }
443 }
444}
445
446/// A trait to find elements in a package store.
447pub trait PackageStoreLookup {
448 /// Gets a block.
449 fn get_block(&self, id: StoreBlockId) -> &Block;
450 /// Gets an expression.
451 fn get_expr(&self, id: StoreExprId) -> &Expr;
452 /// Gets a global.
453 fn get_global(&self, id: StoreItemId) -> Option<Global>;
454 /// Gets a pat.
455 fn get_pat(&self, id: StorePatId) -> &Pat;
456 /// Gets a statement.
457 fn get_stmt(&self, id: StoreStmtId) -> &Stmt;
458 /// Gets an item.
459 fn get_item(&self, id: StoreItemId) -> &Item;
460}
461
462/// A FIR package store.
463#[derive(Debug, Default)]
464pub struct PackageStore(IndexMap<PackageId, Package>);
465
466impl PackageStoreLookup for PackageStore {
467 fn get_block(&self, id: StoreBlockId) -> &Block {
468 self.get(id.package).get_block(id.block)
469 }
470
471 fn get_expr(&self, id: StoreExprId) -> &Expr {
472 self.get(id.package).get_expr(id.expr)
473 }
474
475 fn get_global(&self, id: StoreItemId) -> Option<Global> {
476 self.get(id.package).get_global(id.item)
477 }
478
479 fn get_pat(&self, id: StorePatId) -> &Pat {
480 self.get(id.package).get_pat(id.pat)
481 }
482
483 fn get_stmt(&self, id: StoreStmtId) -> &Stmt {
484 self.get(id.package).get_stmt(id.stmt)
485 }
486
487 fn get_item(&self, id: StoreItemId) -> &Item {
488 self.get(id.package).get_item(id.item)
489 }
490}
491
492impl PackageStore {
493 /// Gets a package from the store.
494 #[must_use]
495 pub fn get(&self, id: PackageId) -> &Package {
496 self.0.get(id).expect("store should have package")
497 }
498
499 /// Gets a mutable package from the store.
500 #[must_use]
501 pub fn get_mut(&mut self, id: PackageId) -> &mut Package {
502 self.0.get_mut(id).expect("store should have package")
503 }
504
505 /// Inserts a package to the store.
506 pub fn insert(&mut self, id: PackageId, package: Package) {
507 self.0.insert(id, package);
508 }
509
510 /// Gets a package store iterator.
511 #[must_use]
512 pub fn iter(&self) -> Iter<PackageId, Package> {
513 self.0.iter()
514 }
515
516 /// Creates a package store.
517 #[must_use]
518 pub fn new() -> Self {
519 Self::default()
520 }
521}
522
523impl<'a> IntoIterator for &'a PackageStore {
524 type IntoIter = qsc_data_structures::index_map::Iter<'a, PackageId, Package>;
525 type Item = (PackageId, &'a Package);
526
527 fn into_iter(self) -> Self::IntoIter {
528 self.iter()
529 }
530}
531
532/// A trait to find elements in a package.
533pub trait PackageLookup {
534 /// Gets a block.
535 fn get_block(&self, id: BlockId) -> &Block;
536 /// Gets an expression.
537 fn get_expr(&self, id: ExprId) -> &Expr;
538 /// Gets a global.
539 fn get_global(&self, id: LocalItemId) -> Option<Global>;
540 /// Gets an item.
541 fn get_item(&self, id: LocalItemId) -> &Item;
542 /// Gets a pat.
543 fn get_pat(&self, id: PatId) -> &Pat;
544 /// Gets a statement.
545 fn get_stmt(&self, id: StmtId) -> &Stmt;
546}
547
548/// The root node of the FIR.
549/// ### Notes
550/// We maintain a dense map of ids within the package.
551/// `BlockId`, `ExprId`, `PatId`, `StmtId`, and `NodeId`s are all assigned
552/// from a type specific counter in the assigner.
553///
554/// `BlockId`, `ExprId`, `PatId`, `StmtId` ids don't leak and are only used
555/// within the containing node. Node ids are used to identify nodes within
556/// the package and require mapping from the HIR node id to the new FIR node id.
557/// `PackageId`s and `LocalItemId`s are 1:1 from the HIR and are not remapped.
558#[derive(Debug)]
559pub struct Package {
560 /// The items in the package.
561 pub items: IndexMap<LocalItemId, Item>,
562 /// The entry expression for an executable package.
563 pub entry: Option<ExprId>,
564 /// The control flow graph for the entry expression in the package.
565 pub entry_exec_graph: ExecGraph,
566 /// The blocks in the package.
567 pub blocks: IndexMap<BlockId, Block>,
568 /// The expressions in the package.
569 pub exprs: IndexMap<ExprId, Expr>,
570 /// The patterns in the package.
571 pub pats: IndexMap<PatId, Pat>,
572 /// The statements in the package.
573 pub stmts: IndexMap<StmtId, Stmt>,
574}
575
576impl Display for Package {
577 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
578 let mut indent = set_indentation(indented(f), 0);
579 write!(indent, "Package:")?;
580 indent = set_indentation(indent, 1);
581 if let Some(e) = &self.entry {
582 write!(indent, "\nEntry Expression: {e}")?;
583 }
584
585 write!(indent, "\nItems:")?;
586 indent = set_indentation(indent, 2);
587 for item in self.items.values() {
588 write!(indent, "\n{item}")?;
589 }
590
591 indent = set_indentation(indent, 1);
592 write!(indent, "\nBlocks:")?;
593 indent = set_indentation(indent, 2);
594 for block in self.blocks.values() {
595 write!(indent, "\n{block}")?;
596 }
597
598 indent = set_indentation(indent, 1);
599 write!(indent, "\nStmts:")?;
600 indent = set_indentation(indent, 2);
601 for stmt in self.stmts.values() {
602 write!(indent, "\n{stmt}")?;
603 }
604
605 indent = set_indentation(indent, 1);
606 write!(indent, "\nExprs:")?;
607 indent = set_indentation(indent, 2);
608 for expr in self.exprs.values() {
609 write!(indent, "\n{expr}")?;
610 }
611
612 indent = set_indentation(indent, 1);
613 write!(indent, "\nPats:")?;
614 indent = set_indentation(indent, 2);
615 for pat in self.pats.values() {
616 write!(indent, "\n{pat}")?;
617 }
618 Ok(())
619 }
620}
621
622impl PackageLookup for Package {
623 fn get_block(&self, id: BlockId) -> &Block {
624 self.blocks.get(id).expect("Block not found")
625 }
626
627 fn get_expr(&self, id: ExprId) -> &Expr {
628 self.exprs.get(id).expect("Expression not found")
629 }
630
631 fn get_global(&self, id: LocalItemId) -> Option<Global> {
632 match &self.items.get(id)?.kind {
633 ItemKind::Callable(callable) => Some(Global::Callable(callable)),
634 ItemKind::Namespace(..) => None,
635 ItemKind::Ty(..) => Some(Global::Udt),
636 ItemKind::Export(_name, _id) => None,
637 }
638 }
639
640 fn get_item(&self, id: LocalItemId) -> &Item {
641 self.items.get(id).expect("Item not found")
642 }
643
644 fn get_pat(&self, id: PatId) -> &Pat {
645 self.pats.get(id).expect("Pattern not found")
646 }
647
648 fn get_stmt(&self, id: StmtId) -> &Stmt {
649 self.stmts.get(id).expect("Statement not found")
650 }
651}
652
653/// An item.
654#[derive(Clone, Debug, PartialEq)]
655pub struct Item {
656 /// The ID.
657 pub id: LocalItemId,
658 /// The span.
659 pub span: Span,
660 /// The parent item.
661 pub parent: Option<LocalItemId>,
662 /// The documentation.
663 pub doc: Rc<str>,
664 /// The attributes.
665 pub attrs: Vec<Attr>,
666 /// The visibility.
667 pub visibility: Visibility,
668 /// The item kind.
669 pub kind: ItemKind,
670}
671
672impl Display for Item {
673 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
674 let mut indent = set_indentation(indented(f), 0);
675 write!(
676 indent,
677 "Item {} {} ({:?}):",
678 self.id, self.span, self.visibility
679 )?;
680
681 indent = set_indentation(indent, 1);
682 if let Some(parent) = self.parent {
683 write!(indent, "\nParent: {parent}")?;
684 }
685
686 if !self.doc.is_empty() {
687 write!(indent, "\nDoc:")?;
688 indent = set_indentation(indent, 2);
689 write!(indent, "\n{}", self.doc)?;
690 indent = set_indentation(indent, 1);
691 }
692
693 for attr in &self.attrs {
694 write!(indent, "\n{attr:?}")?;
695 }
696
697 write!(indent, "\n{}", self.kind)?;
698 Ok(())
699 }
700}
701
702/// An item kind.
703#[derive(Clone, Debug, PartialEq)]
704pub enum ItemKind {
705 /// A `function` or `operation` declaration.
706 Callable(CallableDecl),
707 /// A `namespace` declaration.
708 Namespace(Ident, Vec<LocalItemId>),
709 /// A `newtype` declaration.
710 Ty(Ident, Udt),
711 /// An export referring to another item
712 Export(Ident, ItemId),
713}
714
715impl Display for ItemKind {
716 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
717 match self {
718 ItemKind::Callable(decl) => write!(f, "{decl}"),
719 ItemKind::Namespace(name, items) => {
720 write!(f, "Namespace ({name}):")?;
721 let mut items = items.iter();
722 if let Some(item) = items.next() {
723 write!(f, " Item {item}")?;
724 for item in items {
725 write!(f, ", Item {item}")?;
726 }
727 Ok(())
728 } else {
729 write!(f, " <empty>")
730 }
731 }
732 ItemKind::Ty(name, udt) => write!(f, "Type ({name}): {udt}"),
733 ItemKind::Export(name, item) => write!(f, "Export ({name}): {item}"),
734 }
735 }
736}
737
738/// A callable declaration header.
739#[derive(Clone, Debug, PartialEq)]
740pub struct CallableDecl {
741 /// The node ID.
742 pub id: NodeId,
743 /// The span.
744 pub span: Span,
745 /// The callable kind.
746 pub kind: CallableKind,
747 /// The name of the callable.
748 pub name: Ident,
749 /// The generic parameters to the callable.
750 pub generics: Vec<TypeParameter>,
751 /// The input to the callable.
752 pub input: PatId,
753 /// The return type of the callable.
754 pub output: Ty,
755 /// The functors supported by the callable.
756 pub functors: FunctorSetValue,
757 /// The callable implementation.
758 pub implementation: CallableImpl,
759 /// The attributes of the callable, (e.g.: Measurement or Reset).
760 pub attrs: Vec<Attr>,
761}
762
763impl CallableDecl {
764 /// The type scheme of the callable.
765 #[must_use]
766 pub fn scheme<'a>(&self, f: impl Fn(PatId) -> &'a Pat) -> Scheme {
767 Scheme::new(
768 self.generics.clone(),
769 Box::new(Arrow {
770 kind: self.kind,
771 input: Box::new(f(self.input).ty.clone()),
772 output: Box::new(self.output.clone()),
773 functors: FunctorSet::Value(self.functors),
774 }),
775 )
776 }
777}
778
779impl Display for CallableDecl {
780 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
781 let mut indent = set_indentation(indented(f), 0);
782 write!(
783 indent,
784 "Callable {} {} ({}):",
785 self.id, self.span, self.kind
786 )?;
787 indent = set_indentation(indent, 1);
788 write!(indent, "\nname: {}", self.name)?;
789 if !self.generics.is_empty() {
790 write!(indent, "\ngenerics:")?;
791 indent = set_indentation(indent, 2);
792 for (ix, param) in self.generics.iter().enumerate() {
793 write!(indent, "\n{ix}: {param}")?;
794 }
795 indent = set_indentation(indent, 1);
796 }
797 write!(indent, "\ninput: {}", self.input)?;
798 write!(indent, "\noutput: {}", self.output)?;
799 write!(indent, "\nfunctors: {}", self.functors)?;
800 write!(indent, "\nimplementation: {}", self.implementation)?;
801 Ok(())
802 }
803}
804
805/// A callable implementations.
806#[derive(Clone, Debug, PartialEq)]
807pub enum CallableImpl {
808 /// An intrinsic callable implementation.
809 Intrinsic,
810 /// A specialized callable implementation.
811 Spec(SpecImpl),
812 /// An intrinsic with a simulation override.
813 SimulatableIntrinsic(SpecDecl),
814}
815
816impl Display for CallableImpl {
817 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
818 let mut indent = set_indentation(indented(f), 0);
819 match self {
820 CallableImpl::Intrinsic => {
821 write!(indent, "Instrinsic")?;
822 }
823 CallableImpl::Spec(spec_impl) => {
824 write!(indent, "Spec:")?;
825 indent = set_indentation(indent, 1);
826 write!(indent, "\n{spec_impl}")?;
827 }
828 CallableImpl::SimulatableIntrinsic(spec_decl) => {
829 write!(indent, "SimulatableIntrinsic:")?;
830 indent = set_indentation(indent, 1);
831 write!(indent, "\n{spec_decl}")?;
832 }
833 }
834
835 Ok(())
836 }
837}
838
839/// A specialized implementation.
840#[derive(Clone, Debug, PartialEq)]
841pub struct SpecImpl {
842 /// The body implementation.
843 pub body: SpecDecl,
844 /// The adjoint specialization.
845 pub adj: Option<SpecDecl>,
846 /// The controlled specialization.
847 pub ctl: Option<SpecDecl>,
848 /// The controlled adjoint specialization.
849 pub ctl_adj: Option<SpecDecl>,
850}
851
852impl Display for SpecImpl {
853 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
854 let mut indent = set_indentation(indented(f), 0);
855 write!(indent, "SpecImpl:")?;
856 indent = set_indentation(indent, 1);
857 write!(indent, "\nbody: {}", self.body)?;
858 match &self.adj {
859 Some(spec) => write!(indent, "\nadj: {spec}")?,
860 None => write!(indent, "\nadj: <none>")?,
861 }
862 match &self.ctl {
863 Some(spec) => write!(indent, "\nctl: {spec}")?,
864 None => write!(indent, "\nctl: <none>")?,
865 }
866 match &self.ctl_adj {
867 Some(spec) => write!(indent, "\nctl-adj: {spec}")?,
868 None => write!(indent, "\nctl-adj: <none>")?,
869 }
870 Ok(())
871 }
872}
873
874/// A specialization declaration.
875#[derive(Clone, Debug, PartialEq)]
876pub struct SpecDecl {
877 /// The node ID.
878 pub id: NodeId,
879 /// The span.
880 pub span: Span,
881 /// The block that implements the specialization.
882 pub block: BlockId,
883 /// The input of the specialization.
884 pub input: Option<PatId>,
885 /// The flattened control flow graph for the execution of the specialization.
886 pub exec_graph: ExecGraph,
887}
888
889impl Display for SpecDecl {
890 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
891 write!(
892 f,
893 "SpecDecl {} {}: {:?} {}",
894 self.id, self.span, self.input, self.block
895 )
896 }
897}
898
899/// An execution graph represented by a reference counted vector of nodes.
900pub type ExecGraph = Rc<[ExecGraphNode]>;
901
902#[derive(Copy, Clone, Debug, PartialEq)]
903/// A node within the control flow graph.
904pub enum ExecGraphNode {
905 /// A binding of a value to a variable.
906 Bind(PatId),
907 /// An expression to execute.
908 Expr(ExprId),
909 /// An unconditional jump with to given location.
910 Jump(u32),
911 /// A conditional jump with to given location, where the jump is only taken if the condition is
912 /// true.
913 JumpIf(u32),
914 /// A conditional jump with to given location, where the jump is only taken if the condition is
915 /// false.
916 JumpIfNot(u32),
917 /// An indication that the current accumulated result value should be stored into the value stack.
918 Store,
919 /// A no-op Unit node that tells execution to insert a unit value into the current accumulated result.
920 Unit,
921 /// The end of the control flow graph.
922 Ret,
923 /// The end of the control flow graph plus a pop of the current debug frame. Used instead of `Ret`
924 /// when debugging.
925 RetFrame,
926 /// A statement to track for debugging.
927 Stmt(StmtId),
928 /// A push of a new scope, used when tracking variables for debugging.
929 PushScope,
930 /// A pop of the current scope, used when tracking variables for debugging.
931 PopScope,
932 /// A failure node, inserted just before a `fail` expression to halt execution for debugging.
933 Fail,
934}
935
936/// A sequenced block of statements.
937#[derive(Clone, Debug, PartialEq)]
938pub struct Block {
939 /// The node ID.
940 pub id: BlockId,
941 /// The span.
942 pub span: Span,
943 /// The block type.
944 pub ty: Ty,
945 /// The statements in the block.
946 pub stmts: Vec<StmtId>,
947}
948
949impl Display for Block {
950 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
951 if self.stmts.is_empty() {
952 write!(f, "Block {} {}: <empty>", self.id, self.span)?;
953 } else {
954 let mut indent = set_indentation(indented(f), 0);
955 write!(
956 indent,
957 "Block {} {} [Type {}]:",
958 self.id, self.span, self.ty
959 )?;
960 indent = set_indentation(indent, 1);
961 for s in &self.stmts {
962 write!(indent, "\n{s}")?;
963 }
964 }
965 Ok(())
966 }
967}
968
969/// A statement.
970#[derive(Clone, Debug, PartialEq)]
971pub struct Stmt {
972 /// The stmt ID.
973 pub id: StmtId,
974 /// The span.
975 pub span: Span,
976 /// The statement kind.
977 pub kind: StmtKind,
978 /// The locations within the containing control flow graph for the current statement.
979 pub exec_graph_range: ops::Range<usize>,
980}
981
982impl Display for Stmt {
983 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
984 write!(f, "Stmt {} {}: {}", self.id, self.span, self.kind)
985 }
986}
987
988/// A statement kind.
989#[derive(Clone, Debug, PartialEq)]
990pub enum StmtKind {
991 /// An expression without a trailing semicolon.
992 Expr(ExprId),
993 /// An item.
994 Item(LocalItemId),
995 /// A let or mutable binding: `let a = b;` or `mutable x = b;`.
996 Local(Mutability, PatId, ExprId),
997 /// An expression with a trailing semicolon.
998 Semi(ExprId),
999}
1000
1001impl Display for StmtKind {
1002 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1003 let mut indent = set_indentation(indented(f), 0);
1004 match self {
1005 StmtKind::Expr(e) => write!(indent, "Expr: {e}")?,
1006 StmtKind::Item(item) => write!(indent, "Item: {item}")?,
1007 StmtKind::Local(m, lhs, rhs) => {
1008 write!(indent, "Local ({m:?}):")?;
1009 indent = set_indentation(indent, 1);
1010 write!(indent, "\n{lhs}")?;
1011 write!(indent, "\n{rhs}")?;
1012 }
1013 StmtKind::Semi(e) => write!(indent, "Semi: {e}")?,
1014 }
1015 Ok(())
1016 }
1017}
1018
1019/// An expression.
1020#[derive(Clone, Debug, PartialEq)]
1021pub struct Expr {
1022 /// The expr ID.
1023 pub id: ExprId,
1024 /// The span.
1025 pub span: Span,
1026 /// The expression type.
1027 pub ty: Ty,
1028 /// The expression kind.
1029 pub kind: ExprKind,
1030 /// The locations within the containing control flow graph for the current expression.
1031 pub exec_graph_range: ops::Range<usize>,
1032}
1033
1034impl Display for Expr {
1035 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1036 write!(
1037 f,
1038 "Expr {} {} [Type {}]: {}",
1039 self.id, self.span, self.ty, self.kind
1040 )
1041 }
1042}
1043
1044/// An expression kind.
1045#[derive(Clone, Debug, PartialEq)]
1046pub enum ExprKind {
1047 /// An array: `[a, b, c]`.
1048 Array(Vec<ExprId>),
1049 /// An array of literal values, ie: `[1, 2, 3]`.
1050 ArrayLit(Vec<ExprId>),
1051 /// An array constructed by repeating a value: `[a, size = b]`.
1052 ArrayRepeat(ExprId, ExprId),
1053 /// An assignment: `set a = b`.
1054 Assign(ExprId, ExprId),
1055 /// An assignment with a compound operator. For example: `set a += b`.
1056 AssignOp(BinOp, ExprId, ExprId),
1057 /// An assignment with a compound field update operator: `set a w/= B <- c`.
1058 AssignField(ExprId, Field, ExprId),
1059 /// An assignment with a compound index update operator: `set a w/= b <- c`.
1060 AssignIndex(ExprId, ExprId, ExprId),
1061 /// A binary operator.
1062 BinOp(BinOp, ExprId, ExprId),
1063 /// A block: `{ ... }`.
1064 Block(BlockId),
1065 /// A call: `a(b)`.
1066 Call(ExprId, ExprId),
1067 /// A closure that fixes the vector of local variables as arguments to the callable item.
1068 Closure(Vec<LocalVarId>, LocalItemId),
1069 /// A failure: `fail "message"`.
1070 Fail(ExprId),
1071 /// A field accessor: `a::F` or `a.F`.
1072 Field(ExprId, Field),
1073 /// An unspecified expression, _, which may indicate partial application or discards
1074 Hole,
1075 /// An if expression with an optional else block: `if a { ... } else { ... }`.
1076 ///
1077 /// Note that, as a special case, `elif ...` is effectively parsed as `else if ...`, without a
1078 /// block wrapping the `if`. This distinguishes `elif ...` from `else { if ... }`, which does
1079 /// have a block.
1080 If(ExprId, ExprId, Option<ExprId>),
1081 /// An index accessor: `a[b]`.
1082 Index(ExprId, ExprId),
1083 /// A literal.
1084 Lit(Lit),
1085 /// A range: `start..step..end`, `start..end`, `start...`, `...end`, or `...`.
1086 Range(Option<ExprId>, Option<ExprId>, Option<ExprId>),
1087 /// A return: `return a`.
1088 Return(ExprId),
1089 /// A struct constructor.
1090 Struct(Res, Option<ExprId>, Vec<FieldAssign>),
1091 /// A string.
1092 String(Vec<StringComponent>),
1093 /// Update array index: `a w/ b <- c`.
1094 UpdateIndex(ExprId, ExprId, ExprId),
1095 /// A tuple: `(a, b, c)`.
1096 Tuple(Vec<ExprId>),
1097 /// A unary operator.
1098 UnOp(UnOp, ExprId),
1099 /// A record field update: `a w/ B <- c`.
1100 UpdateField(ExprId, Field, ExprId),
1101 /// A variable and its generic arguments.
1102 Var(Res, Vec<GenericArg>),
1103 /// A while loop: `while a { ... }`.
1104 While(ExprId, BlockId),
1105}
1106
1107impl Display for ExprKind {
1108 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1109 let mut indent = set_indentation(indented(f), 0);
1110 match self {
1111 ExprKind::Array(exprs) | ExprKind::ArrayLit(exprs) => display_array(indent, exprs)?,
1112 ExprKind::ArrayRepeat(val, size) => display_array_repeat(indent, *val, *size)?,
1113 ExprKind::Assign(lhs, rhs) => display_assign(indent, *lhs, *rhs)?,
1114 ExprKind::AssignOp(op, lhs, rhs) => display_assign_op(indent, *op, *lhs, *rhs)?,
1115 ExprKind::AssignField(record, field, replace) => {
1116 display_assign_field(indent, *record, field, *replace)?;
1117 }
1118 ExprKind::AssignIndex(container, item, replace) => {
1119 display_assign_index(indent, *container, *item, *replace)?;
1120 }
1121 ExprKind::BinOp(op, lhs, rhs) => display_bin_op(indent, *op, *lhs, *rhs)?,
1122 ExprKind::Block(block) => write!(indent, "Expr Block: {block}")?,
1123 ExprKind::Call(callable, arg) => display_call(indent, *callable, *arg)?,
1124 ExprKind::Closure(args, callable) => display_closure(indent, args, *callable)?,
1125 ExprKind::Fail(e) => write!(indent, "Fail: {e}")?,
1126 ExprKind::Field(expr, field) => display_field(indent, *expr, field)?,
1127 ExprKind::Hole => write!(indent, "Hole")?,
1128 ExprKind::If(cond, body, els) => display_if(indent, *cond, *body, *els)?,
1129 ExprKind::Index(array, index) => display_index(indent, *array, *index)?,
1130 ExprKind::Lit(lit) => write!(indent, "Lit: {lit}")?,
1131 ExprKind::Range(start, step, end) => display_range(indent, *start, *step, *end)?,
1132 ExprKind::Return(e) => write!(indent, "Return: {e}")?,
1133 ExprKind::Struct(name, copy, fields) => display_struct(indent, name, *copy, fields)?,
1134 ExprKind::String(components) => display_string(indent, components)?,
1135 ExprKind::UpdateIndex(expr1, expr2, expr3) => {
1136 display_update_index(indent, *expr1, *expr2, *expr3)?;
1137 }
1138 ExprKind::Tuple(exprs) => display_tuple(indent, exprs)?,
1139 ExprKind::UnOp(op, expr) => display_un_op(indent, *op, *expr)?,
1140 ExprKind::UpdateField(record, field, replace) => {
1141 display_update_field(indent, *record, field, *replace)?;
1142 }
1143 ExprKind::Var(res, args) => display_var(indent, *res, args)?,
1144 ExprKind::While(cond, block) => display_while(indent, *cond, *block)?,
1145 }
1146 Ok(())
1147 }
1148}
1149
1150fn display_array(mut indent: Indented<Formatter>, exprs: &Vec<ExprId>) -> fmt::Result {
1151 write!(indent, "Array:")?;
1152 indent = set_indentation(indent, 1);
1153 for e in exprs {
1154 write!(indent, "\n{e}")?;
1155 }
1156 Ok(())
1157}
1158
1159fn display_array_repeat(mut indent: Indented<Formatter>, val: ExprId, size: ExprId) -> fmt::Result {
1160 write!(indent, "ArrayRepeat:")?;
1161 indent = set_indentation(indent, 1);
1162 write!(indent, "\n{val}")?;
1163 write!(indent, "\n{size}")?;
1164 Ok(())
1165}
1166
1167fn display_assign(mut indent: Indented<Formatter>, lhs: ExprId, rhs: ExprId) -> fmt::Result {
1168 write!(indent, "Assign:")?;
1169 indent = set_indentation(indent, 1);
1170 write!(indent, "\n{lhs}")?;
1171 write!(indent, "\n{rhs}")?;
1172 Ok(())
1173}
1174
1175fn display_assign_op(
1176 mut indent: Indented<Formatter>,
1177 op: BinOp,
1178 lhs: ExprId,
1179 rhs: ExprId,
1180) -> fmt::Result {
1181 write!(indent, "AssignOp ({op:?}):")?;
1182 indent = set_indentation(indent, 1);
1183 write!(indent, "\n{lhs}")?;
1184 write!(indent, "\n{rhs}")?;
1185 Ok(())
1186}
1187
1188fn display_assign_field(
1189 mut indent: Indented<Formatter>,
1190 record: ExprId,
1191 field: &Field,
1192 replace: ExprId,
1193) -> fmt::Result {
1194 write!(indent, "AssignField:")?;
1195 indent = set_indentation(indent, 1);
1196 write!(indent, "\n{record}")?;
1197 write!(indent, "\n{field}")?;
1198 write!(indent, "\n{replace}")?;
1199 Ok(())
1200}
1201
1202fn display_assign_index(
1203 mut indent: Indented<Formatter>,
1204 array: ExprId,
1205 index: ExprId,
1206 replace: ExprId,
1207) -> fmt::Result {
1208 write!(indent, "AssignIndex:")?;
1209 indent = set_indentation(indent, 1);
1210 write!(indent, "\n{array}")?;
1211 write!(indent, "\n{index}")?;
1212 write!(indent, "\n{replace}")?;
1213 Ok(())
1214}
1215
1216fn display_bin_op(
1217 mut indent: Indented<Formatter>,
1218 op: BinOp,
1219 lhs: ExprId,
1220 rhs: ExprId,
1221) -> fmt::Result {
1222 write!(indent, "BinOp ({op:?}):")?;
1223 indent = set_indentation(indent, 1);
1224 write!(indent, "\n{lhs}")?;
1225 write!(indent, "\n{rhs}")?;
1226 Ok(())
1227}
1228
1229fn display_call(mut indent: Indented<Formatter>, callable: ExprId, arg: ExprId) -> fmt::Result {
1230 write!(indent, "Call:")?;
1231 indent = set_indentation(indent, 1);
1232 write!(indent, "\n{callable}")?;
1233 write!(indent, "\n{arg}")?;
1234 Ok(())
1235}
1236
1237fn display_closure(
1238 mut f: Indented<Formatter>,
1239 args: &[LocalVarId],
1240 callable: LocalItemId,
1241) -> fmt::Result {
1242 f.write_str("Closure([")?;
1243 let mut args = args.iter();
1244 if let Some(arg) = args.next() {
1245 write!(f, "{arg}")?;
1246 }
1247 for arg in args {
1248 write!(f, ", {arg}")?;
1249 }
1250 write!(f, "], {callable})")
1251}
1252
1253fn display_field(mut indent: Indented<Formatter>, expr: ExprId, field: &Field) -> fmt::Result {
1254 write!(indent, "Field:")?;
1255 indent = set_indentation(indent, 1);
1256 write!(indent, "\n{expr}")?;
1257 write!(indent, "\n{field:?}")?;
1258 Ok(())
1259}
1260
1261fn display_if(
1262 mut indent: Indented<Formatter>,
1263 cond: ExprId,
1264 body: ExprId,
1265 els: Option<ExprId>,
1266) -> fmt::Result {
1267 write!(indent, "If:")?;
1268 indent = set_indentation(indent, 1);
1269 write!(indent, "\n{cond}")?;
1270 write!(indent, "\n{body}")?;
1271 if let Some(e) = els {
1272 write!(indent, "\n{e}")?;
1273 }
1274 Ok(())
1275}
1276
1277fn display_index(mut indent: Indented<Formatter>, array: ExprId, index: ExprId) -> fmt::Result {
1278 write!(indent, "Index:")?;
1279 indent = set_indentation(indent, 1);
1280 write!(indent, "\n{array}")?;
1281 write!(indent, "\n{index}")?;
1282 Ok(())
1283}
1284
1285fn display_range(
1286 mut indent: Indented<Formatter>,
1287 start: Option<ExprId>,
1288 step: Option<ExprId>,
1289 end: Option<ExprId>,
1290) -> fmt::Result {
1291 write!(indent, "Range:")?;
1292 indent = set_indentation(indent, 1);
1293 match start {
1294 Some(e) => write!(indent, "\n{e}")?,
1295 None => write!(indent, "\n<no start>")?,
1296 }
1297 match step {
1298 Some(e) => write!(indent, "\n{e}")?,
1299 None => write!(indent, "\n<no step>")?,
1300 }
1301 match end {
1302 Some(e) => write!(indent, "\n{e}")?,
1303 None => write!(indent, "\n<no end>")?,
1304 }
1305 Ok(())
1306}
1307
1308fn display_struct(
1309 mut indent: Indented<Formatter>,
1310 name: &Res,
1311 copy: Option<ExprId>,
1312 fields: &Vec<FieldAssign>,
1313) -> fmt::Result {
1314 write!(indent, "Struct ({name}):")?;
1315 if copy.is_none() && fields.is_empty() {
1316 write!(indent, " <empty>")?;
1317 return Ok(());
1318 }
1319 indent = set_indentation(indent, 1);
1320 if let Some(copy) = copy {
1321 write!(indent, "\nCopy: {copy}")?;
1322 }
1323 for field in fields {
1324 write!(indent, "\n{field}")?;
1325 }
1326 Ok(())
1327}
1328
1329fn display_string(mut indent: Indented<Formatter>, components: &[StringComponent]) -> fmt::Result {
1330 write!(indent, "String:")?;
1331 indent = set_indentation(indent, 1);
1332 for component in components {
1333 match component {
1334 StringComponent::Expr(expr) => write!(indent, "\nExpr: {expr}")?,
1335 StringComponent::Lit(str) => write!(indent, "\nLit: {str:?}")?,
1336 }
1337 }
1338
1339 Ok(())
1340}
1341
1342fn display_update_index(
1343 mut indent: Indented<Formatter>,
1344 expr1: ExprId,
1345 expr2: ExprId,
1346 expr3: ExprId,
1347) -> fmt::Result {
1348 write!(indent, "UpdateIndex:")?;
1349 indent = set_indentation(indent, 1);
1350 write!(indent, "\n{expr1}")?;
1351 write!(indent, "\n{expr2}")?;
1352 write!(indent, "\n{expr3}")?;
1353 Ok(())
1354}
1355
1356fn display_tuple(mut indent: Indented<Formatter>, exprs: &Vec<ExprId>) -> fmt::Result {
1357 if exprs.is_empty() {
1358 write!(indent, "Unit")?;
1359 } else {
1360 write!(indent, "Tuple:")?;
1361 indent = set_indentation(indent, 1);
1362 for e in exprs {
1363 write!(indent, "\n{e}")?;
1364 }
1365 }
1366 Ok(())
1367}
1368
1369fn display_un_op(mut indent: Indented<Formatter>, op: UnOp, expr: ExprId) -> fmt::Result {
1370 write!(indent, "UnOp ({op}):")?;
1371 indent = set_indentation(indent, 1);
1372 write!(indent, "\n{expr}")?;
1373 Ok(())
1374}
1375
1376fn display_update_field(
1377 mut indent: Indented<Formatter>,
1378 record: ExprId,
1379 field: &Field,
1380 replace: ExprId,
1381) -> fmt::Result {
1382 write!(indent, "UpdateField:")?;
1383 indent = set_indentation(indent, 1);
1384 write!(indent, "\n{record}")?;
1385 write!(indent, "\n{field}")?;
1386 write!(indent, "\n{replace}")?;
1387 Ok(())
1388}
1389
1390fn display_var(mut f: Indented<Formatter>, res: Res, args: &[GenericArg]) -> fmt::Result {
1391 if args.is_empty() {
1392 write!(f, "Var: {res}")
1393 } else {
1394 write!(f, "Var:")?;
1395 f = set_indentation(f, 1);
1396 write!(f, "\nres: {res}")?;
1397 write!(f, "\ngenerics:")?;
1398 f = set_indentation(f, 2);
1399 for arg in args {
1400 write!(f, "\n{arg}")?;
1401 }
1402 Ok(())
1403 }
1404}
1405
1406fn display_while(mut indent: Indented<Formatter>, cond: ExprId, block: BlockId) -> fmt::Result {
1407 write!(indent, "While:")?;
1408 indent = set_indentation(indent, 1);
1409 write!(indent, "\n{cond}")?;
1410 write!(indent, "\n{block}")?;
1411 Ok(())
1412}
1413
1414/// A field assignment in a struct constructor expression.
1415#[derive(Clone, Debug, PartialEq)]
1416pub struct FieldAssign {
1417 /// The node ID.
1418 pub id: NodeId,
1419 /// The span.
1420 pub span: Span,
1421 /// The field to assign.
1422 pub field: Field,
1423 /// The value to assign to the field.
1424 pub value: ExprId,
1425}
1426
1427impl Display for FieldAssign {
1428 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1429 write!(
1430 f,
1431 "FieldsAssign {} {}: ({}) {}",
1432 self.id, self.span, self.field, self.value
1433 )
1434 }
1435}
1436
1437/// A string component.
1438#[derive(Clone, Debug, PartialEq)]
1439pub enum StringComponent {
1440 /// An expression.
1441 Expr(ExprId),
1442 /// A string literal.
1443 Lit(Rc<str>),
1444}
1445
1446/// A pattern.
1447#[derive(Clone, Debug, Eq, PartialEq)]
1448pub struct Pat {
1449 /// The node ID.
1450 pub id: PatId,
1451 /// The span.
1452 pub span: Span,
1453 /// The pattern type.
1454 pub ty: Ty,
1455 /// The pattern kind.
1456 pub kind: PatKind,
1457}
1458
1459impl Display for Pat {
1460 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1461 write!(
1462 f,
1463 "Pat {} {} [Type {}]: {}",
1464 self.id, self.span, self.ty, self.kind
1465 )
1466 }
1467}
1468
1469/// A pattern kind.
1470#[derive(Clone, Debug, Eq, PartialEq)]
1471pub enum PatKind {
1472 /// A binding.
1473 Bind(Ident),
1474 /// A discarded binding, `_`.
1475 Discard,
1476 /// A tuple: `(a, b, c)`.
1477 Tuple(Vec<PatId>),
1478}
1479
1480impl Display for PatKind {
1481 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1482 let mut indent = set_indentation(indented(f), 0);
1483 match self {
1484 PatKind::Bind(id) => {
1485 write!(indent, "Bind: {id}")?;
1486 }
1487 PatKind::Discard => write!(indent, "Discard")?,
1488 PatKind::Tuple(ps) => {
1489 if ps.is_empty() {
1490 write!(indent, "Unit")?;
1491 } else {
1492 write!(indent, "Tuple:")?;
1493 indent = set_indentation(indent, 1);
1494 for p in ps {
1495 write!(indent, "\n{p}")?;
1496 }
1497 }
1498 }
1499 }
1500 Ok(())
1501 }
1502}
1503
1504/// An identifier.
1505#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1506pub struct Ident {
1507 /// The node ID.
1508 pub id: LocalVarId,
1509 /// The span.
1510 pub span: Span,
1511 /// The identifier name.
1512 pub name: Rc<str>,
1513}
1514
1515impl Display for Ident {
1516 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1517 write!(f, "Ident {} {} \"{}\"", self.id, self.span, self.name)
1518 }
1519}
1520
1521/// An attribute.
1522#[derive(Clone, Debug, PartialEq)]
1523pub enum Attr {
1524 /// Indicates that a callable is an entry point to a program.
1525 EntryPoint,
1526 /// Indicates that a callable is a measurement.
1527 Measurement,
1528 /// Indicates that a callable is a reset.
1529 Reset,
1530}
1531
1532/// A field.
1533#[derive(Clone, Debug, Eq, PartialEq)]
1534pub enum Field {
1535 /// A field path.
1536 Path(FieldPath),
1537 /// A primitive field for a built-in type.
1538 Prim(PrimField),
1539 /// An invalid field.
1540 Err,
1541}
1542
1543impl Display for Field {
1544 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1545 match self {
1546 Field::Path(path) => write!(f, "Path({:?})", path.indices),
1547 Field::Prim(prim) => write!(f, "Prim({prim:?}"),
1548 Field::Err => f.write_str("Err"),
1549 }
1550 }
1551}
1552
1553/// A path to a field in a tuple or user-defined type.
1554#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
1555pub struct FieldPath {
1556 /// The tuple item indices to follow in order from top to bottom.
1557 pub indices: Vec<usize>,
1558}
1559
1560/// A primitive field for a built-in type.
1561#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1562pub enum PrimField {
1563 /// The start of a range.
1564 Start,
1565 /// The step of a range.
1566 Step,
1567 /// The end of a range.
1568 End,
1569}
1570
1571impl FromStr for PrimField {
1572 type Err = ();
1573
1574 fn from_str(s: &str) -> result::Result<Self, <Self as FromStr>::Err> {
1575 match s {
1576 "Start" => Ok(Self::Start),
1577 "Step" => Ok(Self::Step),
1578 "End" => Ok(Self::End),
1579 _ => Err(()),
1580 }
1581 }
1582}
1583
1584/// The visibility of a declaration.
1585#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1586pub enum Visibility {
1587 /// Visible everywhere.
1588 Public,
1589 /// Visible within a package.
1590 Internal,
1591}
1592
1593/// A callable kind.
1594#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
1595pub enum CallableKind {
1596 /// A function.
1597 Function,
1598 /// An operation.
1599 Operation,
1600}
1601
1602impl Display for CallableKind {
1603 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1604 match self {
1605 CallableKind::Function => f.write_str("function"),
1606 CallableKind::Operation => f.write_str("operation"),
1607 }
1608 }
1609}
1610
1611/// The mutability of a binding.
1612#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1613pub enum Mutability {
1614 /// An immutable binding.
1615 Immutable,
1616 /// A mutable binding.
1617 Mutable,
1618}
1619
1620/// The source of an allocated qubit.
1621#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1622pub enum QubitSource {
1623 /// A qubit initialized to the zero state.
1624 Fresh,
1625 /// A qubit borrowed from another part of the program that may be in any state, and is expected
1626 /// to be returned to that state before being released.
1627 Dirty,
1628}
1629
1630/// A literal.
1631#[derive(Clone, Debug, PartialEq)]
1632pub enum Lit {
1633 /// A big integer literal.
1634 BigInt(BigInt),
1635 /// A boolean literal.
1636 Bool(bool),
1637 /// A floating-point literal.
1638 Double(f64),
1639 /// An integer literal.
1640 Int(i64),
1641 /// A Pauli operator literal.
1642 Pauli(Pauli),
1643 /// A measurement result literal.
1644 Result(Result),
1645}
1646
1647impl Display for Lit {
1648 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1649 match self {
1650 Lit::BigInt(val) => write!(f, "BigInt({val})")?,
1651 Lit::Bool(val) => write!(f, "Bool({val})")?,
1652 Lit::Double(val) => write!(f, "Double({val})")?,
1653 Lit::Int(val) => write!(f, "Int({val})")?,
1654 Lit::Pauli(val) => write!(f, "Pauli({val:?})")?,
1655 Lit::Result(val) => write!(f, "Result({val:?})")?,
1656 }
1657 Ok(())
1658 }
1659}
1660
1661/// A measurement result.
1662#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1663pub enum Result {
1664 /// The zero eigenvalue.
1665 Zero,
1666 /// The one eigenvalue.
1667 One,
1668}
1669
1670/// A Pauli operator.
1671#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1672pub enum Pauli {
1673 /// The Pauli I operator.
1674 I,
1675 /// The Pauli X operator.
1676 X,
1677 /// The Pauli Y operator.
1678 Y,
1679 /// The Pauli Z operator.
1680 Z,
1681}
1682
1683/// A functor that may be applied to an operation.
1684#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1685pub enum Functor {
1686 /// The adjoint functor.
1687 Adj,
1688 /// The controlled functor.
1689 Ctl,
1690}
1691
1692impl Display for Functor {
1693 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1694 match self {
1695 Functor::Adj => f.write_str("Adj"),
1696 Functor::Ctl => f.write_str("Ctl"),
1697 }
1698 }
1699}
1700
1701/// A unary operator.
1702#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1703pub enum UnOp {
1704 /// A functor application.
1705 Functor(Functor),
1706 /// Negation: `-`.
1707 Neg,
1708 /// Bitwise NOT: `~~~`.
1709 NotB,
1710 /// Logical NOT: `not`.
1711 NotL,
1712 /// A leading `+`.
1713 Pos,
1714 /// Unwrap a user-defined type: `!`.
1715 Unwrap,
1716}
1717
1718impl Display for UnOp {
1719 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1720 match self {
1721 UnOp::Functor(func) => write!(f, "Functor {func:?}")?,
1722 _ => fmt::Debug::fmt(self, f)?,
1723 }
1724 Ok(())
1725 }
1726}
1727
1728/// A binary operator.
1729#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1730pub enum BinOp {
1731 /// Addition: `+`.
1732 Add,
1733 /// Bitwise AND: `&&&`.
1734 AndB,
1735 /// Logical AND: `and`.
1736 AndL,
1737 /// Division: `/`.
1738 Div,
1739 /// Equality: `==`.
1740 Eq,
1741 /// Exponentiation: `^`.
1742 Exp,
1743 /// Greater than: `>`.
1744 Gt,
1745 /// Greater than or equal: `>=`.
1746 Gte,
1747 /// Less than: `<`.
1748 Lt,
1749 /// Less than or equal: `<=`.
1750 Lte,
1751 /// Modulus: `%`.
1752 Mod,
1753 /// Multiplication: `*`.
1754 Mul,
1755 /// Inequality: `!=`.
1756 Neq,
1757 /// Bitwise OR: `|||`.
1758 OrB,
1759 /// Logical OR: `or`.
1760 OrL,
1761 /// Shift left: `<<<`.
1762 Shl,
1763 /// Shift right: `>>>`.
1764 Shr,
1765 /// Subtraction: `-`.
1766 Sub,
1767 /// Bitwise XOR: `^^^`.
1768 XorB,
1769}
1770