microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.3.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_fir/src/fir.rs

1687lines · 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 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)]
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)]
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}
459
460/// A FIR package store.
461#[derive(Debug, Default)]
462pub struct PackageStore(IndexMap<PackageId, Package>);
463
464impl PackageStoreLookup for PackageStore {
465 fn get_block(&self, id: StoreBlockId) -> &Block {
466 self.get(id.package).get_block(id.block)
467 }
468
469 fn get_expr(&self, id: StoreExprId) -> &Expr {
470 self.get(id.package).get_expr(id.expr)
471 }
472
473 fn get_global(&self, id: StoreItemId) -> Option<Global> {
474 self.get(id.package).get_global(id.item)
475 }
476
477 fn get_pat(&self, id: StorePatId) -> &Pat {
478 self.get(id.package).get_pat(id.pat)
479 }
480
481 fn get_stmt(&self, id: StoreStmtId) -> &Stmt {
482 self.get(id.package).get_stmt(id.stmt)
483 }
484}
485
486impl PackageStore {
487 /// Gets a package from the store.
488 #[must_use]
489 pub fn get(&self, id: PackageId) -> &Package {
490 self.0.get(id).expect("store should have package")
491 }
492
493 /// Gets a mutable package from the store.
494 #[must_use]
495 pub fn get_mut(&mut self, id: PackageId) -> &mut Package {
496 self.0.get_mut(id).expect("store should have package")
497 }
498
499 /// Inserts a package to the store.
500 pub fn insert(&mut self, id: PackageId, package: Package) {
501 self.0.insert(id, package);
502 }
503
504 /// Gets a package store iterator.
505 #[must_use]
506 pub fn iter(&self) -> Iter<PackageId, Package> {
507 self.0.iter()
508 }
509
510 /// Creates a package store.
511 #[must_use]
512 pub fn new() -> Self {
513 Self::default()
514 }
515}
516
517impl<'a> IntoIterator for &'a PackageStore {
518 type IntoIter = qsc_data_structures::index_map::Iter<'a, PackageId, Package>;
519 type Item = (PackageId, &'a Package);
520
521 fn into_iter(self) -> Self::IntoIter {
522 self.iter()
523 }
524}
525
526/// A trait to find elements in a package.
527pub trait PackageLookup {
528 /// Gets a block.
529 fn get_block(&self, id: BlockId) -> &Block;
530 /// Gets an expression.
531 fn get_expr(&self, id: ExprId) -> &Expr;
532 /// Gets a global.
533 fn get_global(&self, id: LocalItemId) -> Option<Global>;
534 /// Gets an item.
535 fn get_item(&self, id: LocalItemId) -> &Item;
536 /// Gets a pat.
537 fn get_pat(&self, id: PatId) -> &Pat;
538 /// Gets a statement.
539 fn get_stmt(&self, id: StmtId) -> &Stmt;
540}
541
542/// The root node of the FIR.
543/// ### Notes
544/// We maintain a dense map of ids within the package.
545/// `BlockId`, `ExprId`, `PatId`, `StmtId`, and `NodeId`s are all assigned
546/// from a type specific counter in the assigner.
547///
548/// `BlockId`, `ExprId`, `PatId`, `StmtId` ids don't leak and are only used
549/// within the containing node. Node ids are used to identify nodes within
550/// the package and require mapping from the HIR node id to the new FIR node id.
551/// `PackageId`s and `LocalItemId`s are 1:1 from the HIR and are not remapped.
552#[derive(Clone, Debug)]
553pub struct Package {
554 /// The items in the package.
555 pub items: IndexMap<LocalItemId, Item>,
556 /// The entry expression for an executable package.
557 pub entry: Option<ExprId>,
558 /// The control flow graph for the entry expression in the package.
559 pub entry_exec_graph: Rc<[ExecGraphNode]>,
560 /// The blocks in the package.
561 pub blocks: IndexMap<BlockId, Block>,
562 /// The expressions in the package.
563 pub exprs: IndexMap<ExprId, Expr>,
564 /// The patterns in the package.
565 pub pats: IndexMap<PatId, Pat>,
566 /// The statements in the package.
567 pub stmts: IndexMap<StmtId, Stmt>,
568}
569
570impl Display for Package {
571 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
572 let mut indent = set_indentation(indented(f), 0);
573 write!(indent, "Package:")?;
574 indent = set_indentation(indent, 1);
575 if let Some(e) = &self.entry {
576 write!(indent, "\nEntry Expression: {e}")?;
577 }
578
579 write!(indent, "\nItems:")?;
580 indent = set_indentation(indent, 2);
581 for item in self.items.values() {
582 write!(indent, "\n{item}")?;
583 }
584
585 indent = set_indentation(indent, 1);
586 write!(indent, "\nBlocks:")?;
587 indent = set_indentation(indent, 2);
588 for block in self.blocks.values() {
589 write!(indent, "\n{block}")?;
590 }
591
592 indent = set_indentation(indent, 1);
593 write!(indent, "\nStmts:")?;
594 indent = set_indentation(indent, 2);
595 for stmt in self.stmts.values() {
596 write!(indent, "\n{stmt}")?;
597 }
598
599 indent = set_indentation(indent, 1);
600 write!(indent, "\nExprs:")?;
601 indent = set_indentation(indent, 2);
602 for expr in self.exprs.values() {
603 write!(indent, "\n{expr}")?;
604 }
605
606 indent = set_indentation(indent, 1);
607 write!(indent, "\nPats:")?;
608 indent = set_indentation(indent, 2);
609 for pat in self.pats.values() {
610 write!(indent, "\n{pat}")?;
611 }
612 Ok(())
613 }
614}
615
616impl PackageLookup for Package {
617 fn get_block(&self, id: BlockId) -> &Block {
618 self.blocks.get(id).expect("Block not found")
619 }
620
621 fn get_expr(&self, id: ExprId) -> &Expr {
622 self.exprs.get(id).expect("Expression not found")
623 }
624
625 fn get_global(&self, id: LocalItemId) -> Option<Global> {
626 match &self.items.get(id)?.kind {
627 ItemKind::Callable(callable) => Some(Global::Callable(callable)),
628 ItemKind::Namespace(..) => None,
629 ItemKind::Ty(..) => Some(Global::Udt),
630 }
631 }
632
633 fn get_item(&self, id: LocalItemId) -> &Item {
634 self.items.get(id).expect("Item not found")
635 }
636
637 fn get_pat(&self, id: PatId) -> &Pat {
638 self.pats.get(id).expect("Pattern not found")
639 }
640
641 fn get_stmt(&self, id: StmtId) -> &Stmt {
642 self.stmts.get(id).expect("Statement not found")
643 }
644}
645
646/// An item.
647#[derive(Clone, Debug, PartialEq)]
648pub struct Item {
649 /// The ID.
650 pub id: LocalItemId,
651 /// The span.
652 pub span: Span,
653 /// The parent item.
654 pub parent: Option<LocalItemId>,
655 /// The documentation.
656 pub doc: Rc<str>,
657 /// The attributes.
658 pub attrs: Vec<Attr>,
659 /// The visibility.
660 pub visibility: Visibility,
661 /// The item kind.
662 pub kind: ItemKind,
663}
664
665impl Display for Item {
666 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
667 let mut indent = set_indentation(indented(f), 0);
668 write!(
669 indent,
670 "Item {} {} ({:?}):",
671 self.id, self.span, self.visibility
672 )?;
673
674 indent = set_indentation(indent, 1);
675 if let Some(parent) = self.parent {
676 write!(indent, "\nParent: {parent}")?;
677 }
678
679 if !self.doc.is_empty() {
680 write!(indent, "\nDoc:")?;
681 indent = set_indentation(indent, 2);
682 write!(indent, "\n{}", self.doc)?;
683 indent = set_indentation(indent, 1);
684 }
685
686 for attr in &self.attrs {
687 write!(indent, "\n{attr:?}")?;
688 }
689
690 write!(indent, "\n{}", self.kind)?;
691 Ok(())
692 }
693}
694
695/// An item kind.
696#[derive(Clone, Debug, PartialEq)]
697pub enum ItemKind {
698 /// A `function` or `operation` declaration.
699 Callable(CallableDecl),
700 /// A `namespace` declaration.
701 Namespace(Ident, Vec<LocalItemId>),
702 /// A `newtype` declaration.
703 Ty(Ident, Udt),
704}
705
706impl Display for ItemKind {
707 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
708 match self {
709 ItemKind::Callable(decl) => write!(f, "{decl}"),
710 ItemKind::Namespace(name, items) => {
711 write!(f, "Namespace ({name}):")?;
712 let mut items = items.iter();
713 if let Some(item) = items.next() {
714 write!(f, " Item {item}")?;
715 for item in items {
716 write!(f, ", Item {item}")?;
717 }
718 Ok(())
719 } else {
720 write!(f, " <empty>")
721 }
722 }
723 ItemKind::Ty(name, udt) => write!(f, "Type ({name}): {udt}"),
724 }
725 }
726}
727
728/// A callable declaration header.
729#[derive(Clone, Debug, PartialEq)]
730pub struct CallableDecl {
731 /// The node ID.
732 pub id: NodeId,
733 /// The span.
734 pub span: Span,
735 /// The callable kind.
736 pub kind: CallableKind,
737 /// The name of the callable.
738 pub name: Ident,
739 /// The generic parameters to the callable.
740 pub generics: Vec<GenericParam>,
741 /// The input to the callable.
742 pub input: PatId,
743 /// The return type of the callable.
744 pub output: Ty,
745 /// The functors supported by the callable.
746 pub functors: FunctorSetValue,
747 /// The callable implementation.
748 pub implementation: CallableImpl,
749}
750
751impl CallableDecl {
752 /// The type scheme of the callable.
753 #[must_use]
754 pub fn scheme<'a>(&self, f: impl Fn(PatId) -> &'a Pat) -> Scheme {
755 Scheme::new(
756 self.generics.clone(),
757 Box::new(Arrow {
758 kind: self.kind,
759 input: Box::new(f(self.input).ty.clone()),
760 output: Box::new(self.output.clone()),
761 functors: FunctorSet::Value(self.functors),
762 }),
763 )
764 }
765}
766
767impl Display for CallableDecl {
768 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
769 let mut indent = set_indentation(indented(f), 0);
770 write!(
771 indent,
772 "Callable {} {} ({}):",
773 self.id, self.span, self.kind
774 )?;
775 indent = set_indentation(indent, 1);
776 write!(indent, "\nname: {}", self.name)?;
777 if !self.generics.is_empty() {
778 write!(indent, "\ngenerics:")?;
779 indent = set_indentation(indent, 2);
780 for (ix, param) in self.generics.iter().enumerate() {
781 write!(indent, "\n{ix}: {param}")?;
782 }
783 indent = set_indentation(indent, 1);
784 }
785 write!(indent, "\ninput: {}", self.input)?;
786 write!(indent, "\noutput: {}", self.output)?;
787 write!(indent, "\nfunctors: {}", self.functors)?;
788 write!(indent, "\nimplementation: {}", self.implementation)?;
789 Ok(())
790 }
791}
792
793/// A callable implementations.
794#[derive(Clone, Debug, PartialEq)]
795pub enum CallableImpl {
796 /// An intrinsic callable implementation.
797 Intrinsic,
798 /// A specialized callable implementation.
799 Spec(SpecImpl),
800}
801
802impl Display for CallableImpl {
803 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
804 let mut indent = set_indentation(indented(f), 0);
805 match self {
806 CallableImpl::Intrinsic => {
807 write!(indent, "Instrinsic")?;
808 }
809 CallableImpl::Spec(spec_impl) => {
810 write!(indent, "Spec:")?;
811 indent = set_indentation(indent, 1);
812 write!(indent, "\n{spec_impl}")?;
813 }
814 }
815
816 Ok(())
817 }
818}
819
820/// A specialized implementation.
821#[derive(Clone, Debug, PartialEq)]
822pub struct SpecImpl {
823 /// The body implementation.
824 pub body: SpecDecl,
825 /// The adjoint specialization.
826 pub adj: Option<SpecDecl>,
827 /// The controlled specialization.
828 pub ctl: Option<SpecDecl>,
829 /// The controlled adjoint specialization.
830 pub ctl_adj: Option<SpecDecl>,
831}
832
833impl Display for SpecImpl {
834 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
835 let mut indent = set_indentation(indented(f), 0);
836 write!(indent, "SpecImpl:",)?;
837 indent = set_indentation(indent, 1);
838 write!(indent, "\nbody: {}", self.body)?;
839 match &self.adj {
840 Some(spec) => write!(indent, "\nadj: {spec}")?,
841 None => write!(indent, "\nadj: <none>")?,
842 }
843 match &self.ctl {
844 Some(spec) => write!(indent, "\nctl: {spec}")?,
845 None => write!(indent, "\nctl: <none>")?,
846 }
847 match &self.ctl_adj {
848 Some(spec) => write!(indent, "\nctl-adj: {spec}")?,
849 None => write!(indent, "\nctl-adj: <none>")?,
850 }
851 Ok(())
852 }
853}
854
855/// A specialization declaration.
856#[derive(Clone, Debug, PartialEq)]
857pub struct SpecDecl {
858 /// The node ID.
859 pub id: NodeId,
860 /// The span.
861 pub span: Span,
862 /// The block that implements the specialization.
863 pub block: BlockId,
864 /// The input of the specialization.
865 pub input: Option<PatId>,
866 /// The flattened control flow graph for the execution of the specialization.
867 pub exec_graph: Rc<[ExecGraphNode]>,
868}
869
870impl Display for SpecDecl {
871 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
872 write!(
873 f,
874 "SpecDecl {} {}: {:?} {}",
875 self.id, self.span, self.input, self.block
876 )
877 }
878}
879
880#[derive(Copy, Clone, Debug, PartialEq)]
881/// A node within the control flow graph.
882pub enum ExecGraphNode {
883 /// A binding of a value to a variable.
884 Bind(PatId),
885 /// An expression to execute.
886 Expr(ExprId),
887 /// A statement to track for debugging.
888 Stmt(StmtId),
889 /// An unconditional jump with to given location.
890 Jump(u32),
891 /// A conditional jump with to given location, where the jump is only taken if the condition is
892 /// true.
893 JumpIf(u32),
894 /// A conditional jump with to given location, where the jump is only taken if the condition is
895 /// false.
896 JumpIfNot(u32),
897 /// An indication that the current accumulated result value should be stored into the value stack.
898 Store,
899 /// A no-op Unit node that tells execution to insert a unit value into the current accumulated result.
900 Unit,
901 /// The end of the control flow graph.
902 Ret,
903}
904
905/// A sequenced block of statements.
906#[derive(Clone, Debug, PartialEq)]
907pub struct Block {
908 /// The node ID.
909 pub id: BlockId,
910 /// The span.
911 pub span: Span,
912 /// The block type.
913 pub ty: Ty,
914 /// The statements in the block.
915 pub stmts: Vec<StmtId>,
916}
917
918impl Display for Block {
919 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
920 if self.stmts.is_empty() {
921 write!(f, "Block {} {}: <empty>", self.id, self.span)?;
922 } else {
923 let mut indent = set_indentation(indented(f), 0);
924 write!(
925 indent,
926 "Block {} {} [Type {}]:",
927 self.id, self.span, self.ty
928 )?;
929 indent = set_indentation(indent, 1);
930 for s in &self.stmts {
931 write!(indent, "\n{s}")?;
932 }
933 }
934 Ok(())
935 }
936}
937
938/// A statement.
939#[derive(Clone, Debug, PartialEq)]
940pub struct Stmt {
941 /// The stmt ID.
942 pub id: StmtId,
943 /// The span.
944 pub span: Span,
945 /// The statement kind.
946 pub kind: StmtKind,
947 /// The locations within the containing control flow graph for the current statement.
948 pub exec_graph_range: ops::Range<usize>,
949}
950
951impl Display for Stmt {
952 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
953 write!(f, "Stmt {} {}: {}", self.id, self.span, self.kind)
954 }
955}
956
957/// A statement kind.
958#[derive(Clone, Debug, PartialEq)]
959pub enum StmtKind {
960 /// An expression without a trailing semicolon.
961 Expr(ExprId),
962 /// An item.
963 Item(LocalItemId),
964 /// A let or mutable binding: `let a = b;` or `mutable x = b;`.
965 Local(Mutability, PatId, ExprId),
966 /// An expression with a trailing semicolon.
967 Semi(ExprId),
968}
969
970impl Display for StmtKind {
971 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
972 let mut indent = set_indentation(indented(f), 0);
973 match self {
974 StmtKind::Expr(e) => write!(indent, "Expr: {e}")?,
975 StmtKind::Item(item) => write!(indent, "Item: {item}")?,
976 StmtKind::Local(m, lhs, rhs) => {
977 write!(indent, "Local ({m:?}):")?;
978 indent = set_indentation(indent, 1);
979 write!(indent, "\n{lhs}")?;
980 write!(indent, "\n{rhs}")?;
981 }
982 StmtKind::Semi(e) => write!(indent, "Semi: {e}")?,
983 }
984 Ok(())
985 }
986}
987
988/// An expression.
989#[derive(Clone, Debug, PartialEq)]
990pub struct Expr {
991 /// The expr ID.
992 pub id: ExprId,
993 /// The span.
994 pub span: Span,
995 /// The expression type.
996 pub ty: Ty,
997 /// The expression kind.
998 pub kind: ExprKind,
999 /// The locations within the containing control flow graph for the current expression.
1000 pub exec_graph_range: ops::Range<usize>,
1001}
1002
1003impl Display for Expr {
1004 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1005 write!(
1006 f,
1007 "Expr {} {} [Type {}]: {}",
1008 self.id, self.span, self.ty, self.kind
1009 )
1010 }
1011}
1012
1013/// An expression kind.
1014#[derive(Clone, Debug, PartialEq)]
1015pub enum ExprKind {
1016 /// An array: `[a, b, c]`.
1017 Array(Vec<ExprId>),
1018 /// An array of literal values, ie: `[1, 2, 3]`.
1019 ArrayLit(Vec<ExprId>),
1020 /// An array constructed by repeating a value: `[a, size = b]`.
1021 ArrayRepeat(ExprId, ExprId),
1022 /// An assignment: `set a = b`.
1023 Assign(ExprId, ExprId),
1024 /// An assignment with a compound operator. For example: `set a += b`.
1025 AssignOp(BinOp, ExprId, ExprId),
1026 /// An assignment with a compound field update operator: `set a w/= B <- c`.
1027 AssignField(ExprId, Field, ExprId),
1028 /// An assignment with a compound index update operator: `set a w/= b <- c`.
1029 AssignIndex(ExprId, ExprId, ExprId),
1030 /// A binary operator.
1031 BinOp(BinOp, ExprId, ExprId),
1032 /// A block: `{ ... }`.
1033 Block(BlockId),
1034 /// A call: `a(b)`.
1035 Call(ExprId, ExprId),
1036 /// A closure that fixes the vector of local variables as arguments to the callable item.
1037 Closure(Vec<LocalVarId>, LocalItemId),
1038 /// A failure: `fail "message"`.
1039 Fail(ExprId),
1040 /// A field accessor: `a::F`.
1041 Field(ExprId, Field),
1042 /// An unspecified expression, _, which may indicate partial application or discards
1043 Hole,
1044 /// An if expression with an optional else block: `if a { ... } else { ... }`.
1045 ///
1046 /// Note that, as a special case, `elif ...` is effectively parsed as `else if ...`, without a
1047 /// block wrapping the `if`. This distinguishes `elif ...` from `else { if ... }`, which does
1048 /// have a block.
1049 If(ExprId, ExprId, Option<ExprId>),
1050 /// An index accessor: `a[b]`.
1051 Index(ExprId, ExprId),
1052 /// A literal.
1053 Lit(Lit),
1054 /// A range: `start..step..end`, `start..end`, `start...`, `...end`, or `...`.
1055 Range(Option<ExprId>, Option<ExprId>, Option<ExprId>),
1056 /// A return: `return a`.
1057 Return(ExprId),
1058 /// A string.
1059 String(Vec<StringComponent>),
1060 /// Update array index: `a w/ b <- c`.
1061 UpdateIndex(ExprId, ExprId, ExprId),
1062 /// A tuple: `(a, b, c)`.
1063 Tuple(Vec<ExprId>),
1064 /// A unary operator.
1065 UnOp(UnOp, ExprId),
1066 /// A record field update: `a w/ B <- c`.
1067 UpdateField(ExprId, Field, ExprId),
1068 /// A variable and its generic arguments.
1069 Var(Res, Vec<GenericArg>),
1070 /// A while loop: `while a { ... }`.
1071 While(ExprId, BlockId),
1072}
1073
1074impl Display for ExprKind {
1075 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1076 let mut indent = set_indentation(indented(f), 0);
1077 match self {
1078 ExprKind::Array(exprs) | ExprKind::ArrayLit(exprs) => display_array(indent, exprs)?,
1079 ExprKind::ArrayRepeat(val, size) => display_array_repeat(indent, *val, *size)?,
1080 ExprKind::Assign(lhs, rhs) => display_assign(indent, *lhs, *rhs)?,
1081 ExprKind::AssignOp(op, lhs, rhs) => display_assign_op(indent, *op, *lhs, *rhs)?,
1082 ExprKind::AssignField(record, field, replace) => {
1083 display_assign_field(indent, *record, field, *replace)?;
1084 }
1085 ExprKind::AssignIndex(container, item, replace) => {
1086 display_assign_index(indent, *container, *item, *replace)?;
1087 }
1088 ExprKind::BinOp(op, lhs, rhs) => display_bin_op(indent, *op, *lhs, *rhs)?,
1089 ExprKind::Block(block) => write!(indent, "Expr Block: {block}")?,
1090 ExprKind::Call(callable, arg) => display_call(indent, *callable, *arg)?,
1091 ExprKind::Closure(args, callable) => display_closure(indent, args, *callable)?,
1092 ExprKind::Fail(e) => write!(indent, "Fail: {e}")?,
1093 ExprKind::Field(expr, field) => display_field(indent, *expr, field)?,
1094 ExprKind::Hole => write!(indent, "Hole")?,
1095 ExprKind::If(cond, body, els) => display_if(indent, *cond, *body, *els)?,
1096 ExprKind::Index(array, index) => display_index(indent, *array, *index)?,
1097 ExprKind::Lit(lit) => write!(indent, "Lit: {lit}")?,
1098 ExprKind::Range(start, step, end) => display_range(indent, *start, *step, *end)?,
1099 ExprKind::Return(e) => write!(indent, "Return: {e}")?,
1100 ExprKind::String(components) => display_string(indent, components)?,
1101 ExprKind::UpdateIndex(expr1, expr2, expr3) => {
1102 display_update_index(indent, *expr1, *expr2, *expr3)?;
1103 }
1104 ExprKind::Tuple(exprs) => display_tuple(indent, exprs)?,
1105 ExprKind::UnOp(op, expr) => display_un_op(indent, *op, *expr)?,
1106 ExprKind::UpdateField(record, field, replace) => {
1107 display_update_field(indent, *record, field, *replace)?;
1108 }
1109 ExprKind::Var(res, args) => display_var(indent, *res, args)?,
1110 ExprKind::While(cond, block) => display_while(indent, *cond, *block)?,
1111 }
1112 Ok(())
1113 }
1114}
1115
1116fn display_array(mut indent: Indented<Formatter>, exprs: &Vec<ExprId>) -> fmt::Result {
1117 write!(indent, "Array:")?;
1118 indent = set_indentation(indent, 1);
1119 for e in exprs {
1120 write!(indent, "\n{e}")?;
1121 }
1122 Ok(())
1123}
1124
1125fn display_array_repeat(mut indent: Indented<Formatter>, val: ExprId, size: ExprId) -> fmt::Result {
1126 write!(indent, "ArrayRepeat:")?;
1127 indent = set_indentation(indent, 1);
1128 write!(indent, "\n{val}")?;
1129 write!(indent, "\n{size}")?;
1130 Ok(())
1131}
1132
1133fn display_assign(mut indent: Indented<Formatter>, lhs: ExprId, rhs: ExprId) -> fmt::Result {
1134 write!(indent, "Assign:")?;
1135 indent = set_indentation(indent, 1);
1136 write!(indent, "\n{lhs}")?;
1137 write!(indent, "\n{rhs}")?;
1138 Ok(())
1139}
1140
1141fn display_assign_op(
1142 mut indent: Indented<Formatter>,
1143 op: BinOp,
1144 lhs: ExprId,
1145 rhs: ExprId,
1146) -> fmt::Result {
1147 write!(indent, "AssignOp ({op:?}):")?;
1148 indent = set_indentation(indent, 1);
1149 write!(indent, "\n{lhs}")?;
1150 write!(indent, "\n{rhs}")?;
1151 Ok(())
1152}
1153
1154fn display_assign_field(
1155 mut indent: Indented<Formatter>,
1156 record: ExprId,
1157 field: &Field,
1158 replace: ExprId,
1159) -> fmt::Result {
1160 write!(indent, "AssignField:")?;
1161 indent = set_indentation(indent, 1);
1162 write!(indent, "\n{record}")?;
1163 write!(indent, "\n{field}")?;
1164 write!(indent, "\n{replace}")?;
1165 Ok(())
1166}
1167
1168fn display_assign_index(
1169 mut indent: Indented<Formatter>,
1170 array: ExprId,
1171 index: ExprId,
1172 replace: ExprId,
1173) -> fmt::Result {
1174 write!(indent, "AssignIndex:")?;
1175 indent = set_indentation(indent, 1);
1176 write!(indent, "\n{array}")?;
1177 write!(indent, "\n{index}")?;
1178 write!(indent, "\n{replace}")?;
1179 Ok(())
1180}
1181
1182fn display_bin_op(
1183 mut indent: Indented<Formatter>,
1184 op: BinOp,
1185 lhs: ExprId,
1186 rhs: ExprId,
1187) -> fmt::Result {
1188 write!(indent, "BinOp ({op:?}):")?;
1189 indent = set_indentation(indent, 1);
1190 write!(indent, "\n{lhs}")?;
1191 write!(indent, "\n{rhs}")?;
1192 Ok(())
1193}
1194
1195fn display_call(mut indent: Indented<Formatter>, callable: ExprId, arg: ExprId) -> fmt::Result {
1196 write!(indent, "Call:")?;
1197 indent = set_indentation(indent, 1);
1198 write!(indent, "\n{callable}")?;
1199 write!(indent, "\n{arg}")?;
1200 Ok(())
1201}
1202
1203fn display_closure(
1204 mut f: Indented<Formatter>,
1205 args: &[LocalVarId],
1206 callable: LocalItemId,
1207) -> fmt::Result {
1208 f.write_str("Closure([")?;
1209 let mut args = args.iter();
1210 if let Some(arg) = args.next() {
1211 write!(f, "{arg}")?;
1212 }
1213 for arg in args {
1214 write!(f, ", {arg}")?;
1215 }
1216 write!(f, "], {callable})")
1217}
1218
1219fn display_field(mut indent: Indented<Formatter>, expr: ExprId, field: &Field) -> fmt::Result {
1220 write!(indent, "Field:")?;
1221 indent = set_indentation(indent, 1);
1222 write!(indent, "\n{expr}")?;
1223 write!(indent, "\n{field:?}")?;
1224 Ok(())
1225}
1226
1227fn display_if(
1228 mut indent: Indented<Formatter>,
1229 cond: ExprId,
1230 body: ExprId,
1231 els: Option<ExprId>,
1232) -> fmt::Result {
1233 write!(indent, "If:")?;
1234 indent = set_indentation(indent, 1);
1235 write!(indent, "\n{cond}")?;
1236 write!(indent, "\n{body}")?;
1237 if let Some(e) = els {
1238 write!(indent, "\n{e}")?;
1239 }
1240 Ok(())
1241}
1242
1243fn display_index(mut indent: Indented<Formatter>, array: ExprId, index: ExprId) -> fmt::Result {
1244 write!(indent, "Index:")?;
1245 indent = set_indentation(indent, 1);
1246 write!(indent, "\n{array}")?;
1247 write!(indent, "\n{index}")?;
1248 Ok(())
1249}
1250
1251fn display_range(
1252 mut indent: Indented<Formatter>,
1253 start: Option<ExprId>,
1254 step: Option<ExprId>,
1255 end: Option<ExprId>,
1256) -> fmt::Result {
1257 write!(indent, "Range:")?;
1258 indent = set_indentation(indent, 1);
1259 match start {
1260 Some(e) => write!(indent, "\n{e}")?,
1261 None => write!(indent, "\n<no start>")?,
1262 }
1263 match step {
1264 Some(e) => write!(indent, "\n{e}")?,
1265 None => write!(indent, "\n<no step>")?,
1266 }
1267 match end {
1268 Some(e) => write!(indent, "\n{e}")?,
1269 None => write!(indent, "\n<no end>")?,
1270 }
1271 Ok(())
1272}
1273
1274fn display_string(mut indent: Indented<Formatter>, components: &[StringComponent]) -> fmt::Result {
1275 write!(indent, "String:")?;
1276 indent = set_indentation(indent, 1);
1277 for component in components {
1278 match component {
1279 StringComponent::Expr(expr) => write!(indent, "\nExpr: {expr}")?,
1280 StringComponent::Lit(str) => write!(indent, "\nLit: {str:?}")?,
1281 }
1282 }
1283
1284 Ok(())
1285}
1286
1287fn display_update_index(
1288 mut indent: Indented<Formatter>,
1289 expr1: ExprId,
1290 expr2: ExprId,
1291 expr3: ExprId,
1292) -> fmt::Result {
1293 write!(indent, "UpdateIndex:")?;
1294 indent = set_indentation(indent, 1);
1295 write!(indent, "\n{expr1}")?;
1296 write!(indent, "\n{expr2}")?;
1297 write!(indent, "\n{expr3}")?;
1298 Ok(())
1299}
1300
1301fn display_tuple(mut indent: Indented<Formatter>, exprs: &Vec<ExprId>) -> fmt::Result {
1302 if exprs.is_empty() {
1303 write!(indent, "Unit")?;
1304 } else {
1305 write!(indent, "Tuple:")?;
1306 indent = set_indentation(indent, 1);
1307 for e in exprs {
1308 write!(indent, "\n{e}")?;
1309 }
1310 }
1311 Ok(())
1312}
1313
1314fn display_un_op(mut indent: Indented<Formatter>, op: UnOp, expr: ExprId) -> fmt::Result {
1315 write!(indent, "UnOp ({op}):")?;
1316 indent = set_indentation(indent, 1);
1317 write!(indent, "\n{expr}")?;
1318 Ok(())
1319}
1320
1321fn display_update_field(
1322 mut indent: Indented<Formatter>,
1323 record: ExprId,
1324 field: &Field,
1325 replace: ExprId,
1326) -> fmt::Result {
1327 write!(indent, "UpdateField:")?;
1328 indent = set_indentation(indent, 1);
1329 write!(indent, "\n{record}")?;
1330 write!(indent, "\n{field}")?;
1331 write!(indent, "\n{replace}")?;
1332 Ok(())
1333}
1334
1335fn display_var(mut f: Indented<Formatter>, res: Res, args: &[GenericArg]) -> fmt::Result {
1336 if args.is_empty() {
1337 write!(f, "Var: {res}")
1338 } else {
1339 write!(f, "Var:")?;
1340 f = set_indentation(f, 1);
1341 write!(f, "\nres: {res}")?;
1342 write!(f, "\ngenerics:")?;
1343 f = set_indentation(f, 2);
1344 for arg in args {
1345 write!(f, "\n{arg}")?;
1346 }
1347 Ok(())
1348 }
1349}
1350
1351fn display_while(mut indent: Indented<Formatter>, cond: ExprId, block: BlockId) -> fmt::Result {
1352 write!(indent, "While:")?;
1353 indent = set_indentation(indent, 1);
1354 write!(indent, "\n{cond}")?;
1355 write!(indent, "\n{block}")?;
1356 Ok(())
1357}
1358
1359/// A string component.
1360#[derive(Clone, Debug, PartialEq)]
1361pub enum StringComponent {
1362 /// An expression.
1363 Expr(ExprId),
1364 /// A string literal.
1365 Lit(Rc<str>),
1366}
1367
1368/// A pattern.
1369#[derive(Clone, Debug, Eq, PartialEq)]
1370pub struct Pat {
1371 /// The node ID.
1372 pub id: PatId,
1373 /// The span.
1374 pub span: Span,
1375 /// The pattern type.
1376 pub ty: Ty,
1377 /// The pattern kind.
1378 pub kind: PatKind,
1379}
1380
1381impl Display for Pat {
1382 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1383 write!(
1384 f,
1385 "Pat {} {} [Type {}]: {}",
1386 self.id, self.span, self.ty, self.kind
1387 )
1388 }
1389}
1390
1391/// A pattern kind.
1392#[derive(Clone, Debug, Eq, PartialEq)]
1393pub enum PatKind {
1394 /// A binding.
1395 Bind(Ident),
1396 /// A discarded binding, `_`.
1397 Discard,
1398 /// A tuple: `(a, b, c)`.
1399 Tuple(Vec<PatId>),
1400}
1401
1402impl Display for PatKind {
1403 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1404 let mut indent = set_indentation(indented(f), 0);
1405 match self {
1406 PatKind::Bind(id) => {
1407 write!(indent, "Bind: {id}")?;
1408 }
1409 PatKind::Discard => write!(indent, "Discard")?,
1410 PatKind::Tuple(ps) => {
1411 if ps.is_empty() {
1412 write!(indent, "Unit")?;
1413 } else {
1414 write!(indent, "Tuple:")?;
1415 indent = set_indentation(indent, 1);
1416 for p in ps {
1417 write!(indent, "\n{p}")?;
1418 }
1419 }
1420 }
1421 }
1422 Ok(())
1423 }
1424}
1425
1426/// An identifier.
1427#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1428pub struct Ident {
1429 /// The node ID.
1430 pub id: LocalVarId,
1431 /// The span.
1432 pub span: Span,
1433 /// The identifier name.
1434 pub name: Rc<str>,
1435}
1436
1437impl Display for Ident {
1438 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1439 write!(f, "Ident {} {} \"{}\"", self.id, self.span, self.name)
1440 }
1441}
1442
1443/// An attribute.
1444#[derive(Clone, Debug, PartialEq)]
1445pub enum Attr {
1446 /// Indicates that a callable is an entry point to a program.
1447 EntryPoint,
1448}
1449
1450/// A field.
1451#[derive(Clone, Debug, Eq, PartialEq)]
1452pub enum Field {
1453 /// A field path.
1454 Path(FieldPath),
1455 /// A primitive field for a built-in type.
1456 Prim(PrimField),
1457 /// An invalid field.
1458 Err,
1459}
1460
1461impl Display for Field {
1462 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1463 match self {
1464 Field::Path(path) => write!(f, "Path({:?})", path.indices),
1465 Field::Prim(prim) => write!(f, "Prim({prim:?}"),
1466 Field::Err => f.write_str("Err"),
1467 }
1468 }
1469}
1470
1471/// A path to a field in a tuple or user-defined type.
1472#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
1473pub struct FieldPath {
1474 /// The tuple item indices to follow in order from top to bottom.
1475 pub indices: Vec<usize>,
1476}
1477
1478/// A primitive field for a built-in type.
1479#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1480pub enum PrimField {
1481 /// The start of a range.
1482 Start,
1483 /// The step of a range.
1484 Step,
1485 /// The end of a range.
1486 End,
1487}
1488
1489impl FromStr for PrimField {
1490 type Err = ();
1491
1492 fn from_str(s: &str) -> result::Result<Self, <Self as FromStr>::Err> {
1493 match s {
1494 "Start" => Ok(Self::Start),
1495 "Step" => Ok(Self::Step),
1496 "End" => Ok(Self::End),
1497 _ => Err(()),
1498 }
1499 }
1500}
1501
1502/// The visibility of a declaration.
1503#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1504pub enum Visibility {
1505 /// Visible everywhere.
1506 Public,
1507 /// Visible within a package.
1508 Internal,
1509}
1510
1511/// A callable kind.
1512#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1513pub enum CallableKind {
1514 /// A function.
1515 Function,
1516 /// An operation.
1517 Operation,
1518}
1519
1520impl Display for CallableKind {
1521 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1522 match self {
1523 CallableKind::Function => f.write_str("function"),
1524 CallableKind::Operation => f.write_str("operation"),
1525 }
1526 }
1527}
1528
1529/// The mutability of a binding.
1530#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1531pub enum Mutability {
1532 /// An immutable binding.
1533 Immutable,
1534 /// A mutable binding.
1535 Mutable,
1536}
1537
1538/// The source of an allocated qubit.
1539#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1540pub enum QubitSource {
1541 /// A qubit initialized to the zero state.
1542 Fresh,
1543 /// A qubit borrowed from another part of the program that may be in any state, and is expected
1544 /// to be returned to that state before being released.
1545 Dirty,
1546}
1547
1548/// A literal.
1549#[derive(Clone, Debug, PartialEq)]
1550pub enum Lit {
1551 /// A big integer literal.
1552 BigInt(BigInt),
1553 /// A boolean literal.
1554 Bool(bool),
1555 /// A floating-point literal.
1556 Double(f64),
1557 /// An integer literal.
1558 Int(i64),
1559 /// A Pauli operator literal.
1560 Pauli(Pauli),
1561 /// A measurement result literal.
1562 Result(Result),
1563}
1564
1565impl Display for Lit {
1566 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1567 match self {
1568 Lit::BigInt(val) => write!(f, "BigInt({val})")?,
1569 Lit::Bool(val) => write!(f, "Bool({val})")?,
1570 Lit::Double(val) => write!(f, "Double({val})")?,
1571 Lit::Int(val) => write!(f, "Int({val})")?,
1572 Lit::Pauli(val) => write!(f, "Pauli({val:?})")?,
1573 Lit::Result(val) => write!(f, "Result({val:?})")?,
1574 }
1575 Ok(())
1576 }
1577}
1578
1579/// A measurement result.
1580#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1581pub enum Result {
1582 /// The zero eigenvalue.
1583 Zero,
1584 /// The one eigenvalue.
1585 One,
1586}
1587
1588/// A Pauli operator.
1589#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1590pub enum Pauli {
1591 /// The Pauli I operator.
1592 I,
1593 /// The Pauli X operator.
1594 X,
1595 /// The Pauli Y operator.
1596 Y,
1597 /// The Pauli Z operator.
1598 Z,
1599}
1600
1601/// A functor that may be applied to an operation.
1602#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1603pub enum Functor {
1604 /// The adjoint functor.
1605 Adj,
1606 /// The controlled functor.
1607 Ctl,
1608}
1609
1610impl Display for Functor {
1611 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1612 match self {
1613 Functor::Adj => f.write_str("Adj"),
1614 Functor::Ctl => f.write_str("Ctl"),
1615 }
1616 }
1617}
1618
1619/// A unary operator.
1620#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1621pub enum UnOp {
1622 /// A functor application.
1623 Functor(Functor),
1624 /// Negation: `-`.
1625 Neg,
1626 /// Bitwise NOT: `~~~`.
1627 NotB,
1628 /// Logical NOT: `not`.
1629 NotL,
1630 /// A leading `+`.
1631 Pos,
1632 /// Unwrap a user-defined type: `!`.
1633 Unwrap,
1634}
1635
1636impl Display for UnOp {
1637 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1638 match self {
1639 UnOp::Functor(func) => write!(f, "Functor {func:?}")?,
1640 _ => fmt::Debug::fmt(self, f)?,
1641 }
1642 Ok(())
1643 }
1644}
1645
1646/// A binary operator.
1647#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1648pub enum BinOp {
1649 /// Addition: `+`.
1650 Add,
1651 /// Bitwise AND: `&&&`.
1652 AndB,
1653 /// Logical AND: `and`.
1654 AndL,
1655 /// Division: `/`.
1656 Div,
1657 /// Equality: `==`.
1658 Eq,
1659 /// Exponentiation: `^`.
1660 Exp,
1661 /// Greater than: `>`.
1662 Gt,
1663 /// Greater than or equal: `>=`.
1664 Gte,
1665 /// Less than: `<`.
1666 Lt,
1667 /// Less than or equal: `<=`.
1668 Lte,
1669 /// Modulus: `%`.
1670 Mod,
1671 /// Multiplication: `*`.
1672 Mul,
1673 /// Inequality: `!=`.
1674 Neq,
1675 /// Bitwise OR: `|||`.
1676 OrB,
1677 /// Logical OR: `or`.
1678 OrL,
1679 /// Shift left: `<<<`.
1680 Shl,
1681 /// Shift right: `>>>`.
1682 Shr,
1683 /// Subtraction: `-`.
1684 Sub,
1685 /// Bitwise XOR: `^^^`.
1686 XorB,
1687}
1688