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#[derive(Debug, Clone, Default)]
42pub struct Book {
43 pub defs: Definitions,
45
46 pub hvm_defs: HvmDefinitions,
48
49 pub adts: Adts,
51
52 pub ctrs: Constructors,
54
55 pub entrypoint: Option<Name>,
57
58 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#[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 Builtin,
88 Generated,
90 User,
92 Imported,
94 Unknown,
96}
97
98#[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#[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 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 Oper {
187 opr: Op,
188 fst: Box<Term>,
189 snd: Box<Term>,
190 },
191 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 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 POW,
265 LE,
267 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 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#[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
325impl 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 let mut i = self.children_mut().filter(|x| x.children().next().is_some());
454
455 let Some(b) = i.next() else { break };
457
458 if { i }.next().is_none() {
461 *self = std::mem::take(b);
462 continue;
463 }
464
465 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 pub fn lam(pat: Pattern, bod: Term) -> Self {
494 Self::tagged_lam(Tag::Static, pat, bod)
495 }
496
497 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 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 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 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 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 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 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 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 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 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 pub fn subst_unscoped(&mut self, from: &Name, to: &Term) {
859 maybe_grow(|| {
860 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 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 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 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 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 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 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 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}