1use crate::{
2 fun::{
3 display::DisplayFn, Adt, AdtCtr, Adts, Constructors, CtrField, FanKind, HvmDefinition, HvmDefinitions,
4 MatchRule, Name, Num, Op, Pattern, Rule, Source, SourceKind, Tag, Term, Type, STRINGS,
5 },
6 imp::parser::ImpParser,
7 imports::{Import, ImportCtx, ImportType},
8 maybe_grow,
9};
10use highlight_error::highlight_error;
11use indexmap::IndexMap;
12use itertools::Itertools;
13use std::ops::Range;
14use TSPL::{ParseError, Parser};
15
16type FunDefinition = super::Definition;
17type ImpDefinition = crate::imp::Definition;
18
19#[derive(Debug, Clone, Default)]
21pub struct ParseBook {
22 pub fun_defs: IndexMap<Name, FunDefinition>,
24
25 pub imp_defs: IndexMap<Name, ImpDefinition>,
27
28 pub hvm_defs: HvmDefinitions,
30
31 pub adts: Adts,
33
34 pub ctrs: Constructors,
36
37 pub import_ctx: ImportCtx,
39
40 pub source: Name,
42}
43
44impl ParseBook {
45 pub fn contains_def(&self, name: &Name) -> bool {
46 self.fun_defs.contains_key(name) || self.imp_defs.contains_key(name) || self.hvm_defs.contains_key(name)
47 }
48
49 pub fn contains_builtin_def(&self, name: &Name) -> Option<bool> {
50 self
51 .fun_defs
52 .get(name)
53 .map(|d| d.is_builtin())
54 .or_else(|| self.imp_defs.get(name).map(|d| d.source.is_builtin()))
55 .or_else(|| self.hvm_defs.get(name).map(|d| d.source.is_builtin()))
56 }
57}
58
59pub type ParseResult<T> = std::result::Result<T, ParseError>;
60
61pub struct FunParser<'i> {
62 file: Name,
63 input: &'i str,
64 index: usize,
65 builtin: bool,
66}
67
68impl<'a> FunParser<'a> {
69 pub fn new(file: Name, input: &'a str, builtin: bool) -> Self {
70 Self { file, input, index: 0, builtin }
71 }
72
73 pub fn parse_book(&mut self, default_book: ParseBook) -> ParseResult<ParseBook> {
76 let mut book = default_book;
77 let mut indent = self.advance_newlines()?;
78 while !self.is_eof() {
79 if self.starts_with_keyword("object") {
81 let ini_idx = *self.index();
82 let mut prs = ImpParser {
83 file: self.file.clone(),
84 input: self.input,
85 index: *self.index(),
86 builtin: self.builtin,
87 };
88 let (adt, nxt_indent) = prs.parse_object(indent)?;
89 self.index = prs.index;
90 let end_idx = *self.index();
91 self.add_type_def(adt, &mut book, ini_idx..end_idx)?;
92 indent = nxt_indent;
93 continue;
94 }
95
96 if self.starts_with_keyword("def") {
98 let ini_idx = *self.index();
99 let mut prs =
100 ImpParser { file: self.file.clone(), input: self.input, index: ini_idx, builtin: self.builtin };
101 let (def, nxt_indent) = prs.parse_function_def(indent)?;
102 self.index = prs.index;
103 let end_idx = *self.index();
104 self.add_imp_def(def, &mut book, ini_idx..end_idx)?;
105 indent = nxt_indent;
106 continue;
107 }
108
109 if self.starts_with_keyword("type") {
111 fn starts_with_imp_type(p: &mut FunParser) -> ParseResult<()> {
112 p.parse_keyword("type")?;
113 p.skip_trivia_inline()?;
114 p.parse_top_level_name()?;
115 p.skip_trivia_inline()?;
116 if p.starts_with(":") || p.starts_with("(") {
117 Ok(())
118 } else {
119 Err(ParseError::new((0, 0), ""))
120 }
121 }
122
123 let ini_idx = *self.index();
124 let is_imp = starts_with_imp_type(self).is_ok();
125 self.index = ini_idx;
126 if is_imp {
127 let mut prs = ImpParser {
129 file: self.file.clone(),
130 input: self.input,
131 index: *self.index(),
132 builtin: self.builtin,
133 };
134 let (adt, nxt_indent) = prs.parse_type_def(indent)?;
135 self.index = prs.index;
136 let end_idx = *self.index();
137 self.add_type_def(adt, &mut book, ini_idx..end_idx)?;
138 indent = nxt_indent;
139 continue;
140 } else {
141 let adt = self.parse_type_def()?;
143 let end_idx = *self.index();
144 self.add_type_def(adt, &mut book, ini_idx..end_idx)?;
145 indent = self.advance_newlines()?;
146 continue;
147 }
148 }
149
150 if self.starts_with_keyword("hvm") {
152 let ini_idx = self.index;
153 let mut prs =
154 ImpParser { file: self.file.clone(), input: self.input, index: self.index, builtin: self.builtin };
155 let (def, nxt_indent) = prs.parse_hvm()?;
156 *self.index() = prs.index;
157 let end_idx = *self.index();
158 self.add_hvm(def, &mut book, ini_idx..end_idx)?;
159 indent = nxt_indent;
160 continue;
161 }
162
163 if self.starts_with_keyword("from") {
165 let import = self.parse_from_import()?;
166 book.import_ctx.add_import(import);
167 indent = self.advance_newlines()?;
168 continue;
169 }
170
171 if self.starts_with_keyword("import") {
172 let imports = self.parse_import()?;
173 for imp in imports {
174 book.import_ctx.add_import(imp);
175 }
176 indent = self.advance_newlines()?;
177 continue;
178 }
179
180 let ini_idx = *self.index();
182 let def = self.parse_fun_def()?;
183 let end_idx = *self.index();
184
185 self.add_fun_def(def, &mut book, ini_idx..end_idx)?;
186 indent = self.advance_newlines()?;
187 }
188
189 Ok(book)
190 }
191
192 fn parse_type_def(&mut self) -> ParseResult<Adt> {
193 let ini_idx = self.index;
195 self.parse_keyword("type")?;
196 self.skip_trivia();
197
198 let name;
199 let vars;
200 if self.try_consume("(") {
201 self.skip_trivia();
203 name = self.parse_restricted_name("Datatype")?;
204 vars = self
205 .labelled(|p| p.list_like(|p| p.parse_var_name(), "", ")", "", false, 0), "Type variable or ')'")?;
206 self.consume("=")?;
207 } else {
208 name = self.parse_restricted_name("Datatype")?;
210 vars = self
211 .labelled(|p| p.list_like(|p| p.parse_var_name(), "", "=", "", false, 0), "Type variable or '='")?;
212 }
213
214 let mut ctrs = vec![self.parse_type_ctr(&name, &vars)?];
215 while self.try_consume("|") {
216 ctrs.push(self.parse_type_ctr(&name, &vars)?);
217 }
218 let ctrs = ctrs.into_iter().map(|ctr| (ctr.name.clone(), ctr)).collect::<IndexMap<_, _>>();
219
220 let end_idx = *self.index();
221 let source = Source::from_file_span(&self.file, self.input, ini_idx..end_idx, self.builtin);
222 let adt = Adt { name, vars, ctrs, source };
223 Ok(adt)
224 }
225
226 fn parse_type_ctr(&mut self, type_name: &Name, type_vars: &[Name]) -> ParseResult<AdtCtr> {
227 self.skip_trivia();
230 let ini_idx = *self.index();
231 if self.try_consume("(") {
232 self.skip_trivia();
235 let ctr_name = self.parse_top_level_name()?;
236 let ctr_name = Name::new(format!("{type_name}/{ctr_name}"));
237
238 let fields = self.list_like(|p| p.parse_type_ctr_field(), "", ")", "", false, 0)?;
239 let field_types = fields.iter().map(|f| f.typ.clone()).collect::<Vec<_>>();
240 let end_idx = *self.index();
241 self.check_repeated_ctr_fields(&fields, &ctr_name, ini_idx..end_idx)?;
242
243 let typ = make_ctr_type(type_name.clone(), &field_types, type_vars);
244 let ctr = AdtCtr { name: ctr_name, typ, fields };
245 Ok(ctr)
246 } else {
247 let name = self.parse_restricted_name("Datatype constructor")?;
249 let name = Name::new(format!("{type_name}/{name}"));
250 let typ = make_ctr_type(type_name.clone(), &[], type_vars);
251 let ctr = AdtCtr { name, typ, fields: vec![] };
252 Ok(ctr)
253 }
254 }
255
256 fn parse_type_ctr_field(&mut self) -> ParseResult<CtrField> {
257 let rec = self.try_consume("~");
258
259 let nam;
260 let typ;
261 if self.try_consume("(") {
262 nam = self.parse_var_name()?;
263 if self.try_consume(":") {
264 typ = self.parse_type_term()?;
265 } else {
266 typ = Type::Any;
267 }
268 self.consume(")")?;
269 } else {
270 nam = self.parse_var_name()?;
271 typ = Type::Any;
272 }
273 Ok(CtrField { nam, typ, rec })
274 }
275
276 fn parse_fun_def(&mut self) -> ParseResult<FunDefinition> {
277 let ini_idx = *self.index();
278
279 if let Ok((name, args, check, typ)) = self.parse_def_sig() {
281 if self.try_consume("=") {
282 let body = self.parse_term()?;
284 let pats = args.into_iter().map(|nam| Pattern::Var(Some(nam))).collect();
285 let rules = vec![Rule { pats, body }];
286 let end_idx = *self.index();
287 let source = Source::from_file_span(&self.file, self.input, ini_idx..end_idx, self.builtin);
288 let def = FunDefinition { name, typ, check, rules, source };
289 Ok(def)
290 } else {
291 let mut rules = vec![];
293 let (_, rule) = self.parse_rule()?;
294 rules.push(rule);
295 while self.starts_with_rule(&name) {
296 let (_, rule) = self.parse_rule()?;
297 rules.push(rule);
298 }
299 let end_idx = *self.index();
300 let source = Source::from_file_span(&self.file, self.input, ini_idx..end_idx, self.builtin);
301 let def = FunDefinition { name, typ, check, rules, source };
302 Ok(def)
303 }
304 } else {
305 self.index = ini_idx;
307 let check = self.parse_checked(false);
309 let mut rules = vec![];
310 let (name, rule) = self.parse_rule()?;
311 rules.push(rule);
312 while self.starts_with_rule(&name) {
313 let (_, rule) = self.parse_rule()?;
314 rules.push(rule);
315 }
316 let end_idx = *self.index();
317 let source = Source::from_file_span(&self.file, self.input, ini_idx..end_idx, self.builtin);
318 let def = FunDefinition { name, typ: Type::Any, check, rules, source };
319 Ok(def)
320 }
321 }
322
323 fn parse_def_sig(&mut self) -> ParseResult<(Name, Vec<Name>, bool, Type)> {
326 let check = self.parse_checked(true);
330 let (name, args, typ) = if self.try_consume("(") {
331 let name = self.parse_top_level_name()?;
332 let args = self.list_like(|p| p.parse_def_sig_arg(), "", ")", "", false, 0)?;
333 self.consume(":")?;
334 let typ = self.parse_type_term()?;
335 (name, args, typ)
336 } else {
337 let name = self.parse_top_level_name()?;
338 let args = self.list_like(|p| p.parse_def_sig_arg(), "", ":", "", false, 0)?;
339 let typ = self.parse_type_term()?;
340 (name, args, typ)
341 };
342 let (args, arg_types): (Vec<_>, Vec<_>) = args.into_iter().unzip();
343 let typ = make_fn_type(arg_types, typ);
344 Ok((name, args, check, typ))
345 }
346
347 fn parse_def_sig_arg(&mut self) -> ParseResult<(Name, Type)> {
348 if self.try_consume("(") {
352 let name = self.parse_var_name()?;
353 let typ = if self.try_consume(":") { self.parse_type_term()? } else { Type::Any };
354 self.consume(")")?;
355 Ok((name, typ))
356 } else {
357 let name = self.parse_var_name()?;
358 Ok((name, Type::Any))
359 }
360 }
361
362 fn parse_checked(&mut self, default: bool) -> bool {
363 if self.try_parse_keyword("checked") {
364 true
365 } else if self.try_parse_keyword("unchecked") {
366 false
367 } else {
368 default
369 }
370 }
371
372 fn parse_from_import(&mut self) -> ParseResult<Import> {
373 self.parse_keyword("from")?;
377 self.skip_trivia_inline()?;
378
379 let path = self.parse_restricted_name("Path")?;
380 self.skip_trivia_inline()?;
381
382 self.consume("import")?;
383 self.skip_trivia_inline()?;
384
385 let relative = path.starts_with("./") | path.starts_with("../");
386
387 if self.try_consume("*") {
388 return Ok(Import::new(path, ImportType::Glob, relative));
389 }
390
391 if self.try_consume("(") {
392 let sub = self.list_like(|p| p.parse_name_maybe_alias("Name"), "", ")", ",", false, 1)?;
393 return Ok(Import::new(path, ImportType::List(sub), relative));
394 }
395
396 let (import, alias) = self.parse_name_maybe_alias("Import")?;
397 Ok(Import::new(path, ImportType::Single(import, alias), relative))
398 }
399
400 fn parse_import(&mut self) -> ParseResult<Vec<Import>> {
401 self.parse_keyword("import")?;
404 self.skip_trivia_inline()?;
405
406 let new_import = |import: Name, alias: Option<Name>, relative: bool| -> Import {
407 let (path, import) = match import.rsplit_once('/') {
408 Some((start, end)) => (Name::new(start), Name::new(end)),
409 None => (Name::default(), import),
410 };
411
412 Import::new(path, ImportType::Single(import, alias), relative)
413 };
414
415 if self.try_consume("(") {
416 let list = self.list_like(|p| p.parse_import_name("Name"), "", ")", ",", false, 1)?;
417 let imports = list.into_iter().map(|(a, b, c)| new_import(a, b, c)).collect_vec();
418 return Ok(imports);
419 }
420
421 let (import, alias, relative) = self.parse_import_name("Import")?;
422 let import = new_import(import, alias, relative);
423 Ok(vec![import])
424 }
425
426 fn parse_rule_lhs(&mut self) -> ParseResult<(Name, Vec<Pattern>)> {
427 if self.try_consume_exactly("(") {
428 self.skip_trivia();
429 let name = self.parse_restricted_name("Function")?;
430 let pats = self.list_like(|p| p.parse_pattern(false), "", ")", "", false, 0)?;
431 Ok((name, pats))
432 } else {
433 let name = self.labelled(|p| p.parse_top_level_name(), "top-level definition")?;
437 let mut pats = vec![];
438 self.skip_trivia();
439 while !self.starts_with("=") {
440 pats.push(self.parse_pattern(false)?);
441 self.skip_trivia();
442 }
443 Ok((name, pats))
444 }
445 }
446
447 fn parse_rule(&mut self) -> ParseResult<(Name, Rule)> {
448 self.skip_trivia();
449 let (name, pats) = self.parse_rule_lhs()?;
450
451 self.consume("=")?;
452
453 let body = self.parse_term()?;
454
455 let rule = Rule { pats, body };
456 Ok((name, rule))
457 }
458
459 fn starts_with_rule(&mut self, expected_name: &Name) -> bool {
460 let ini_idx = *self.index();
461 self.skip_trivia();
462 let res = self.parse_rule_lhs();
463 if !self.try_consume("=") {
464 self.index = ini_idx;
465 return false;
466 }
467 self.index = ini_idx;
468 if let Ok((name, _)) = res {
469 if &name == expected_name {
470 true
472 } else {
473 false
475 }
476 } else {
477 false
479 }
480 }
481
482 fn parse_pattern(&mut self, simple: bool) -> ParseResult<Pattern> {
483 maybe_grow(|| {
484 let (tag, unexpected_tag) = self.parse_tag()?;
485 self.skip_trivia();
486
487 if self.starts_with("(") {
489 self.advance_one();
490 let head_ini_idx = *self.index();
491 let head = self.parse_pattern(simple)?;
492 let head_end_idx = *self.index();
493
494 self.skip_trivia();
496 if self.starts_with(",") || simple {
497 self.consume(",")?;
498 let mut els = self.list_like(|p| p.parse_pattern(simple), "", ")", ",", true, 1)?;
499 els.insert(0, head);
500 return Ok(Pattern::Fan(FanKind::Tup, tag.unwrap_or(Tag::Static), els));
501 }
502
503 unexpected_tag(self)?;
505 let Pattern::Var(Some(name)) = head else {
506 return self.expected_spanned("constructor name", head_ini_idx..head_end_idx);
507 };
508 let els = self.list_like(|p| p.parse_pattern(simple), "", ")", "", false, 0)?;
509 return Ok(Pattern::Ctr(name, els));
510 }
511
512 if self.starts_with("{") {
514 let els = self.list_like(|p| p.parse_pattern(simple), "{", "}", ",", false, 0)?;
515 return Ok(Pattern::Fan(FanKind::Dup, tag.unwrap_or(Tag::Auto), els));
516 }
517
518 if self.starts_with("[") && !simple {
520 unexpected_tag(self)?;
521 let els = self.list_like(|p| p.parse_pattern(simple), "[", "]", ",", false, 0)?;
522 return Ok(Pattern::Lst(els));
523 }
524
525 if self.starts_with("\"") && !simple {
527 unexpected_tag(self)?;
528 let str = self.parse_quoted_string()?;
529 return Ok(Pattern::Str(STRINGS.get(str)));
530 }
531
532 if self.starts_with("'") {
534 unexpected_tag(self)?;
535 let char = self.parse_quoted_char()?;
536 return Ok(Pattern::Num(char as u32));
537 }
538
539 if self.peek_one().is_some_and(|c| c.is_ascii_digit()) {
541 unexpected_tag(self)?;
542 let num = self.parse_u32()?;
543 return Ok(Pattern::Num(num));
544 }
545
546 if self.starts_with("$") {
548 unexpected_tag(self)?;
549 self.advance_one();
550 self.skip_trivia();
551 let name = self.parse_var_name()?;
552 return Ok(Pattern::Chn(name));
553 }
554
555 if self.starts_with("*")
557 || self
558 .peek_one()
559 .is_some_and(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.' || c == '-' || c == '/')
560 {
561 unexpected_tag(self)?;
562 let nam = self.parse_name_or_era()?;
563 return Ok(Pattern::Var(nam));
564 }
565
566 let ini_idx = *self.index();
567 while !(self.is_eof() || self.starts_with("=")) {
568 self.advance_one();
569 }
570 let cur_idx = *self.index();
571
572 self.expected_spanned("pattern or '='", ini_idx..cur_idx)
573 })
574 }
575
576 pub fn parse_term(&mut self) -> ParseResult<Term> {
577 maybe_grow(|| {
578 let (tag, unexpected_tag) = self.parse_tag()?;
579 self.skip_trivia();
580
581 if self.starts_with("λ") || self.starts_with("@") {
583 self.advance_one();
584 let tag = tag.unwrap_or(Tag::Static);
585 let pat = self.parse_pattern(true)?;
586 let bod = self.parse_term()?;
587 return Ok(Term::Lam { tag, pat: Box::new(pat), bod: Box::new(bod) });
588 }
589
590 if self.starts_with("(") {
592 self.advance_one();
593 self.skip_trivia();
594
595 if let Some(opr) = self.try_parse_oper() {
603 if (opr == Op::ADD || opr == Op::SUB) && self.peek_one().is_some_and(|c| "0123456789".contains(c)) {
604 unexpected_tag(self)?;
605 *self.index() -= 1;
606 let num = self.parse_number()?;
607 let head = Term::Num { val: num };
608 self.skip_trivia();
609
610 if self.starts_with(",") {
611 self.consume_exactly(",")?;
612 let tail = self.list_like(|p| p.parse_term(), "", ")", ",", true, 1)?;
613 let els = [head].into_iter().chain(tail).collect();
614 return Ok(Term::Fan { fan: FanKind::Tup, tag: tag.unwrap_or(Tag::Static), els });
615 }
616
617 if self.starts_with(")") {
618 self.consume_exactly(")")?;
619 return Ok(head);
620 }
621
622 let els = self.list_like(|p| p.parse_term(), "", ")", "", false, 0)?;
623 let term = els.into_iter().fold(head, |fun, arg| Term::App {
624 tag: tag.clone().unwrap_or(Tag::Static),
625 fun: Box::new(fun),
626 arg: Box::new(arg),
627 });
628 return Ok(term);
629 }
630
631 self.skip_trivia();
632
633 if opr == Op::MUL && self.starts_with(",") {
634 self.consume_exactly(",")?;
635 let tail = self.list_like(|p| p.parse_term(), "", ")", ",", true, 1)?;
636 let els = [Term::Era].into_iter().chain(tail).collect();
637 return Ok(Term::Fan { fan: FanKind::Tup, tag: tag.unwrap_or(Tag::Static), els });
638 }
639
640 if opr == Op::MUL && self.starts_with(")") {
641 self.consume_exactly(")")?;
642 return Ok(Term::Era);
643 }
644
645 unexpected_tag(self)?;
647 let fst = self.parse_term()?;
648 let snd = self.parse_term()?;
649 self.consume(")")?;
650 return Ok(Term::Oper { opr, fst: Box::new(fst), snd: Box::new(snd) });
651 }
652
653 let head = self.parse_term()?;
655
656 self.skip_trivia();
658 if self.starts_with(",") {
659 let mut els = vec![head];
660 while self.try_consume(",") {
661 els.push(self.parse_term()?);
662 }
663 self.consume(")")?;
664 return Ok(Term::Fan { fan: FanKind::Tup, tag: tag.unwrap_or(Tag::Static), els });
665 }
666
667 let els = self.list_like(|p| p.parse_term(), "", ")", "", false, 0)?;
669 let term = els.into_iter().fold(head, |fun, arg| Term::App {
670 tag: tag.clone().unwrap_or(Tag::Static),
671 fun: Box::new(fun),
672 arg: Box::new(arg),
673 });
674 return Ok(term);
675 }
676
677 if self.starts_with("[") {
679 unexpected_tag(self)?;
680 let els = self.list_like(|p| p.parse_term(), "[", "]", ",", false, 0)?;
681 return Ok(Term::List { els });
682 }
683
684 if self.starts_with("![") {
686 self.advance_one();
687 self.advance_one();
688 unexpected_tag(self)?;
689 let lft = self.parse_term()?;
690 self.try_consume(",");
691 let rgt = self.parse_term()?;
692 self.labelled(|p| p.consume("]"), "Only two children in a Tree/Node")?;
693 return Ok(Term::call(Term::r#ref("Tree/Node"), [lft, rgt]));
694 }
695
696 if self.starts_with("!") {
698 self.advance_one();
699 unexpected_tag(self)?;
700 let val = self.parse_term()?;
701 return Ok(Term::app(Term::r#ref("Tree/Leaf"), val));
702 }
703
704 if self.starts_with("{") {
706 let els = self.list_like(|p| p.parse_term(), "{", "}", ",", false, 2)?;
707 return Ok(Term::Fan { fan: FanKind::Dup, tag: tag.unwrap_or(Tag::Auto), els });
708 }
709
710 if self.starts_with("$") {
712 self.advance_one();
713 unexpected_tag(self)?;
714 self.skip_trivia();
715 let nam = self.parse_var_name()?;
716 return Ok(Term::Link { nam });
717 }
718
719 if self.starts_with("*") {
721 self.advance_one();
722 unexpected_tag(self)?;
723 return Ok(Term::Era);
724 }
725
726 if self.starts_with("#") {
728 self.advance_one();
729 unexpected_tag(self)?;
730 let val = self.parse_u32()?;
731 return Ok(Term::Nat { val });
732 }
733
734 if self.starts_with("\"") {
736 unexpected_tag(self)?;
737 let str = self.parse_quoted_string()?;
738 return Ok(Term::Str { val: STRINGS.get(str) });
739 }
740
741 if self.starts_with("'") {
743 unexpected_tag(self)?;
744 let char = self.parse_quoted_char()?;
745 return Ok(Term::Num { val: Num::U24(char as u32 & 0x00ff_ffff) });
746 }
747
748 if self.starts_with("`") {
750 unexpected_tag(self)?;
751 let val = self.parse_quoted_symbol()?;
752 return Ok(Term::Num { val: Num::U24(val) });
753 }
754
755 if self.peek_one().is_some_and(is_num_char) {
757 unexpected_tag(self)?;
758 let num = self.parse_number()?;
759 return Ok(Term::Num { val: num });
760 }
761
762 if self.try_parse_keyword("use") {
764 unexpected_tag(self)?;
765 self.skip_trivia();
766 let nam = self.parse_var_name()?;
767 self.consume("=")?;
768 let val = self.parse_term()?;
769 self.try_consume(";");
770 let nxt = self.parse_term()?;
771 return Ok(Term::Use { nam: Some(nam), val: Box::new(val), nxt: Box::new(nxt) });
772 }
773
774 if self.try_parse_keyword("let") {
776 unexpected_tag(self)?;
777 let pat = self.parse_pattern(true)?;
778 self.consume("=")?;
779 let val = self.parse_term()?;
780 self.try_consume(";");
781 let nxt = self.parse_term()?;
782 return Ok(Term::Let { pat: Box::new(pat), val: Box::new(val), nxt: Box::new(nxt) });
783 }
784
785 if self.try_parse_keyword("ask") {
787 unexpected_tag(self)?;
788 let pat = self.parse_pattern(true)?;
789 self.consume("=")?;
790 let val = self.parse_term()?;
791 self.try_consume(";");
792 let nxt = self.parse_term()?;
793 return Ok(Term::Ask { pat: Box::new(pat), val: Box::new(val), nxt: Box::new(nxt) });
794 }
795
796 if self.try_parse_keyword("def") {
798 self.skip_trivia();
799 let mut def = self.parse_fun_def()?;
800 def.source.kind = SourceKind::Generated;
801 let nxt = self.parse_term()?;
802 return Ok(Term::Def { def, nxt: Box::new(nxt) });
803 }
804
805 if self.try_parse_keyword("if") {
807 let mut chain = Vec::new();
808 let cnd = self.parse_term()?;
809 self.consume("{")?;
810 let thn = self.parse_term()?;
811 self.consume("}")?;
812
813 chain.push((cnd, thn));
814
815 self.skip_trivia_inline()?;
816 while self.try_parse_keyword("elif") {
817 let cnd = self.parse_term()?;
818 self.consume("{")?;
819 let thn = self.parse_term()?;
820 self.consume("}")?;
821 self.skip_trivia_inline()?;
822 chain.push((cnd, thn));
823 }
824
825 self.consume("else")?;
826 self.consume("{")?;
827 let els = self.parse_term()?;
828 self.consume("}")?;
829 let els = chain.into_iter().rfold(els, |acc, (cnd, thn)| Term::Swt {
830 bnd: Some(Name::new("%cond")),
831 arg: Box::new(cnd),
832 with_bnd: Vec::new(),
833 with_arg: Vec::new(),
834 pred: Some(Name::new("%cond-1")),
835 arms: vec![acc, thn],
836 });
837 return Ok(els);
838 }
839
840 if self.try_parse_keyword("match") {
842 unexpected_tag(self)?;
843 let (bnd, arg) = self.parse_match_arg()?;
844 let (with_bnd, with_arg) = self.parse_with_clause()?;
845 let arms = self.list_like(|p| p.parse_match_arm(), "", "}", ";", false, 1)?;
846 return Ok(Term::Mat { arg: Box::new(arg), bnd, with_bnd, with_arg, arms });
847 }
848
849 if self.try_parse_keyword("switch") {
851 unexpected_tag(self)?;
852 let (bnd, arg) = self.parse_match_arg()?;
853 let (with_bnd, with_arg) = self.parse_with_clause()?;
854
855 self.try_consume("|");
856 self.consume("0")?;
857 self.consume(":")?;
858 let zero = self.parse_term()?;
859 self.try_consume(";");
860
861 let mut arms = vec![zero];
862 let mut expected_num = 1;
863 loop {
864 self.try_consume("|");
865 if self.try_consume("_") {
867 self.consume(":")?;
868 arms.push(self.parse_term()?);
869 self.try_consume(";");
870 self.consume("}")?;
871 break;
872 }
873 let val = self.parse_u32()?;
875 if val != expected_num {
876 return self.expected(&format!("'{}'", &expected_num.to_string()));
877 }
878 expected_num += 1;
879 self.consume(":")?;
880 arms.push(self.parse_term()?);
881 self.try_consume(";");
882 }
883 let pred = Some(Name::new(format!("{}-{}", bnd.as_ref().unwrap(), arms.len() - 1)));
884 return Ok(Term::Swt { arg: Box::new(arg), bnd, with_bnd, with_arg, pred, arms });
885 }
886
887 if self.try_parse_keyword("with") {
889 unexpected_tag(self)?;
890 let typ = self.parse_name()?;
891 self.consume("{")?;
892 let bod = self.parse_term()?;
893 self.consume("}")?;
894 return Ok(Term::With { typ: Name::new(typ), bod: Box::new(bod) });
895 }
896
897 if self.try_parse_keyword("fold") {
899 unexpected_tag(self)?;
900 let (bnd, arg) = self.parse_match_arg()?;
901 let (with_bnd, with_arg) = self.parse_with_clause()?;
902 let arms = self.list_like(|p| p.parse_match_arm(), "", "}", ";", false, 1)?;
903 return Ok(Term::Fold { arg: Box::new(arg), bnd, with_bnd, with_arg, arms });
904 }
905
906 if self.try_parse_keyword("bend") {
908 unexpected_tag(self)?;
909 let args = self.list_like(
910 |p| {
911 let bind = p.parse_var_name()?;
912 let init = if p.try_consume("=") { p.parse_term()? } else { Term::Var { nam: bind.clone() } };
913 Ok((bind, init))
914 },
915 "",
916 "{",
917 ",",
918 false,
919 0,
920 )?;
921 let (bind, init): (Vec<_>, Vec<_>) = args.into_iter().unzip();
922 let bind = bind.into_iter().map(Some).collect::<Vec<_>>();
923 self.skip_trivia();
924 self.parse_keyword("when")?;
925 let cond = self.parse_term()?;
926 self.consume(":")?;
927 let step = self.parse_term()?;
928 self.skip_trivia();
929 self.parse_keyword("else")?;
930 self.consume(":")?;
931 let base = self.parse_term()?;
932 self.consume("}")?;
933 return Ok(Term::Bend {
934 bnd: bind,
935 arg: init,
936 cond: Box::new(cond),
937 step: Box::new(step),
938 base: Box::new(base),
939 });
940 }
941
942 if self.try_parse_keyword("open") {
944 unexpected_tag(self)?;
945 self.skip_trivia();
946 let typ = self.parse_top_level_name()?;
947 self.skip_trivia();
948 let var = self.parse_var_name()?;
949 self.try_consume(";");
950 let bod = self.parse_term()?;
951 return Ok(Term::Open { typ, var, bod: Box::new(bod) });
952 }
953
954 unexpected_tag(self)?;
956 let nam = self.labelled(|p| p.parse_var_name(), "term")?;
957 Ok(Term::Var { nam })
958 })
959 }
960
961 fn parse_name_or_era(&mut self) -> ParseResult<Option<Name>> {
962 self.labelled(
963 |p| {
964 if p.try_consume_exactly("*") {
965 Ok(None)
966 } else {
967 let nam = p.parse_var_name()?;
968 Ok(Some(nam))
969 }
970 },
971 "name or '*'",
972 )
973 }
974
975 fn parse_tag(&mut self) -> ParseResult<(Option<Tag>, impl FnOnce(&mut Self) -> ParseResult<()>)> {
979 let index = self.index;
980 self.skip_trivia();
981 let tag = if self.peek_one() == Some('#')
982 && !self.peek_many(2).is_some_and(|x| x.chars().nth(1).unwrap().is_ascii_digit())
983 {
984 let msg = "Tagged terms not supported for hvm32.".to_string();
985 return self.err_msg_spanned(&msg, index..index + 1);
986 } else {
987 None
988 };
989 let end_index = self.index;
990 Ok((tag.clone(), move |slf: &mut Self| {
991 if let Some(tag) = tag {
992 let msg = format!("Unexpected tag '{tag}'");
993 slf.err_msg_spanned(&msg, index..end_index)
994 } else {
995 Ok(())
996 }
997 }))
998 }
999
1000 fn parse_match_arg(&mut self) -> ParseResult<(Option<Name>, Term)> {
1002 let ini_idx = *self.index();
1003 let mut arg = self.parse_term()?;
1004 let end_idx = *self.index();
1005
1006 self.skip_trivia();
1007 match (&mut arg, self.starts_with("=")) {
1008 (Term::Var { nam }, true) => {
1009 self.consume("=")?;
1010 Ok((Some(std::mem::take(nam)), self.parse_term()?))
1011 }
1012 (Term::Var { nam }, false) => Ok((Some(nam.clone()), Term::Var { nam: std::mem::take(nam) })),
1013 (_, true) => self.expected_spanned("argument name", ini_idx..end_idx),
1014 (arg, false) => Ok((Some(Name::new("%arg")), std::mem::take(arg))),
1015 }
1016 }
1017
1018 fn parse_named_arg(&mut self) -> ParseResult<(Option<Name>, Term)> {
1020 let nam = self.parse_var_name()?;
1021 self.skip_trivia();
1022 if self.starts_with("=") {
1023 self.advance_one();
1024 let arg = self.parse_term()?;
1025 Ok((Some(nam), arg))
1026 } else {
1027 let arg = Term::Var { nam: nam.clone() };
1028 Ok((Some(nam), arg))
1029 }
1030 }
1031
1032 fn parse_with_clause(&mut self) -> ParseResult<(Vec<Option<Name>>, Vec<Term>)> {
1033 self.skip_trivia();
1034 let res = if self.try_parse_keyword("with") {
1035 self.list_like(|p| p.parse_named_arg(), "", "{", ",", false, 1)?.into_iter().unzip()
1036 } else {
1037 self.consume_exactly("{")?;
1038 (vec![], vec![])
1039 };
1040 Ok(res)
1041 }
1042
1043 fn parse_match_arm(&mut self) -> ParseResult<MatchRule> {
1044 self.try_consume("|");
1045 self.skip_trivia();
1046 let nam = self.parse_name_or_era()?;
1047 self.consume(":")?;
1048 let bod = self.parse_term()?;
1049 Ok((nam, vec![], bod))
1050 }
1051
1052 fn parse_type_term(&mut self) -> ParseResult<Type> {
1053 let mut left = self.parse_type_atom()?;
1054 self.skip_trivia();
1055 while self.try_consume_exactly("->") {
1056 let right = self.parse_type_term()?;
1057 left = Type::Arr(Box::new(left), Box::new(right));
1058 }
1059 Ok(left)
1060 }
1061
1062 fn parse_type_atom(&mut self) -> ParseResult<Type> {
1065 self.skip_trivia();
1066 if self.try_parse_keyword("Any") {
1067 Ok(Type::Any)
1068 } else if self.try_parse_keyword("None") {
1069 Ok(Type::None)
1070 } else if self.try_parse_keyword("_") {
1071 Ok(Type::Hole)
1072 } else if self.try_parse_keyword("u24") {
1073 Ok(Type::U24)
1074 } else if self.try_parse_keyword("i24") {
1075 Ok(Type::I24)
1076 } else if self.try_parse_keyword("f24") {
1077 Ok(Type::F24)
1078 } else if self.try_consume_exactly("(") {
1079 let ini_idx = *self.index();
1081 let head = self.parse_type_term()?;
1082 self.skip_trivia();
1083 if self.try_consume_exactly(")") {
1084 Ok(head)
1086 } else if self.try_consume_exactly(",") {
1087 let mut types = vec![head];
1089 loop {
1090 types.push(self.parse_type_term()?);
1091 self.skip_trivia();
1092 if !self.try_consume_exactly(",") {
1093 break;
1094 }
1095 }
1096 self.consume(")")?;
1097 Ok(Type::Tup(types))
1098 } else {
1099 let Type::Var(nam) = head else {
1101 let end_idx = *self.index();
1102 return self.expected_spanned("type constructor", ini_idx..end_idx);
1104 };
1105 let mut args = vec![];
1106 while !self.try_consume(")") {
1108 args.push(self.parse_type_term()?);
1109 self.skip_trivia();
1110 }
1111 Ok(Type::Ctr(nam, args))
1112 }
1113 } else {
1114 let nam = self.parse_var_name()?;
1117 Ok(Type::Var(nam))
1118 }
1119 }
1120
1121 fn add_fun_def(&mut self, def: FunDefinition, book: &mut ParseBook, span: Range<usize>) -> ParseResult<()> {
1122 self.check_top_level_redefinition(&def.name, book, span)?;
1123 book.fun_defs.insert(def.name.clone(), def);
1124 Ok(())
1125 }
1126
1127 fn add_imp_def(
1128 &mut self,
1129 def: crate::imp::Definition,
1130 book: &mut ParseBook,
1131 span: Range<usize>,
1132 ) -> ParseResult<()> {
1133 self.check_top_level_redefinition(&def.name, book, span)?;
1134 book.imp_defs.insert(def.name.clone(), def);
1135 Ok(())
1136 }
1137
1138 fn add_hvm(&mut self, def: HvmDefinition, book: &mut ParseBook, span: Range<usize>) -> ParseResult<()> {
1139 self.check_top_level_redefinition(&def.name, book, span)?;
1140 book.hvm_defs.insert(def.name.clone(), def);
1141 Ok(())
1142 }
1143
1144 fn add_type_def(&mut self, adt: Adt, book: &mut ParseBook, span: Range<usize>) -> ParseResult<()> {
1145 self.check_type_redefinition(&adt.name, book, span.clone())?;
1146 for ctr in adt.ctrs.keys() {
1147 if let Some(builtin) = book.contains_builtin_def(ctr) {
1148 let msg = FunParser::redefinition_of_function_msg(builtin, ctr);
1149 return self.err_msg_spanned(&msg, span);
1150 }
1151 match book.ctrs.entry(ctr.clone()) {
1152 indexmap::map::Entry::Vacant(e) => _ = e.insert(adt.name.clone()),
1153 indexmap::map::Entry::Occupied(e) => {
1154 let msg = FunParser::redefinition_of_constructor_msg(e.key());
1155 return self.err_msg_spanned(&msg, span);
1156 }
1157 }
1158 }
1159 book.adts.insert(adt.name.clone(), adt);
1160 Ok(())
1161 }
1162
1163 fn check_top_level_redefinition(
1164 &mut self,
1165 name: &Name,
1166 book: &mut ParseBook,
1167 span: Range<usize>,
1168 ) -> ParseResult<()> {
1169 if let Some(builtin) = book.contains_builtin_def(name) {
1170 let msg = Self::redefinition_of_function_msg(builtin, name);
1171 return self.err_msg_spanned(&msg, span);
1172 }
1173 if book.ctrs.contains_key(name) {
1174 let msg = Self::redefinition_of_constructor_msg(name);
1175 return self.err_msg_spanned(&msg, span);
1176 }
1177 if book.hvm_defs.contains_key(name) {
1178 let msg = Self::redefinition_of_hvm_msg(false, name);
1179 return self.err_msg_spanned(&msg, span);
1180 }
1181 Ok(())
1182 }
1183
1184 fn check_type_redefinition(
1185 &mut self,
1186 name: &Name,
1187 book: &mut ParseBook,
1188 span: Range<usize>,
1189 ) -> ParseResult<()> {
1190 if book.adts.contains_key(name) {
1191 let msg = Self::redefinition_of_type_msg(name);
1192 return self.err_msg_spanned(&msg, span);
1193 }
1194 Ok(())
1195 }
1196}
1197
1198impl<'a> Parser<'a> for FunParser<'a> {
1199 fn input(&mut self) -> &'a str {
1200 self.input
1201 }
1202
1203 fn index(&mut self) -> &mut usize {
1204 &mut self.index
1205 }
1206
1207 fn expected<T>(&mut self, exp: &str) -> ParseResult<T> {
1211 let ini_idx = *self.index();
1212 let end_idx = *self.index() + 1;
1213 self.expected_spanned(exp, ini_idx..end_idx)
1214 }
1215
1216 fn expected_and<T>(&mut self, exp: &str, msg: &str) -> ParseResult<T> {
1220 let ini_idx = *self.index();
1221 let end_idx = *self.index() + 1;
1222 self.expected_spanned_and(exp, msg, ini_idx..end_idx)
1223 }
1224
1225 fn consume(&mut self, text: &str) -> ParseResult<()> {
1229 self.skip_trivia();
1230 if self.input().get(*self.index()..).unwrap_or_default().starts_with(text) {
1231 *self.index() += text.len();
1232 Ok(())
1233 } else {
1234 self.expected(format!("'{text}'").as_str())
1235 }
1236 }
1237
1238 fn skip_trivia(&mut self) {
1239 while let Some(c) = self.peek_one() {
1240 if c.is_ascii_whitespace() {
1241 self.advance_one();
1242 continue;
1243 }
1244 if c == '#' {
1245 self.advance_one();
1246 if let Some(c) = self.peek_one() {
1247 if c == '{' {
1248 self.advance_one();
1249 while let Some(c) = self.peek_one() {
1250 self.advance_one();
1251 if c == '#' {
1252 if let Some('}') = self.peek_one() {
1253 self.advance_one();
1254 break;
1255 } else {
1256 self.advance_one();
1257 }
1258 }
1259 }
1260 } else {
1261 while let Some(c) = self.peek_one() {
1262 if c != '\n' {
1263 self.advance_one();
1264 } else {
1265 break;
1266 }
1267 }
1268 }
1269 }
1270 continue;
1271 }
1272 break;
1273 }
1274 }
1275}
1276
1277pub fn is_name_char(c: char) -> bool {
1278 c.is_ascii_alphanumeric() || c == '_' || c == '.' || c == '-' || c == '/'
1279}
1280
1281pub fn is_num_char(c: char) -> bool {
1282 "0123456789+-".contains(c)
1283}
1284
1285pub fn make_fn_type(args: Vec<Type>, ret: Type) -> Type {
1286 args.into_iter().rfold(ret, |acc, typ| Type::Arr(Box::new(typ), Box::new(acc)))
1287}
1288
1289pub fn make_ctr_type(type_name: Name, fields: &[Type], vars: &[Name]) -> Type {
1290 let typ = Type::Ctr(type_name, vars.iter().cloned().map(Type::Var).collect());
1291 let typ = fields.iter().rfold(typ, |acc, typ| Type::Arr(Box::new(typ.clone()), Box::new(acc)));
1292 typ
1293}
1294
1295#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1296pub enum Indent {
1297 Val(isize),
1298 Eof,
1299}
1300
1301impl Indent {
1302 pub fn new(val: isize) -> Self {
1303 Indent::Val(val)
1304 }
1305
1306 pub fn enter_level(&mut self) {
1307 if let Indent::Val(val) = self {
1308 *val += 2;
1309 }
1310 }
1311
1312 pub fn exit_level(&mut self) {
1313 if let Indent::Val(val) = self {
1314 *val -= 2;
1315 }
1316 }
1317}
1318
1319impl<'a> ParserCommons<'a> for FunParser<'a> {}
1320
1321pub trait ParserCommons<'a>: Parser<'a> {
1322 fn labelled<T>(&mut self, parser: impl Fn(&mut Self) -> ParseResult<T>, label: &str) -> ParseResult<T> {
1323 match parser(self) {
1324 Ok(val) => Ok(val),
1325 Err(_) => self.expected(label),
1326 }
1327 }
1328
1329 fn parse_restricted_name(&mut self, kind: &str) -> ParseResult<Name> {
1330 let ini_idx = *self.index();
1331 let name = self.take_while(is_name_char);
1332 if name.is_empty() {
1333 self.expected(&format!("{kind} name"))?
1334 }
1335 let name = Name::new(name.to_owned());
1336 let end_idx = *self.index();
1337 if name.contains("__") {
1338 let msg = format!("{kind} names are not allowed to contain \"__\".");
1339 self.err_msg_spanned(&msg, ini_idx..end_idx)
1340 } else if name.starts_with("//") {
1341 let msg = format!("{kind} names are not allowed to start with \"//\".");
1342 self.err_msg_spanned(&msg, ini_idx..end_idx)
1343 } else {
1344 Ok(name)
1345 }
1346 }
1347
1348 fn parse_top_level_name(&mut self) -> ParseResult<Name> {
1349 self.parse_restricted_name("Top-level")
1350 }
1351
1352 fn parse_var_name(&mut self) -> ParseResult<Name> {
1353 self.parse_restricted_name("Variable")
1354 }
1355
1356 fn parse_name_maybe_alias(&mut self, label: &str) -> ParseResult<(Name, Option<Name>)> {
1357 let name = self.parse_restricted_name(label)?;
1358
1359 if self.try_consume("as") {
1360 self.skip_trivia();
1361 let alias = self.parse_restricted_name("Alias")?;
1362 Ok((name, Some(alias)))
1363 } else {
1364 Ok((name, None))
1365 }
1366 }
1367
1368 fn parse_import_name(&mut self, label: &str) -> ParseResult<(Name, Option<Name>, bool)> {
1369 let (import, alias) = self.parse_name_maybe_alias(label)?;
1370 let relative = import.starts_with("./") | import.starts_with("../");
1371 Ok((import, alias, relative))
1372 }
1373
1374 fn consume_exactly(&mut self, text: &str) -> ParseResult<()> {
1376 if self.input().get(*self.index()..).unwrap_or_default().starts_with(text) {
1377 *self.index() += text.len();
1378 Ok(())
1379 } else {
1380 self.expected(format!("'{text}'").as_str())
1381 }
1382 }
1383
1384 fn consume_new_line(&mut self) -> ParseResult<()> {
1385 self.skip_trivia_inline()?;
1386 self.try_consume_exactly("\r");
1387 self.labelled(|p| p.consume_exactly("\n"), "newline")
1388 }
1389
1390 fn advance_newlines(&mut self) -> ParseResult<Indent> {
1392 loop {
1393 let num_spaces = self.advance_trivia_inline()?;
1394 if self.peek_one() == Some('\r') {
1395 self.advance_one();
1396 }
1397 if self.peek_one() == Some('\n') {
1398 self.advance_one();
1399 } else if self.is_eof() {
1400 return Ok(Indent::Eof);
1401 } else {
1402 return Ok(Indent::Val(num_spaces));
1403 }
1404 }
1405 }
1406
1407 fn advance_trivia_inline(&mut self) -> ParseResult<isize> {
1410 let mut char_count = 0;
1411 while let Some(c) = self.peek_one() {
1412 if c == '\t' {
1413 let idx = *self.index();
1414 return self.err_msg_spanned("Tabs are not accepted for indentation.", idx..idx + 1);
1415 }
1416 if " ".contains(c) {
1417 self.advance_one();
1418 char_count += 1;
1419 continue;
1420 }
1421 if c == '#' {
1422 self.advance_one();
1423 char_count += 1;
1424 if let Some(c) = self.peek_one() {
1425 if c == '{' {
1426 self.advance_one();
1427 char_count += 1;
1428 while let Some(c) = self.peek_one() {
1429 self.advance_one();
1430 char_count += 1;
1431 if c == '#' {
1432 if let Some('}') = self.peek_one() {
1433 self.advance_one();
1434 char_count += 1;
1435 break;
1436 } else {
1437 self.advance_one();
1438 char_count += 1;
1439 }
1440 }
1441 }
1442 } else {
1443 while let Some(c) = self.peek_one() {
1444 if c != '\n' {
1445 self.advance_one();
1446 char_count += 1;
1447 } else {
1448 break;
1449 }
1450 }
1451 }
1452 }
1453 continue;
1454 }
1455 break;
1456 }
1457 Ok(char_count)
1458 }
1459
1460 fn skip_trivia_inline(&mut self) -> ParseResult<()> {
1462 self.advance_trivia_inline()?;
1463 Ok(())
1464 }
1465
1466 fn expected_spanned<T>(&mut self, exp: &str, span: Range<usize>) -> ParseResult<T> {
1467 let is_eof = self.is_eof();
1468 let detected = DisplayFn(|f| if is_eof { write!(f, " end of input") } else { Ok(()) });
1469 let msg = format!("\x1b[1m- expected:\x1b[0m {}\n\x1b[1m- detected:\x1b[0m{}", exp, detected);
1470 self.with_ctx(Err(msg), span)
1471 }
1472
1473 fn expected_spanned_and<T>(&mut self, exp: &str, msg: &str, span: Range<usize>) -> ParseResult<T> {
1475 let is_eof = self.is_eof();
1476 let detected = DisplayFn(|f| if is_eof { write!(f, " end of input") } else { Ok(()) });
1477 let msg = format!(
1478 "\x1b[1m- information:\x1b[0m {}\n\x1b[1m- expected:\x1b[0m {}\n\x1b[1m- detected:\x1b[0m{}",
1479 msg, exp, detected,
1480 );
1481 self.with_ctx(Err(msg), span)
1482 }
1483
1484 fn err_msg_spanned<T>(&mut self, msg: &str, span: Range<usize>) -> ParseResult<T> {
1486 let is_eof = self.is_eof();
1487 let eof_msg = if is_eof { " end of input" } else { "" };
1488 let msg = format!("{msg}\nLocation:{eof_msg}");
1489 self.with_ctx(Err(msg), span)
1490 }
1491
1492 fn with_ctx<T>(&mut self, res: Result<T, impl std::fmt::Display>, span: Range<usize>) -> ParseResult<T> {
1494 res.map_err(|msg| {
1495 let ctx = highlight_error(span.start, span.end, self.input());
1496 let msg = format!("{msg}\n{ctx}");
1497 ParseError::new((span.start, span.end), msg)
1498 })
1499 }
1500
1501 fn try_consume(&mut self, text: &str) -> bool {
1503 self.skip_trivia();
1504 if self.starts_with(text) {
1505 self.consume(text).unwrap();
1506 true
1507 } else {
1508 false
1509 }
1510 }
1511
1512 fn try_consume_exactly(&mut self, text: &str) -> bool {
1514 if self.starts_with(text) {
1515 self.consume_exactly(text).unwrap();
1516 true
1517 } else {
1518 false
1519 }
1520 }
1521
1522 fn try_parse_keyword(&mut self, keyword: &str) -> bool {
1523 if self.starts_with_keyword(keyword) {
1524 self.consume_exactly(keyword).unwrap();
1525 true
1526 } else {
1527 false
1528 }
1529 }
1530
1531 fn parse_keyword(&mut self, keyword: &str) -> ParseResult<()> {
1532 let ini_idx = *self.index();
1533 self.consume_exactly(keyword)?;
1534 let end_idx = *self.index();
1535 let input = &self.input()[*self.index()..];
1536 let next_is_name = input.chars().next().is_some_and(is_name_char);
1537 if !next_is_name {
1538 Ok(())
1539 } else {
1540 self.expected_spanned(&format!("keyword '{keyword}'"), ini_idx..end_idx + 1)
1541 }
1542 }
1543
1544 fn starts_with_keyword(&mut self, keyword: &str) -> bool {
1545 if self.starts_with(keyword) {
1546 let input = &self.input()[*self.index() + keyword.len()..];
1547 let next_is_name = input.chars().next().is_some_and(is_name_char);
1548 !next_is_name
1549 } else {
1550 false
1551 }
1552 }
1553
1554 fn list_like<T>(
1564 &mut self,
1565 mut parser: impl FnMut(&mut Self) -> ParseResult<T>,
1566 start: &str,
1567 end: &str,
1568 sep: &str,
1569 hard_sep: bool,
1570 min_els: usize,
1571 ) -> ParseResult<Vec<T>> {
1572 self.consume_exactly(start)?;
1573
1574 let mut els = vec![];
1575 for i in 0..min_els {
1577 self.skip_trivia();
1578 els.push(parser(self)?);
1579 self.skip_trivia();
1580 if hard_sep && !(i == min_els - 1 && self.starts_with(end)) {
1581 self.consume(sep)?;
1582 } else {
1583 self.try_consume(sep);
1584 }
1585 }
1586
1587 while !self.try_consume(end) {
1589 els.push(parser(self)?);
1590 self.skip_trivia();
1591 if hard_sep && !self.starts_with(end) {
1592 self.consume(sep)?;
1593 } else {
1594 self.try_consume(sep);
1595 }
1596 }
1597 Ok(els)
1598 }
1599
1600 fn try_parse_oper(&mut self) -> Option<Op> {
1601 let opr = if self.try_consume_exactly("+") {
1602 Op::ADD
1603 } else if self.try_consume_exactly("-") {
1604 Op::SUB
1605 } else if self.try_consume_exactly("**") {
1606 Op::POW
1607 } else if self.try_consume_exactly("*") {
1608 Op::MUL
1609 } else if self.try_consume_exactly("/") {
1610 Op::DIV
1611 } else if self.try_consume_exactly("%") {
1612 Op::REM
1613 } else if self.try_consume_exactly("<<") {
1614 Op::SHL
1615 } else if self.try_consume_exactly(">>") {
1616 Op::SHR
1617 } else if self.try_consume_exactly("<=") {
1618 Op::LE
1619 } else if self.try_consume_exactly(">=") {
1620 Op::GE
1621 } else if self.try_consume_exactly("<") {
1622 Op::LT
1623 } else if self.try_consume_exactly(">") {
1624 Op::GT
1625 } else if self.try_consume_exactly("==") {
1626 Op::EQ
1627 } else if self.try_consume_exactly("!=") {
1628 Op::NEQ
1629 } else if self.try_consume_exactly("&") {
1630 Op::AND
1631 } else if self.try_consume_exactly("|") {
1632 Op::OR
1633 } else if self.try_consume_exactly("^") {
1634 Op::XOR
1635 } else {
1636 return None;
1637 };
1638 Some(opr)
1639 }
1640
1641 fn peek_oper(&mut self) -> Option<Op> {
1642 let opr = if self.starts_with("+") {
1643 Op::ADD
1644 } else if self.starts_with("-") {
1645 Op::SUB
1646 } else if self.starts_with("**") {
1647 Op::POW
1648 } else if self.starts_with("*") {
1649 Op::MUL
1650 } else if self.starts_with("/") {
1651 Op::DIV
1652 } else if self.starts_with("%") {
1653 Op::REM
1654 } else if self.starts_with("<<") {
1655 Op::SHL
1656 } else if self.starts_with(">>") {
1657 Op::SHR
1658 } else if self.starts_with("<=") {
1659 Op::LE
1660 } else if self.starts_with(">=") {
1661 Op::GE
1662 } else if self.starts_with("<") {
1663 Op::LT
1664 } else if self.starts_with(">") {
1665 Op::GT
1666 } else if self.starts_with("==") {
1667 Op::EQ
1668 } else if self.starts_with("!=") {
1669 Op::NEQ
1670 } else if self.starts_with("&") {
1671 Op::AND
1672 } else if self.starts_with("|") {
1673 Op::OR
1674 } else if self.starts_with("^") {
1675 Op::XOR
1676 } else {
1677 return None;
1678 };
1679 Some(opr)
1680 }
1681
1682 fn parse_u32(&mut self) -> ParseResult<u32> {
1683 let radix = match self.peek_many(2) {
1684 Some("0x") => {
1685 self.advance_many(2);
1686 Radix::Hex
1687 }
1688 Some("0b") => {
1689 self.advance_many(2);
1690 Radix::Bin
1691 }
1692 _ => Radix::Dec,
1693 };
1694 let num_str = self.take_while(move |c| c.is_digit(radix as u32) || c == '_');
1695 let num_str = num_str.chars().filter(|c| *c != '_').collect::<String>();
1696
1697 let next_is_hex = self.peek_one().is_some_and(|c| "0123456789abcdefABCDEF".contains(c));
1698 if next_is_hex || num_str.is_empty() {
1699 self.expected(format!("valid {radix} digit").as_str())
1700 } else {
1701 u32::from_str_radix(&num_str, radix as u32)
1702 .map_err(|e| self.expected_and::<u64>("integer", &e.to_string()).unwrap_err())
1703 }
1704 }
1705
1706 fn u32_with_radix(&mut self, radix: Radix) -> ParseResult<u32> {
1707 let num_str = self.take_while(move |c| c.is_digit(radix as u32) || c == '_');
1708 let num_str = num_str.chars().filter(|c| *c != '_').collect::<String>();
1709 let next_is_hex = self.peek_one().is_some_and(|c| "0123456789abcdefABCDEF".contains(c));
1710 if next_is_hex || num_str.is_empty() {
1711 self.expected(format!("valid {radix} digit").as_str())
1712 } else {
1713 u32::from_str_radix(&num_str, radix as u32)
1714 .map_err(|e| self.expected_and::<u64>("integer", &e.to_string()).unwrap_err())
1715 }
1716 }
1717
1718 fn parse_number(&mut self) -> ParseResult<Num> {
1719 let ini_idx = *self.index();
1720 let sign = if self.try_consume_exactly("+") {
1721 Some(1)
1722 } else if self.try_consume_exactly("-") {
1723 Some(-1)
1724 } else {
1725 None
1726 };
1727 let radix = match self.peek_many(2) {
1728 Some("0x") => {
1729 self.advance_many(2);
1730 Radix::Hex
1731 }
1732 Some("0b") => {
1733 self.advance_many(2);
1734 Radix::Bin
1735 }
1736 _ => Radix::Dec,
1737 };
1738 let num = self.u32_with_radix(radix)?;
1739 let frac = if let Some('.') = self.peek_one() {
1740 self.advance_one();
1741 let fra_str = self.take_while(|c| c.is_digit(radix as u32) || c == '_');
1742 let fra_str = fra_str.chars().filter(|c| *c != '_').collect::<String>();
1743 let fra = u32::from_str_radix(&fra_str, radix as u32)
1744 .map_err(|e| self.expected_and::<u64>("integer", &e.to_string()).unwrap_err())?;
1745 let fra = fra as f32 / (radix.to_f32()).powi(fra_str.len() as i32);
1746 Some(fra)
1747 } else {
1748 None
1749 };
1750
1751 if let Some(frac) = frac {
1752 let sign = sign.unwrap_or(1);
1753 return Ok(Num::F24(sign as f32 * (num as f32 + frac)));
1754 }
1755
1756 if let Some(sign) = sign {
1757 let num = sign * num as i32;
1758 if !(-0x00800000..=0x007fffff).contains(&num) {
1759 return self.num_range_err(ini_idx, "I24");
1760 }
1761 Ok(Num::I24(num))
1762 } else {
1763 if num >= 1 << 24 {
1764 return self.num_range_err(ini_idx, "U24");
1765 }
1766 Ok(Num::U24(num))
1767 }
1768 }
1769
1770 fn num_range_err<T>(&mut self, ini_idx: usize, typ: &str) -> ParseResult<T> {
1771 let msg = format!("\x1b[1mNumber literal outside of range for {}.\x1b[0m", typ);
1772 let end_idx = *self.index();
1773 self.err_msg_spanned(&msg, ini_idx..end_idx)
1774 }
1775
1776 fn parse_quoted_symbol(&mut self) -> ParseResult<u32> {
1779 self.consume_exactly("`")?;
1780 let mut result = 0;
1781 let mut count = 0;
1782 while count < 4 {
1783 if self.starts_with("`") {
1784 break;
1785 }
1786 count += 1;
1787 let Some(c) = self.advance_one() else { self.expected("base_64 character")? };
1788 let c = c as u8;
1789 let nxt = match c {
1790 b'A'..=b'Z' => c - b'A',
1791 b'a'..=b'z' => c - b'a' + 26,
1792 b'0'..=b'9' => c - b'0' + 52,
1793 b'+' => 62,
1794 b'/' => 63,
1795 _ => return self.expected("base64 character"),
1796 };
1797 result = (result << 6) | nxt as u32;
1798 }
1799 self.consume_exactly("`")?;
1800 Ok(result)
1801 }
1802
1803 fn check_repeated_ctr_fields(
1804 &mut self,
1805 fields: &[CtrField],
1806 ctr_name: &Name,
1807 span: Range<usize>,
1808 ) -> ParseResult<()> {
1809 for i in 0..fields.len() {
1810 let field = &fields[i];
1811 if fields.iter().skip(i + 1).any(|a: &CtrField| a.nam == field.nam) {
1812 let msg = format!("Found a repeated field '{}' in constructor {}.", field.nam, ctr_name);
1813 return self.err_msg_spanned(&msg, span);
1814 }
1815 }
1816 Ok(())
1817 }
1818
1819 fn redefinition_of_function_msg(builtin: bool, function_name: &str) -> String {
1820 if builtin {
1821 format!("Redefinition of builtin (function) '{function_name}'.")
1822 } else {
1823 format!("Redefinition of function '{function_name}'.")
1824 }
1825 }
1826
1827 fn redefinition_of_hvm_msg(builtin: bool, function_name: &str) -> String {
1828 if builtin {
1829 format!("Redefinition of builtin (native HVM function) '{function_name}'.")
1830 } else {
1831 format!("Redefinition of native HVM function '{function_name}'.")
1832 }
1833 }
1834
1835 fn redefinition_of_constructor_msg(constructor_name: &str) -> String {
1836 if crate::fun::builtins::BUILTIN_CTRS.contains(&constructor_name) {
1837 format!("Redefinition of builtin (constructor) '{constructor_name}'.")
1838 } else {
1839 format!("Redefinition of constructor '{constructor_name}'.")
1840 }
1841 }
1842
1843 fn redefinition_of_type_msg(type_name: &str) -> String {
1844 if crate::fun::builtins::BUILTIN_TYPES.contains(&type_name) {
1845 format!("Redefinition of builtin (type) '{type_name}'.")
1846 } else {
1847 format!("Redefinition of type '{type_name}'.")
1848 }
1849 }
1850}
1851
1852#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1853pub enum Radix {
1854 Bin = 2,
1855 Dec = 10,
1856 Hex = 16,
1857}
1858
1859impl Radix {
1860 fn to_f32(self) -> f32 {
1861 match self {
1862 Radix::Bin => 2.,
1863 Radix::Dec => 10.,
1864 Radix::Hex => 16.,
1865 }
1866 }
1867}
1868
1869impl std::fmt::Display for Radix {
1870 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1871 match self {
1872 Radix::Bin => write!(f, "binary"),
1873 Radix::Dec => write!(f, "decimal"),
1874 Radix::Hex => write!(f, "hexadecimal"),
1875 }
1876 }
1877}