bend/fun/
mod.rs

1use crate::{
2  diagnostics::{Diagnostics, DiagnosticsConfig, TextSpan},
3  imports::Import,
4  maybe_grow, multi_iterator, ENTRY_POINT,
5};
6use indexmap::{IndexMap, IndexSet};
7use interner::global::{GlobalPool, GlobalString};
8use itertools::Itertools;
9use std::{
10  borrow::Cow,
11  hash::Hash,
12  ops::{Deref, Range},
13};
14
15pub mod builtins;
16pub mod check;
17pub mod display;
18pub mod load_book;
19pub mod net_to_term;
20pub mod parser;
21pub mod term_to_net;
22pub mod transform;
23
24pub use net_to_term::{net_to_term, ReadbackError};
25pub use term_to_net::{book_to_hvm, term_to_hvm};
26
27pub static STRINGS: GlobalPool<String> = GlobalPool::new();
28#[derive(Debug)]
29pub struct Ctx<'book> {
30  pub book: &'book mut Book,
31  pub info: Diagnostics,
32}
33
34impl Ctx<'_> {
35  pub fn new(book: &mut Book, diagnostics_cfg: DiagnosticsConfig) -> Ctx {
36    Ctx { book, info: Diagnostics::new(diagnostics_cfg) }
37  }
38}
39
40/// The representation of a program.
41#[derive(Debug, Clone, Default)]
42pub struct Book {
43  /// Function definitions.
44  pub defs: Definitions,
45
46  /// HVM native function definitions.
47  pub hvm_defs: HvmDefinitions,
48
49  /// Algebraic datatype definitions.
50  pub adts: Adts,
51
52  /// Map of constructor name to type name.
53  pub ctrs: Constructors,
54
55  /// A custom or default "main" entrypoint.
56  pub entrypoint: Option<Name>,
57
58  /// Imports declared in the program.
59  pub imports: Vec<Import>,
60}
61
62pub type Definitions = IndexMap<Name, Definition>;
63pub type HvmDefinitions = IndexMap<Name, HvmDefinition>;
64pub type Adts = IndexMap<Name, Adt>;
65pub type Constructors = IndexMap<Name, Name>;
66
67/// A pattern matching function definition.
68#[derive(Debug, Clone, PartialEq, Eq, Hash)]
69pub struct Definition {
70  pub name: Name,
71  pub typ: Type,
72  pub check: bool,
73  pub rules: Vec<Rule>,
74  pub source: Source,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78pub struct Source {
79  pub file: Option<String>,
80  pub span: Option<TextSpan>,
81  pub kind: SourceKind,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, Hash)]
85pub enum SourceKind {
86  /// Built into the language.
87  Builtin,
88  /// Was generated by the compiler.
89  Generated,
90  /// Source code from a local book.
91  User,
92  /// Source code from an imported book.
93  Imported,
94  /// Unknown by the compiler at this stage.
95  Unknown,
96}
97
98/// An HVM native definition.
99#[derive(Debug, Clone)]
100pub struct HvmDefinition {
101  pub name: Name,
102  pub typ: Type,
103  pub body: hvm::ast::Net,
104  pub source: Source,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Hash)]
108pub enum Type {
109  Any,
110  Hole,
111  Var(Name),
112  Ctr(Name, Vec<Type>),
113  Arr(Box<Type>, Box<Type>),
114  Tup(Vec<Type>),
115  U24,
116  F24,
117  I24,
118  None,
119  Number(Box<Type>),
120  Integer(Box<Type>),
121}
122
123/// A pattern matching rule of a definition.
124#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
125pub struct Rule {
126  pub pats: Vec<Pattern>,
127  pub body: Term,
128}
129
130#[derive(Debug, Default, PartialEq, Eq, Hash)]
131pub enum Term {
132  Lam {
133    tag: Tag,
134    pat: Box<Pattern>,
135    bod: Box<Term>,
136  },
137  Var {
138    nam: Name,
139  },
140  Link {
141    nam: Name,
142  },
143  Let {
144    pat: Box<Pattern>,
145    val: Box<Term>,
146    nxt: Box<Term>,
147  },
148  With {
149    typ: Name,
150    bod: Box<Term>,
151  },
152  Ask {
153    pat: Box<Pattern>,
154    val: Box<Term>,
155    nxt: Box<Term>,
156  },
157  Use {
158    nam: Option<Name>,
159    val: Box<Term>,
160    nxt: Box<Term>,
161  },
162  App {
163    tag: Tag,
164    fun: Box<Term>,
165    arg: Box<Term>,
166  },
167  /// Either a tuple or a superposition
168  Fan {
169    fan: FanKind,
170    tag: Tag,
171    els: Vec<Term>,
172  },
173  Num {
174    val: Num,
175  },
176  Nat {
177    val: u32,
178  },
179  Str {
180    val: GlobalString,
181  },
182  List {
183    els: Vec<Term>,
184  },
185  /// A numeric operation between built-in numbers.
186  Oper {
187    opr: Op,
188    fst: Box<Term>,
189    snd: Box<Term>,
190  },
191  /// Pattern matching on an ADT.
192  Mat {
193    bnd: Option<Name>,
194    arg: Box<Term>,
195    with_bnd: Vec<Option<Name>>,
196    with_arg: Vec<Term>,
197    arms: Vec<MatchRule>,
198  },
199  /// Native pattern matching on numbers
200  Swt {
201    bnd: Option<Name>,
202    arg: Box<Term>,
203    with_bnd: Vec<Option<Name>>,
204    with_arg: Vec<Term>,
205    pred: Option<Name>,
206    arms: Vec<Term>,
207  },
208  Fold {
209    bnd: Option<Name>,
210    arg: Box<Term>,
211    with_bnd: Vec<Option<Name>>,
212    with_arg: Vec<Term>,
213    arms: Vec<MatchRule>,
214  },
215  Bend {
216    bnd: Vec<Option<Name>>,
217    arg: Vec<Term>,
218    cond: Box<Term>,
219    step: Box<Term>,
220    base: Box<Term>,
221  },
222  Open {
223    typ: Name,
224    var: Name,
225    bod: Box<Term>,
226  },
227  Ref {
228    nam: Name,
229  },
230  Def {
231    def: Definition,
232    nxt: Box<Term>,
233  },
234  Era,
235  #[default]
236  Err,
237}
238
239pub type MatchRule = (Option<Name>, Vec<Option<Name>>, Term);
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242pub enum FanKind {
243  Tup,
244  Dup,
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
248pub enum Op {
249  ADD,
250  SUB,
251  MUL,
252  DIV,
253  REM,
254  EQ,
255  NEQ,
256  LT,
257  GT,
258  AND,
259  OR,
260  XOR,
261  SHL,
262  SHR,
263  // a^b
264  POW,
265  /// Less than or equal
266  LE,
267  /// Greater than or equal
268  GE,
269}
270
271#[derive(Debug, Clone, Copy)]
272pub enum Num {
273  U24(u32),
274  I24(i32),
275  F24(f32),
276}
277
278#[derive(Debug, Clone, PartialEq, Eq, Hash)]
279pub enum Pattern {
280  Var(Option<Name>),
281  Chn(Name),
282  Ctr(Name, Vec<Pattern>),
283  Num(u32),
284  /// Either a tuple or a duplication
285  Fan(FanKind, Tag, Vec<Pattern>),
286  Lst(Vec<Pattern>),
287  Str(GlobalString),
288}
289
290#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
291pub enum Tag {
292  Named(Name),
293  Numeric(u16),
294  Auto,
295  #[default]
296  Static,
297}
298
299/// A user defined datatype
300#[derive(Debug, Clone)]
301pub struct Adt {
302  pub name: Name,
303  pub vars: Vec<Name>,
304  pub ctrs: IndexMap<Name, AdtCtr>,
305  pub source: Source,
306}
307
308#[derive(Debug, Clone)]
309pub struct AdtCtr {
310  pub name: Name,
311  pub typ: Type,
312  pub fields: Vec<CtrField>,
313}
314
315#[derive(Debug, Clone)]
316pub struct CtrField {
317  pub nam: Name,
318  pub rec: bool,
319  pub typ: Type,
320}
321
322#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
323pub struct Name(GlobalString);
324
325/* Implementations */
326
327impl PartialEq<str> for Name {
328  fn eq(&self, other: &str) -> bool {
329    &**self == other
330  }
331}
332
333impl PartialEq<&str> for Name {
334  fn eq(&self, other: &&str) -> bool {
335    self == *other
336  }
337}
338
339impl PartialEq<Option<Name>> for Name {
340  fn eq(&self, other: &Option<Name>) -> bool {
341    if let Some(other) = other.as_ref() {
342      self == other
343    } else {
344      false
345    }
346  }
347}
348
349impl PartialEq<Name> for Option<Name> {
350  fn eq(&self, other: &Name) -> bool {
351    other.eq(self)
352  }
353}
354
355impl PartialEq<Option<&Name>> for Name {
356  fn eq(&self, other: &Option<&Name>) -> bool {
357    if let Some(other) = other {
358      &self == other
359    } else {
360      false
361    }
362  }
363}
364
365impl PartialEq<Name> for Option<&Name> {
366  fn eq(&self, other: &Name) -> bool {
367    other.eq(self)
368  }
369}
370
371pub fn num_to_name(mut num: u64) -> String {
372  let mut name = String::new();
373  loop {
374    let c = (num % 26) as u8 + b'a';
375    name.push(c as char);
376    num /= 26;
377    if num == 0 {
378      break;
379    }
380  }
381  name
382}
383
384impl Tag {
385  pub fn adt_name(name: &Name) -> Self {
386    Self::Named(name.clone())
387  }
388}
389
390impl Clone for Term {
391  fn clone(&self) -> Self {
392    maybe_grow(|| match self {
393      Self::Lam { tag, pat, bod } => Self::Lam { tag: tag.clone(), pat: pat.clone(), bod: bod.clone() },
394      Self::Var { nam } => Self::Var { nam: nam.clone() },
395      Self::Link { nam } => Self::Link { nam: nam.clone() },
396      Self::Let { pat, val, nxt } => Self::Let { pat: pat.clone(), val: val.clone(), nxt: nxt.clone() },
397      Self::With { typ, bod } => Self::With { typ: typ.clone(), bod: bod.clone() },
398      Self::Ask { pat, val, nxt } => Self::Ask { pat: pat.clone(), val: val.clone(), nxt: nxt.clone() },
399      Self::Use { nam, val, nxt } => Self::Use { nam: nam.clone(), val: val.clone(), nxt: nxt.clone() },
400      Self::App { tag, fun, arg } => Self::App { tag: tag.clone(), fun: fun.clone(), arg: arg.clone() },
401      Self::Fan { fan, tag, els } => Self::Fan { fan: *fan, tag: tag.clone(), els: els.clone() },
402      Self::Num { val } => Self::Num { val: *val },
403      Self::Nat { val } => Self::Nat { val: *val },
404      Self::Str { val } => Self::Str { val: val.clone() },
405      Self::List { els } => Self::List { els: els.clone() },
406      Self::Oper { opr, fst, snd } => Self::Oper { opr: *opr, fst: fst.clone(), snd: snd.clone() },
407      Self::Mat { arg, bnd, with_bnd, with_arg, arms } => Self::Mat {
408        arg: arg.clone(),
409        bnd: bnd.clone(),
410        with_bnd: with_bnd.clone(),
411        with_arg: with_arg.clone(),
412        arms: arms.clone(),
413      },
414      Self::Swt { arg, bnd, with_bnd, with_arg, pred, arms } => Self::Swt {
415        arg: arg.clone(),
416        bnd: bnd.clone(),
417        with_bnd: with_bnd.clone(),
418        with_arg: with_arg.clone(),
419        pred: pred.clone(),
420        arms: arms.clone(),
421      },
422      Self::Fold { bnd, arg, with_bnd, with_arg, arms } => Self::Fold {
423        bnd: bnd.clone(),
424        arg: arg.clone(),
425        with_bnd: with_bnd.clone(),
426        with_arg: with_arg.clone(),
427        arms: arms.clone(),
428      },
429      Self::Bend { bnd: bind, arg: init, cond, step, base } => Self::Bend {
430        bnd: bind.clone(),
431        arg: init.clone(),
432        cond: cond.clone(),
433        step: step.clone(),
434        base: base.clone(),
435      },
436      Self::Open { typ, var, bod: nxt } => {
437        Self::Open { typ: typ.clone(), var: var.clone(), bod: nxt.clone() }
438      }
439      Self::Ref { nam } => Self::Ref { nam: nam.clone() },
440      Self::Def { def, nxt } => Self::Def { def: def.clone(), nxt: nxt.clone() },
441      Self::Era => Self::Era,
442      Self::Err => Self::Err,
443    })
444  }
445}
446
447impl Drop for Term {
448  fn drop(&mut self) {
449    loop {
450      // Each iteration moves a child with nested nodes to the last child.
451      // When no nested on the left, we can just drop it and they'll be handled
452      // by the special cases;
453      let mut i = self.children_mut().filter(|x| x.children().next().is_some());
454
455      // No nested children, just drop everything
456      let Some(b) = i.next() else { break };
457
458      // Only one child with nested nodes, move it up to be the new root.
459      // Non-nested (height=0) children are dropped recursively.
460      if { i }.next().is_none() {
461        *self = std::mem::take(b);
462        continue;
463      }
464
465      // Rotate the tree right:
466      // ```text
467      //     a            b
468      //    / \          / \
469      //   b   e   ->   c   a
470      //  / \              / \
471      // c   d            d   e
472      // ```
473      let tmp = Term::Err;
474      let d = std::mem::replace(b.children_mut().next_back().unwrap(), tmp);
475      let b = std::mem::replace(b, d);
476      let a = std::mem::replace(self, b);
477      let tmp = std::mem::replace(self.children_mut().next_back().unwrap(), a);
478      std::mem::forget(tmp);
479    }
480  }
481}
482
483impl From<Option<Name>> for Pattern {
484  fn from(value: Option<Name>) -> Self {
485    Pattern::Var(value)
486  }
487}
488
489impl Term {
490  /* Common construction patterns */
491
492  /// Lambda with a static tag
493  pub fn lam(pat: Pattern, bod: Term) -> Self {
494    Self::tagged_lam(Tag::Static, pat, bod)
495  }
496
497  /// Lambda with any tag
498  pub fn tagged_lam(tag: Tag, pat: Pattern, bod: Term) -> Self {
499    Term::Lam { tag, pat: Box::new(pat), bod: Box::new(bod) }
500  }
501
502  /// Wraps a term in lambdas, so that the outermost lambda is the first given element.
503  ///
504  /// The lambda equivalent of [`Term::call`].
505  pub fn rfold_lams(term: Term, pats: impl DoubleEndedIterator<Item = Option<Name>>) -> Self {
506    pats.into_iter().rfold(term, |bod, nam| Self::lam(Pattern::Var(nam), bod))
507  }
508
509  pub fn var_or_era(nam: Option<Name>) -> Self {
510    if let Some(nam) = nam {
511      Term::Var { nam }
512    } else {
513      Term::Era
514    }
515  }
516
517  pub fn app(fun: Term, arg: Term) -> Self {
518    Self::tagged_app(Tag::Static, fun, arg)
519  }
520
521  pub fn tagged_app(tag: Tag, fun: Term, arg: Term) -> Self {
522    Term::App { tag, fun: Box::new(fun), arg: Box::new(arg) }
523  }
524
525  /// Make a call term by folding args around a called function term with applications.
526  pub fn call(called: Term, args: impl IntoIterator<Item = Term>) -> Self {
527    args.into_iter().fold(called, Term::app)
528  }
529
530  pub fn tagged_call(tag: Tag, called: Term, args: impl IntoIterator<Item = Term>) -> Self {
531    args.into_iter().fold(called, |acc, arg| Term::tagged_app(tag.clone(), acc, arg))
532  }
533
534  /// Apply a variable to a term by the var name.
535  pub fn arg_call(fun: Term, arg: Name) -> Self {
536    Term::app(fun, Term::Var { nam: arg })
537  }
538
539  pub fn r#ref(name: &str) -> Self {
540    Term::Ref { nam: Name::new(name) }
541  }
542
543  pub fn str(str: &str) -> Self {
544    Term::Str { val: STRINGS.get(str) }
545  }
546
547  pub fn sub_num(arg: Term, val: Num) -> Term {
548    if val.is_zero() {
549      arg
550    } else {
551      Term::Oper { opr: Op::SUB, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
552    }
553  }
554
555  pub fn add_num(arg: Term, val: Num) -> Term {
556    if val.is_zero() {
557      arg
558    } else {
559      Term::Oper { opr: Op::ADD, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
560    }
561  }
562
563  pub fn pattern(&self) -> Option<&Pattern> {
564    match self {
565      Term::Lam { pat, .. } | Term::Let { pat, .. } => Some(pat),
566      _ => None,
567    }
568  }
569
570  pub fn pattern_mut(&mut self) -> Option<&mut Pattern> {
571    match self {
572      Term::Lam { pat, .. } | Term::Let { pat, .. } => Some(pat),
573      _ => None,
574    }
575  }
576
577  /* Iterators */
578  pub fn children(&self) -> impl DoubleEndedIterator<Item = &Term> + Clone {
579    multi_iterator!(ChildrenIter { Zero, One, Two, Vec, Mat, Swt, Bend, Fold });
580    match self {
581      Term::Mat { arg, bnd: _, with_bnd: _, with_arg, arms } => {
582        ChildrenIter::Mat([arg.as_ref()].into_iter().chain(with_arg.iter()).chain(arms.iter().map(|r| &r.2)))
583      }
584      Term::Swt { arg, bnd: _, with_bnd: _, with_arg, pred: _, arms } => {
585        ChildrenIter::Swt([arg.as_ref()].into_iter().chain(with_arg.iter()).chain(arms))
586      }
587      Term::Bend { bnd: _, arg: init, cond, step, base } => {
588        ChildrenIter::Bend(init.iter().chain([cond.as_ref(), step.as_ref(), base.as_ref()]))
589      }
590      Term::Fold { bnd: _, arg, with_bnd: _, with_arg, arms } => {
591        ChildrenIter::Fold([arg.as_ref()].into_iter().chain(with_arg.iter()).chain(arms.iter().map(|r| &r.2)))
592      }
593      Term::Fan { els, .. } | Term::List { els } => ChildrenIter::Vec(els),
594      Term::Let { val: fst, nxt: snd, .. }
595      | Term::Ask { val: fst, nxt: snd, .. }
596      | Term::Use { val: fst, nxt: snd, .. }
597      | Term::App { fun: fst, arg: snd, .. }
598      | Term::Oper { fst, snd, .. } => ChildrenIter::Two([fst.as_ref(), snd.as_ref()]),
599      Term::Lam { bod, .. } | Term::With { bod, .. } | Term::Open { bod, .. } => {
600        ChildrenIter::One([bod.as_ref()])
601      }
602      Term::Var { .. }
603      | Term::Link { .. }
604      | Term::Num { .. }
605      | Term::Nat { .. }
606      | Term::Str { .. }
607      | Term::Ref { .. }
608      | Term::Def { .. }
609      | Term::Era
610      | Term::Err => ChildrenIter::Zero([]),
611    }
612  }
613
614  pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Term> {
615    multi_iterator!(ChildrenIter { Zero, One, Two, Vec, Mat, Swt, Bend, Fold });
616    match self {
617      Term::Mat { arg, bnd: _, with_bnd: _, with_arg, arms } => ChildrenIter::Mat(
618        [arg.as_mut()].into_iter().chain(with_arg.iter_mut()).chain(arms.iter_mut().map(|r| &mut r.2)),
619      ),
620      Term::Swt { arg, bnd: _, with_bnd: _, with_arg, pred: _, arms } => {
621        ChildrenIter::Swt([arg.as_mut()].into_iter().chain(with_arg.iter_mut()).chain(arms))
622      }
623      Term::Bend { bnd: _, arg: init, cond, step, base } => {
624        ChildrenIter::Bend(init.iter_mut().chain([cond.as_mut(), step.as_mut(), base.as_mut()]))
625      }
626      Term::Fold { bnd: _, arg, with_bnd: _, with_arg, arms } => ChildrenIter::Fold(
627        [arg.as_mut()].into_iter().chain(with_arg.iter_mut()).chain(arms.iter_mut().map(|r| &mut r.2)),
628      ),
629      Term::Fan { els, .. } | Term::List { els } => ChildrenIter::Vec(els),
630      Term::Let { val: fst, nxt: snd, .. }
631      | Term::Ask { val: fst, nxt: snd, .. }
632      | Term::Use { val: fst, nxt: snd, .. }
633      | Term::App { fun: fst, arg: snd, .. }
634      | Term::Oper { fst, snd, .. } => ChildrenIter::Two([fst.as_mut(), snd.as_mut()]),
635      Term::Lam { bod, .. } | Term::With { bod, .. } | Term::Open { bod, .. } => {
636        ChildrenIter::One([bod.as_mut()])
637      }
638      Term::Var { .. }
639      | Term::Link { .. }
640      | Term::Num { .. }
641      | Term::Nat { .. }
642      | Term::Str { .. }
643      | Term::Ref { .. }
644      | Term::Def { .. }
645      | Term::Era
646      | Term::Err => ChildrenIter::Zero([]),
647    }
648  }
649
650  /// An iterator over the subterms with an iterator over the binds
651  /// introduced by the current term for each subterm.
652  ///
653  /// Must only be called after fix_matches.
654  ///
655  /// Example: A lambda introduces 1 bind for it's only subterm,
656  /// while a let expression introduces 0 binds for the value and
657  /// many binds for the next term.
658  pub fn children_with_binds(
659    &self,
660  ) -> impl DoubleEndedIterator<Item = (&Term, impl DoubleEndedIterator<Item = &Option<Name>> + Clone)> + Clone
661  {
662    multi_iterator!(ChildrenIter { Zero, One, Two, Vec, Mat, Swt, Bend });
663    multi_iterator!(BindsIter { Zero, One, Mat, Pat, SwtNum, SwtSucc, Bend });
664    match self {
665      Term::Mat { arg, bnd, with_bnd, with_arg, arms }
666      | Term::Fold { bnd, arg, with_bnd, with_arg, arms } => {
667        let arg = [(arg.as_ref(), BindsIter::Zero([]))].into_iter();
668        let with_arg = with_arg.iter().map(|a| (a, BindsIter::Zero([])));
669        let arms = arms
670          .iter()
671          .map(move |r| (&r.2, BindsIter::Mat([bnd].into_iter().chain(r.1.iter()).chain(with_bnd.iter()))));
672        ChildrenIter::Mat(arg.chain(with_arg).chain(arms))
673      }
674      Term::Swt { arg, bnd, with_bnd, with_arg, pred, arms } => {
675        let (succ, nums) = arms.split_last().unwrap();
676        ChildrenIter::Swt(
677          [(arg.as_ref(), BindsIter::Zero([]))]
678            .into_iter()
679            .chain(with_arg.iter().map(|a| (a, BindsIter::Zero([]))))
680            .chain(nums.iter().map(move |x| (x, BindsIter::SwtNum([bnd].into_iter().chain(with_bnd.iter())))))
681            .chain([(succ, BindsIter::SwtSucc([bnd, pred].into_iter().chain(with_bnd.iter())))]),
682        )
683      }
684      Term::Bend { bnd: bind, arg: init, cond, step, base } => {
685        ChildrenIter::Bend(init.iter().map(|x| (x, BindsIter::Zero([]))).chain([
686          (cond.as_ref(), BindsIter::Bend(bind.iter())),
687          (step.as_ref(), BindsIter::Bend(bind.iter())),
688          (base.as_ref(), BindsIter::Bend(bind.iter())),
689        ]))
690      }
691
692      Term::Fan { els, .. } | Term::List { els } => {
693        ChildrenIter::Vec(els.iter().map(|el| (el, BindsIter::Zero([]))))
694      }
695      Term::Let { pat, val, nxt, .. } | Term::Ask { pat, val, nxt, .. } => {
696        ChildrenIter::Two([(val.as_ref(), BindsIter::Zero([])), (nxt.as_ref(), BindsIter::Pat(pat.binds()))])
697      }
698      Term::Use { nam, val, nxt, .. } => {
699        ChildrenIter::Two([(val.as_ref(), BindsIter::Zero([])), (nxt.as_ref(), BindsIter::One([nam]))])
700      }
701      Term::App { fun: fst, arg: snd, .. } | Term::Oper { fst, snd, .. } => {
702        ChildrenIter::Two([(fst.as_ref(), BindsIter::Zero([])), (snd.as_ref(), BindsIter::Zero([]))])
703      }
704      Term::Lam { pat, bod, .. } => ChildrenIter::One([(bod.as_ref(), BindsIter::Pat(pat.binds()))]),
705      Term::With { bod, .. } => ChildrenIter::One([(bod.as_ref(), BindsIter::Zero([]))]),
706      Term::Var { .. }
707      | Term::Link { .. }
708      | Term::Num { .. }
709      | Term::Nat { .. }
710      | Term::Str { .. }
711      | Term::Ref { .. }
712      | Term::Def { .. }
713      | Term::Era
714      | Term::Err => ChildrenIter::Zero([]),
715      Term::Open { .. } => unreachable!("Open should be removed in earlier pass"),
716    }
717  }
718
719  /// Must only be called after fix_matches.
720  pub fn children_mut_with_binds(
721    &mut self,
722  ) -> impl DoubleEndedIterator<Item = (&mut Term, impl DoubleEndedIterator<Item = &Option<Name>> + Clone)>
723  {
724    multi_iterator!(ChildrenIter { Zero, One, Two, Vec, Mat, Swt, Bend });
725    multi_iterator!(BindsIter { Zero, One, Mat, SwtNum, SwtSucc, Pat, Bend });
726    match self {
727      Term::Mat { arg, bnd, with_bnd, with_arg, arms }
728      | Term::Fold { bnd, arg, with_bnd, with_arg, arms } => {
729        let arg = [(arg.as_mut(), BindsIter::Zero([]))].into_iter();
730        let with_arg = with_arg.iter_mut().map(|a| (a, BindsIter::Zero([])));
731        let arms = arms
732          .iter_mut()
733          .map(|r| (&mut r.2, BindsIter::Mat([&*bnd].into_iter().chain(r.1.iter()).chain(with_bnd.iter()))));
734        ChildrenIter::Mat(arg.chain(with_arg).chain(arms))
735      }
736      Term::Swt { arg, bnd, with_bnd, with_arg, pred, arms } => {
737        let (succ, nums) = arms.split_last_mut().unwrap();
738        ChildrenIter::Swt(
739          [(arg.as_mut(), BindsIter::Zero([]))]
740            .into_iter()
741            .chain(with_arg.iter_mut().map(|a| (a, BindsIter::Zero([]))))
742            .chain(
743              nums.iter_mut().map(|x| (x, BindsIter::SwtNum([&*bnd].into_iter().chain(with_bnd.iter())))),
744            )
745            .chain([(succ, BindsIter::SwtSucc([&*bnd, &*pred].into_iter().chain(with_bnd.iter())))]),
746        )
747      }
748      Term::Bend { bnd, arg, cond, step, base } => {
749        ChildrenIter::Bend(arg.iter_mut().map(|x| (x, BindsIter::Zero([]))).chain([
750          (cond.as_mut(), BindsIter::Bend(bnd.iter())),
751          (step.as_mut(), BindsIter::Bend(bnd.iter())),
752          (base.as_mut(), BindsIter::Bend(bnd.iter())),
753        ]))
754      }
755
756      Term::Fan { els, .. } | Term::List { els } => {
757        ChildrenIter::Vec(els.iter_mut().map(|el| (el, BindsIter::Zero([]))))
758      }
759      Term::Let { pat, val, nxt, .. } | Term::Ask { pat, val, nxt, .. } => {
760        ChildrenIter::Two([(val.as_mut(), BindsIter::Zero([])), (nxt.as_mut(), BindsIter::Pat(pat.binds()))])
761      }
762      Term::Use { nam, val, nxt } => {
763        ChildrenIter::Two([(val.as_mut(), BindsIter::Zero([])), (nxt.as_mut(), BindsIter::One([&*nam]))])
764      }
765      Term::App { fun: fst, arg: snd, .. } | Term::Oper { fst, snd, .. } => {
766        ChildrenIter::Two([(fst.as_mut(), BindsIter::Zero([])), (snd.as_mut(), BindsIter::Zero([]))])
767      }
768      Term::Lam { pat, bod, .. } => ChildrenIter::One([(bod.as_mut(), BindsIter::Pat(pat.binds()))]),
769      Term::With { bod, .. } => ChildrenIter::One([(bod.as_mut(), BindsIter::Zero([]))]),
770      Term::Var { .. }
771      | Term::Link { .. }
772      | Term::Num { .. }
773      | Term::Nat { .. }
774      | Term::Str { .. }
775      | Term::Ref { .. }
776      | Term::Def { .. }
777      | Term::Era
778      | Term::Err => ChildrenIter::Zero([]),
779      Term::Open { .. } => unreachable!("Open should be removed in earlier pass"),
780    }
781  }
782  /* Common checks and transformations */
783
784  /// Substitute the occurrences of a variable in a term with the given term.
785  ///
786  /// Caution: can cause invalid shadowing of variables if used incorrectly.
787  /// Ex: Using subst to beta-reduce `(@a @b a b)` converting it into `@b b`.
788  ///
789  /// NOTE: Expects var bind information to be properly stored in match expressions,
790  /// so it must run AFTER `fix_match_terms`.
791  ///
792  /// NOTE: Since it doesn't (can't) handle `with` clauses in match terms,
793  /// it must be run only AFTER `with` linearization.
794  pub fn subst(&mut self, from: &Name, to: &Term) {
795    maybe_grow(|| {
796      for (child, binds) in self.children_mut_with_binds() {
797        if !binds.flat_map(|b| b.as_ref()).contains(from) {
798          child.subst(from, to);
799        }
800      }
801    });
802
803    if let Term::Var { nam } = self {
804      if nam == from {
805        *self = to.clone();
806      }
807    }
808  }
809
810  /// Substitute the occurrences of a constructor name with the given name.
811  pub fn subst_ctrs(&mut self, from: &Name, to: &Name) {
812    maybe_grow(|| {
813      for child in self.children_mut() {
814        child.subst_ctrs(from, to);
815      }
816    });
817
818    match self {
819      Term::Fold { arms, .. } | Term::Mat { arms, .. } => {
820        for (arm, _, _) in arms {
821          if let Some(nam) = arm {
822            if nam == from {
823              *nam = to.clone();
824            }
825          }
826        }
827      }
828      Term::Open { typ, .. } => {
829        if typ == from {
830          *typ = to.clone();
831        }
832      }
833      _ => (),
834    }
835  }
836
837  /// Substitutes the occurrences of a type constructor in the term with the given name.
838  pub fn subst_type_ctrs(&mut self, from: &Name, to: &Name) {
839    maybe_grow(|| {
840      match self {
841        Term::Def { def, nxt: _ } => {
842          def.typ.subst_ctr(from, to);
843        }
844        Term::With { typ, bod: _ } => {
845          if typ == from {
846            *typ = to.clone();
847          }
848        }
849        _ => (),
850      }
851      for child in self.children_mut() {
852        child.subst_type_ctrs(from, to);
853      }
854    });
855  }
856
857  /// Substitute the occurrence of an unscoped variable with the given term.
858  pub fn subst_unscoped(&mut self, from: &Name, to: &Term) {
859    maybe_grow(|| {
860      // We don't check the unscoped binds because there can be only one bind of an unscoped var.
861      // TODO: potentially there could be some situation where this causes an incorrect program to compile?
862      for child in self.children_mut() {
863        child.subst_unscoped(from, to);
864      }
865    });
866
867    if let Term::Link { nam } = self {
868      if nam == from {
869        *self = to.clone();
870      }
871    }
872  }
873
874  /// Collects all the free variables that a term has
875  /// and the number of times each var is used
876  pub fn free_vars(&self) -> IndexMap<Name, u64> {
877    fn go_term(term: &Term, free_vars: &mut IndexMap<Name, u64>) {
878      maybe_grow(|| {
879        if let Term::Var { nam } = term {
880          *free_vars.entry(nam.clone()).or_default() += 1;
881        }
882
883        for (child, binds) in term.children_with_binds() {
884          let mut new_scope = Default::default();
885          go_term(child, &mut new_scope);
886
887          for nam in binds.flatten() {
888            new_scope.shift_remove(nam);
889          }
890
891          free_vars.extend(new_scope);
892        }
893      })
894    }
895
896    let mut free_vars = Default::default();
897    go_term(self, &mut free_vars);
898    free_vars
899  }
900
901  /// Returns the set of declared and the set of used unscoped variables
902  pub fn unscoped_vars(&self) -> (IndexSet<Name>, IndexSet<Name>) {
903    fn go_pat(pat: &Pattern, decls: &mut IndexSet<Name>) {
904      maybe_grow(|| {
905        if let Pattern::Chn(name) = pat {
906          decls.insert(name.clone());
907        }
908
909        for child in pat.children() {
910          go_pat(child, decls);
911        }
912      })
913    }
914    fn go_term(term: &Term, decls: &mut IndexSet<Name>, uses: &mut IndexSet<Name>) {
915      maybe_grow(|| {
916        if let Term::Link { nam } = term {
917          uses.insert(nam.clone());
918        }
919
920        if let Some(pat) = term.pattern() {
921          go_pat(pat, decls)
922        }
923
924        for child in term.children() {
925          go_term(child, decls, uses);
926        }
927      })
928    }
929    let mut decls = Default::default();
930    let mut uses = Default::default();
931    go_term(self, &mut decls, &mut uses);
932    (decls, uses)
933  }
934
935  pub fn has_unscoped(&self) -> bool {
936    maybe_grow(|| {
937      let mut has_unscoped = match self {
938        Term::Let { pat, .. } if pat.has_unscoped() => true,
939        Term::Link { .. } => true,
940        _ => false,
941      };
942      for child in self.children() {
943        if has_unscoped {
944          return true;
945        }
946        has_unscoped |= child.has_unscoped()
947      }
948      has_unscoped
949    })
950  }
951}
952
953impl Num {
954  pub fn is_zero(&self) -> bool {
955    match self {
956      Num::U24(val) => *val == 0,
957      Num::I24(val) => *val == 0,
958      Num::F24(val) => *val == 0.0,
959    }
960  }
961
962  pub fn to_bits(&self) -> u32 {
963    match self {
964      Num::U24(val) => hvm::hvm::Numb::new_u24(*val).0,
965      Num::I24(val) => hvm::hvm::Numb::new_i24(*val).0,
966      Num::F24(val) => hvm::hvm::Numb::new_f24(*val).0,
967    }
968  }
969
970  pub fn from_bits(bits: u32) -> Self {
971    match hvm::hvm::Numb::get_typ(&hvm::hvm::Numb(bits)) {
972      hvm::hvm::TY_U24 => Num::U24(hvm::hvm::Numb::get_u24(&hvm::hvm::Numb(bits))),
973      hvm::hvm::TY_I24 => Num::I24(hvm::hvm::Numb::get_i24(&hvm::hvm::Numb(bits))),
974      hvm::hvm::TY_F24 => Num::F24(hvm::hvm::Numb::get_f24(&hvm::hvm::Numb(bits))),
975      _ => unreachable!("Invalid Num bits"),
976    }
977  }
978}
979
980impl Hash for Num {
981  fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
982    self.to_bits().hash(state);
983  }
984}
985
986impl PartialEq for Num {
987  fn eq(&self, other: &Self) -> bool {
988    self.to_bits() == other.to_bits()
989  }
990}
991
992impl Eq for Num {}
993
994impl Pattern {
995  pub fn binds(&self) -> impl DoubleEndedIterator<Item = &Option<Name>> + Clone {
996    self.iter().filter_map(|pat| match pat {
997      Pattern::Var(nam) => Some(nam),
998      _ => None,
999    })
1000  }
1001
1002  pub fn binds_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Option<Name>> {
1003    // Can't have a Pattern::iter_mut() since it has a tree-like structure.
1004    let mut binds = vec![];
1005    let mut to_visit = vec![self];
1006    while let Some(pat) = to_visit.pop() {
1007      match pat {
1008        Pattern::Var(nam) => binds.push(nam),
1009        _ => to_visit.extend(pat.children_mut().rev()),
1010      }
1011    }
1012    binds.into_iter()
1013  }
1014
1015  /// Returns an iterator over each immediate child sub-pattern of `self`.
1016  /// Considers Lists as its own pattern and not a sequence of Cons.
1017  pub fn children(&self) -> impl DoubleEndedIterator<Item = &Pattern> + Clone {
1018    multi_iterator!(ChildrenIter { Zero, Vec });
1019    match self {
1020      Pattern::Ctr(_, els) | Pattern::Fan(.., els) | Pattern::Lst(els) => ChildrenIter::Vec(els.iter()),
1021      Pattern::Var(_) | Pattern::Chn(_) | Pattern::Num(_) | Pattern::Str(_) => ChildrenIter::Zero([]),
1022    }
1023  }
1024
1025  pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Pattern> {
1026    multi_iterator!(ChildrenIter { Zero, Vec });
1027    match self {
1028      Pattern::Ctr(_, els) | Pattern::Fan(.., els) | Pattern::Lst(els) => ChildrenIter::Vec(els.iter_mut()),
1029      Pattern::Var(_) | Pattern::Chn(_) | Pattern::Num(_) | Pattern::Str(_) => ChildrenIter::Zero([]),
1030    }
1031  }
1032
1033  /// Returns an iterator over each subpattern in depth-first, left to right order.
1034  // TODO: Not lazy.
1035  pub fn iter(&self) -> impl DoubleEndedIterator<Item = &Pattern> + Clone {
1036    let mut to_visit = vec![self];
1037    let mut els = vec![];
1038    while let Some(pat) = to_visit.pop() {
1039      els.push(pat);
1040      to_visit.extend(pat.children().rev());
1041    }
1042    els.into_iter()
1043  }
1044
1045  pub fn is_wildcard(&self) -> bool {
1046    matches!(self, Pattern::Var(_) | Pattern::Chn(_))
1047  }
1048
1049  pub fn to_term(&self) -> Term {
1050    match self {
1051      Pattern::Var(nam) => Term::var_or_era(nam.clone()),
1052      Pattern::Chn(nam) => Term::Link { nam: nam.clone() },
1053      Pattern::Ctr(ctr, args) => {
1054        Term::call(Term::Ref { nam: ctr.clone() }, args.iter().map(|arg| arg.to_term()))
1055      }
1056      Pattern::Num(val) => Term::Num { val: Num::U24(*val) },
1057      Pattern::Fan(fan, tag, args) => {
1058        Term::Fan { fan: *fan, tag: tag.clone(), els: args.iter().map(|p| p.to_term()).collect() }
1059      }
1060      Pattern::Lst(_) | Pattern::Str(_) => todo!(),
1061    }
1062  }
1063
1064  pub fn has_unscoped(&self) -> bool {
1065    match self {
1066      Pattern::Chn(_) => true,
1067      Pattern::Var(_) | Pattern::Str(_) | Pattern::Num(_) => false,
1068      Pattern::Ctr(_, x) | Pattern::Fan(_, _, x) | Pattern::Lst(x) => x.iter().any(|x| x.has_unscoped()),
1069    }
1070  }
1071
1072  pub fn has_nested(&self) -> bool {
1073    for child in self.children() {
1074      if matches!(child, Pattern::Ctr(_, _) | Pattern::Fan(_, _, _) | Pattern::Lst(_)) {
1075        return true;
1076      }
1077    }
1078    false
1079  }
1080}
1081
1082impl Rule {
1083  pub fn arity(&self) -> usize {
1084    self.pats.len()
1085  }
1086}
1087
1088impl Definition {
1089  pub fn new_gen(name: Name, rules: Vec<Rule>, source: Source, check: bool) -> Self {
1090    let kind = if source.is_builtin() { SourceKind::Builtin } else { SourceKind::Generated };
1091    let source = Source { kind, ..source };
1092    Self { name, typ: Type::Hole, check, rules, source }
1093  }
1094
1095  pub fn is_builtin(&self) -> bool {
1096    self.source.is_builtin()
1097  }
1098
1099  pub fn arity(&self) -> usize {
1100    self.rules[0].arity()
1101  }
1102
1103  #[track_caller]
1104  pub fn assert_no_pattern_matching_rules(&self) {
1105    assert!(self.rules.len() == 1, "Definition rules should have been removed in earlier pass");
1106    assert!(self.rules[0].pats.is_empty(), "Definition args should have been removed in an earlier pass");
1107  }
1108
1109  #[track_caller]
1110  pub fn rule(&self) -> &Rule {
1111    self.assert_no_pattern_matching_rules();
1112    &self.rules[0]
1113  }
1114
1115  #[track_caller]
1116  pub fn rule_mut(&mut self) -> &mut Rule {
1117    self.assert_no_pattern_matching_rules();
1118    &mut self.rules[0]
1119  }
1120}
1121
1122impl Type {
1123  /// Substitutes the occurrences of a type constructor with the given name.
1124  /// Substitutes both `Var` and `Ctr` types since `Var` could be referring to
1125  /// an unresolved type constructor.
1126  pub fn subst_ctr(&mut self, from: &Name, to: &Name) {
1127    maybe_grow(|| {
1128      match self {
1129        Type::Var(nam) => {
1130          if nam == from {
1131            *nam = to.clone();
1132          }
1133        }
1134        Type::Ctr(nam, _) => {
1135          if nam == from {
1136            *nam = to.clone();
1137          }
1138        }
1139        _ => (),
1140      };
1141      for child in self.children_mut() {
1142        child.subst_ctr(from, to);
1143      }
1144    })
1145  }
1146
1147  pub fn children(&self) -> impl Iterator<Item = &Type> {
1148    multi_iterator!(ChildrenIter { Zero, One, Two, Vec });
1149    match self {
1150      Type::Any | Type::None | Type::Hole | Type::I24 | Type::F24 | Type::U24 | Type::Var(_) => {
1151        ChildrenIter::Zero([])
1152      }
1153      Type::Number(t) | Type::Integer(t) => ChildrenIter::One([t.as_ref()]),
1154      Type::Arr(lft, rgt) => ChildrenIter::Two([lft.as_ref(), rgt.as_ref()]),
1155      Type::Tup(els) | Type::Ctr(_, els) => ChildrenIter::Vec(els),
1156    }
1157  }
1158
1159  pub fn children_mut(&mut self) -> impl Iterator<Item = &mut Type> {
1160    multi_iterator!(ChildrenIter { Zero, One, Two, Vec });
1161    match self {
1162      Type::Any | Type::None | Type::Hole | Type::I24 | Type::F24 | Type::U24 | Type::Var(_) => {
1163        ChildrenIter::Zero([])
1164      }
1165      Type::Number(t) | Type::Integer(t) => ChildrenIter::One([t.as_mut()]),
1166      Type::Arr(lft, rgt) => ChildrenIter::Two([lft.as_mut(), rgt.as_mut()]),
1167      Type::Tup(els) | Type::Ctr(_, els) => ChildrenIter::Vec(els),
1168    }
1169  }
1170}
1171
1172impl Name {
1173  pub fn new<'a, V: Into<Cow<'a, str>>>(value: V) -> Name {
1174    Name(STRINGS.get(value))
1175  }
1176
1177  pub fn is_generated(&self) -> bool {
1178    // Generated def names use $ while var names use %
1179    self.contains("__") || self.contains('%')
1180  }
1181
1182  pub fn def_name_from_generated(&self) -> Name {
1183    if let Some(nam) = self.strip_prefix("__") {
1184      Name::new(nam)
1185    } else if let Some((nam, _)) = self.split_once("__") {
1186      Name::new(nam)
1187    } else {
1188      self.clone()
1189    }
1190  }
1191}
1192
1193impl Default for Name {
1194  fn default() -> Self {
1195    Self::new("")
1196  }
1197}
1198
1199impl From<u64> for Name {
1200  fn from(value: u64) -> Self {
1201    Name::new(num_to_name(value).as_str())
1202  }
1203}
1204
1205impl From<u32> for Name {
1206  fn from(value: u32) -> Self {
1207    Name::new(num_to_name(value as u64).as_str())
1208  }
1209}
1210
1211impl Deref for Name {
1212  type Target = str;
1213
1214  fn deref(&self) -> &Self::Target {
1215    &self.0
1216  }
1217}
1218
1219impl AsRef<str> for Name {
1220  fn as_ref(&self) -> &str {
1221    &self.0
1222  }
1223}
1224
1225impl Book {
1226  pub fn hvm_entrypoint(&self) -> &str {
1227    match self.entrypoint.as_ref().map(|e| e.as_ref()) {
1228      Some("main" | "Main") | None => ENTRY_POINT,
1229      Some(nam) => nam,
1230    }
1231  }
1232}
1233
1234impl Source {
1235  pub fn is_builtin(&self) -> bool {
1236    matches!(self.kind, SourceKind::Builtin)
1237  }
1238
1239  pub fn is_local(&self) -> bool {
1240    matches!(self.kind, SourceKind::User)
1241  }
1242
1243  pub fn from_file_span(file: &Name, txt: &str, span: Range<usize>, builtin: bool) -> Self {
1244    let span = Some(TextSpan::from_byte_span(txt, span));
1245    let kind = if builtin { SourceKind::Builtin } else { SourceKind::User };
1246    let file = Some(file.to_string());
1247    Source { file, span, kind }
1248  }
1249}
1250
1251impl Default for Source {
1252  fn default() -> Self {
1253    Self { file: None, span: None, kind: SourceKind::Unknown }
1254  }
1255}
1256
1257#[test]
1258fn num_to_from_bits() {
1259  let a = [
1260    Num::U24(0),
1261    Num::U24(0xFFFFFF),
1262    Num::U24(12345),
1263    Num::I24(0),
1264    Num::I24(0x7FFFFF),
1265    Num::I24(12345),
1266    Num::I24(-12345),
1267    Num::F24(0.0),
1268    Num::I24(-0),
1269    Num::F24(0xFFFFFF as f32),
1270    Num::F24(0.0),
1271    Num::F24(-0.0),
1272    Num::F24(0.00123),
1273    Num::F24(12345.023),
1274    Num::F24(-1235.3849),
1275    Num::F24(1.0),
1276    Num::F24(-1.0),
1277    Num::F24(12323658716.0),
1278    Num::F24(-12323658716.0),
1279    Num::F24(-0.00000000000000001),
1280    Num::F24(0.00000000000000001),
1281    Num::F24(5447856134985749851.3457896137815694178),
1282    Num::F24(-5447856134985749851.3457896137815694178),
1283  ];
1284  for b in a {
1285    assert_eq!(b, Num::from_bits(Num::to_bits(&b)));
1286  }
1287}