microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.2.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_fir/src/fir.rs

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