yatima_core/parse/
term.rs

1use crate::{
2  defs::Defs,
3  name::Name,
4  parse::{
5    error::{
6      throw_err,
7      ParseError,
8      ParseErrorKind,
9    },
10    literal::*,
11    op::parse_opr,
12  },
13  position::Pos,
14  term::{
15    LitType,
16    Term,
17    Uses,
18  },
19};
20
21use sp_cid::Cid;
22use sp_multihash::{
23  Code,
24  MultihashDigest,
25};
26
27use sp_im::conslist::ConsList;
28use sp_ipld::{
29  dag_cbor::DagCborCodec,
30  Codec,
31};
32
33use sp_std::{
34  borrow::ToOwned,
35  boxed::Box,
36  cell::RefCell,
37  rc::Rc,
38  vec::Vec,
39};
40
41use alloc::string::{
42  String,
43  ToString,
44};
45
46use crate::parse::span::Span;
47
48use nom::{
49  branch::alt,
50  bytes::complete::{
51    tag,
52    take_till,
53    take_till1,
54  },
55  character::complete::{
56    digit1,
57    multispace0,
58    multispace1,
59    satisfy,
60  },
61  combinator::{
62    eof,
63    map,
64    opt,
65    peek,
66    success,
67    value,
68  },
69  error::context,
70  multi::{
71    many0,
72    many1,
73    separated_list1,
74  },
75  sequence::{
76    delimited,
77    preceded,
78    terminated,
79  },
80  Err,
81  IResult,
82};
83use sp_std::collections::vec_deque::VecDeque;
84
85/// Parsing context to store expression names
86pub type Ctx = ConsList<Name>;
87
88/// Returns a list of reserved Yatima symbols
89pub fn reserved_symbols() -> VecDeque<String> {
90  VecDeque::from(vec![
91    String::from("//"),
92    String::from("λ"),
93    String::from("ω"),
94    String::from("lambda"),
95    String::from("=>"),
96    String::from("∀"),
97    String::from("forall"),
98    String::from("->"),
99    String::from("@"),
100    String::from("="),
101    String::from(";"),
102    String::from("::"),
103    String::from("let"),
104    String::from("in"),
105    String::from("type"),
106    String::from("data"),
107    String::from("def"),
108    String::from("open"),
109    String::from("case"),
110    String::from("Type"),
111  ])
112}
113
114/// Parses a line comment
115pub fn parse_line_comment(i: Span) -> IResult<Span, Span, ParseError<Span>> {
116  let (i, _) = tag("//")(i)?;
117  let (i, com) = take_till(|c| c == '\n')(i)?;
118  Ok((i, com))
119}
120
121/// Parses zero or more spaces or control characters
122pub fn parse_space(i: Span) -> IResult<Span, Vec<Span>, ParseError<Span>> {
123  let (i, _) = multispace0(i)?;
124  let (i, com) = many0(terminated(parse_line_comment, multispace1))(i)?;
125  Ok((i, com))
126}
127
128/// Parses one or more spaces or control characters
129pub fn parse_space1(i: Span) -> IResult<Span, Vec<Span>, ParseError<Span>> {
130  let (i, _) = multispace1(i)?;
131  let (i, com) = many0(terminated(parse_line_comment, multispace1))(i)?;
132  Ok((i, com))
133}
134
135/// Parses a name
136pub fn parse_name(from: Span) -> IResult<Span, Name, ParseError<Span>> {
137  let (i, s) = take_till1(|x| {
138    char::is_whitespace(x)
139      | (x == ':')
140      | (x == ';')
141      | (x == ')')
142      | (x == '(')
143      | (x == '{')
144      | (x == '}')
145      | (x == ',')
146  })(from)?;
147  let s: String = String::from(s.fragment().to_owned());
148  if reserved_symbols().contains(&s) {
149    Err(Err::Error(ParseError::new(from, ParseErrorKind::ReservedKeyword(s))))
150  }
151  else if s.starts_with('#') {
152    Err(Err::Error(ParseError::new(from, ParseErrorKind::ReservedSyntax(s))))
153  }
154  else if is_numeric_symbol_string1(&s) | is_numeric_symbol_string2(&s) {
155    Err(Err::Error(ParseError::new(from, ParseErrorKind::NumericSyntax(s))))
156  }
157  else if !is_valid_symbol_string(&s) {
158    Err(Err::Error(ParseError::new(from, ParseErrorKind::InvalidSymbol(s))))
159  }
160  else {
161    Ok((i, Name::from(s)))
162  }
163}
164
165/// Checks if a string represents an unsigned number
166pub fn is_numeric_symbol_string1(s: &str) -> bool {
167  s.starts_with('0')
168    || s.starts_with('1')
169    || s.starts_with('2')
170    || s.starts_with('3')
171    || s.starts_with('4')
172    || s.starts_with('5')
173    || s.starts_with('6')
174    || s.starts_with('7')
175    || s.starts_with('8')
176    || s.starts_with('9')
177}
178
179/// Checks if a string represents a signed number
180pub fn is_numeric_symbol_string2(s: &str) -> bool {
181  s.starts_with("-0")
182    || s.starts_with("-1")
183    || s.starts_with("-2")
184    || s.starts_with("-3")
185    || s.starts_with("-4")
186    || s.starts_with("-5")
187    || s.starts_with("-6")
188    || s.starts_with("-7")
189    || s.starts_with("-8")
190    || s.starts_with("-9")
191    || s.starts_with("+0")
192    || s.starts_with("+1")
193    || s.starts_with("+2")
194    || s.starts_with("+3")
195    || s.starts_with("+4")
196    || s.starts_with("+5")
197    || s.starts_with("+6")
198    || s.starts_with("+7")
199    || s.starts_with("+8")
200    || s.starts_with("+9")
201}
202
203/// Checks if a char represents a valid syntactical character
204pub fn is_valid_symbol_char(c: char) -> bool {
205  c != ':'
206    && c != ';'
207    && c != '('
208    && c != ')'
209    && c != '{'
210    && c != '}'
211    && c != ','
212    && !char::is_whitespace(c)
213    && !char::is_control(c)
214}
215
216/// Checks if a string represents valid text
217pub fn is_valid_symbol_string(s: &str) -> bool {
218  let invalid_chars = s.starts_with('"')
219    || s.starts_with('\'')
220    || s.starts_with('#')
221    || s.chars().any(|x| !is_valid_symbol_char(x));
222  !s.is_empty() && !invalid_chars
223}
224
225/// parse an antiquotation (useful when embedding Yatima expressions in a Rust
226/// source file)
227pub fn parse_antiquote(
228  ctx: Ctx,
229  quasi: Rc<VecDeque<Term>>,
230) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
231  move |from: Span| {
232    let (upto, nam) =
233      context("quasiquoted value", preceded(tag("#$"), digit1))(from)?;
234    if let Some((_, trm)) = quasi
235      .iter()
236      .enumerate()
237      .find(|(i, _)| format!("{}", i) == nam.to_string())
238    {
239      Ok((upto, trm.clone()))
240    }
241    else {
242      Err(Err::Error(ParseError::new(
243        upto,
244        ParseErrorKind::UndefinedReference(
245          Name::from(format!("#${}", nam.to_string())),
246          ctx.clone(),
247        ),
248      )))
249    }
250  }
251}
252
253/// Parses a variable
254pub fn parse_var(
255  input: Cid,
256  defs: Rc<RefCell<Defs>>,
257  rec: Option<Name>,
258  ctx: Ctx,
259) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
260  move |from: Span| {
261    let (upto, nam) = context("local or global reference", parse_name)(from)?;
262    let pos = Pos::from_upto(input, from, upto);
263    let is_rec_name = match rec.clone() {
264      Some(rec_ref) => nam == rec_ref,
265      _ => false,
266    };
267    if let Some((idx, _)) = ctx.iter().enumerate().find(|(_, x)| **x == nam) {
268      Ok((upto, Term::Var(pos, nam.clone(), idx as u64)))
269    }
270    else if is_rec_name {
271      Ok((upto, Term::Rec(pos)))
272    }
273    else if let Some(def) = defs.as_ref().borrow().get(&nam) {
274      Ok((upto, Term::Ref(pos, nam.clone(), def.def_cid, def.ast_cid)))
275    }
276    else {
277      Err(Err::Error(ParseError::new(
278        upto,
279        ParseErrorKind::UndefinedReference(nam.clone(), ctx.clone()),
280      )))
281    }
282  }
283}
284
285/// Parses a λ term
286pub fn parse_lam(
287  input: Cid,
288  defs: Rc<RefCell<Defs>>,
289  rec: Option<Name>,
290  ctx: Ctx,
291  quasi: Rc<VecDeque<Term>>,
292) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
293  move |from: Span| {
294    let (i, _) = alt((tag("λ"), tag("lambda")))(from)?;
295    let (i, _) = parse_space(i)?;
296    let (i, ns) = separated_list1(multispace1, parse_name)(i)?;
297    let (i, _) = parse_space(i)?;
298    let (i, _) = tag("=>")(i)?;
299    let (i, _) = parse_space(i)?;
300    let mut ctx2 = ctx.clone();
301    for n in ns.clone().into_iter() {
302      ctx2 = ctx2.cons(n);
303    }
304    let (upto, bod) = parse_expression(
305      input,
306      defs.clone(),
307      rec.clone(),
308      ctx2,
309      quasi.to_owned(),
310    )(i)?;
311    let pos = Pos::from_upto(input, from, upto);
312    let trm = ns
313      .iter()
314      .rev()
315      .fold(bod, |acc, n| Term::Lam(pos, n.clone(), Box::new(acc)));
316    Ok((upto, trm))
317  }
318}
319
320/// Parses a Uses dependent type
321pub fn parse_uses(
322  default: Uses,
323) -> impl Fn(Span) -> IResult<Span, Uses, ParseError<Span>> {
324  move |i: Span| {
325    alt((
326      value(Uses::Many, terminated(tag("ω"), multispace1)),
327      value(Uses::None, terminated(tag("0"), multispace1)),
328      value(Uses::Affi, terminated(tag("&"), multispace1)),
329      value(Uses::Once, terminated(tag("1"), multispace1)),
330      success(default),
331    ))(i)
332  }
333}
334
335/// Parse the full form of a binder (<uses> <var>* : <type>)
336pub fn parse_binder_full(
337  input: Cid,
338  defs: Rc<RefCell<Defs>>,
339  rec: Option<Name>,
340  ctx: Ctx,
341  quasi: Rc<VecDeque<Term>>,
342  uses: Uses,
343) -> impl Fn(Span) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
344  move |i: Span| {
345    let (i, _) = tag("(")(i)?;
346    let (i, _) = parse_space(i)?;
347    let (i, u) = parse_uses(uses)(i)?;
348    let (i, ns) = many1(terminated(parse_name, parse_space))(i)?;
349    let (i, _) = tag(":")(i)?;
350    let (i, _) = parse_space(i)?;
351    let (i, typ) = parse_expression(
352      input,
353      defs.clone(),
354      rec.clone(),
355      ctx.clone(),
356      quasi.to_owned(),
357    )(i)?;
358    let (i, _) = tag(")")(i)?;
359    let mut res = Vec::new();
360    for (i, n) in ns.iter().enumerate() {
361      res.push((u, n.to_owned(), typ.clone().shift(i as i64, Some(0))))
362    }
363    Ok((i, res))
364  }
365}
366
367/// Parse the short form of a binder, which is only a type
368pub fn parse_binder_short(
369  input: Cid,
370  defs: Rc<RefCell<Defs>>,
371  rec: Option<Name>,
372  ctx: Ctx,
373  quasi: Rc<VecDeque<Term>>,
374  uses: Uses,
375) -> impl Fn(Span) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
376  move |i: Span| {
377    map(
378      parse_term(
379        input,
380        defs.clone(),
381        rec.clone(),
382        ctx.clone(),
383        quasi.to_owned(),
384      ),
385      |t| vec![(uses, Name::from("_"), t)],
386    )(i)
387  }
388}
389
390/// Parse a binder in either its long or short form
391pub fn parse_binder(
392  input: Cid,
393  defs: Rc<RefCell<Defs>>,
394  rec: Option<Name>,
395  ctx: Ctx,
396  quasi: Rc<VecDeque<Term>>,
397  nam_opt: bool,
398  uses: Uses,
399) -> impl Fn(Span) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
400  move |i: Span| {
401    if nam_opt {
402      alt((
403        parse_binder_full(
404          input,
405          defs.clone(),
406          rec.clone(),
407          ctx.clone(),
408          quasi.clone(),
409          uses,
410        ),
411        parse_binder_short(
412          input,
413          defs.to_owned(),
414          rec.clone(),
415          ctx.clone(),
416          quasi.to_owned(),
417          uses,
418        ),
419      ))(i)
420    }
421    else {
422      parse_binder_full(
423        input,
424        defs.to_owned(),
425        rec.clone(),
426        ctx.clone(),
427        quasi.to_owned(),
428        uses,
429      )(i)
430    }
431  }
432}
433
434/// Parse zero or more binders
435pub fn parse_binders(
436  input: Cid,
437  defs: Rc<RefCell<Defs>>,
438  rec: Option<Name>,
439  ctx: Ctx,
440  quasi: Rc<VecDeque<Term>>,
441  nam_opt: bool,
442  terminator: Vec<char>,
443  uses: Uses,
444) -> impl FnMut(Span) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>>
445{
446  move |mut i: Span| {
447    let mut ctx = ctx.clone();
448    let mut res = Vec::new();
449
450    loop {
451      match preceded(parse_space, peek(satisfy(|x| terminator.contains(&x))))(i)
452      {
453        Ok((i2, _)) => return Ok((i2, res)),
454        _ => {}
455      }
456      match preceded(
457        parse_space,
458        parse_binder(
459          input,
460          defs.to_owned(),
461          rec.clone(),
462          ctx.clone(),
463          quasi.to_owned(),
464          nam_opt,
465          uses,
466        ),
467      )(i)
468      {
469        Err(e) => return Err(e),
470        Ok((i2, bs)) => {
471          for (u, n, t) in bs {
472            ctx = ctx.cons(n.to_owned());
473            res.push((u, n, t));
474          }
475          i = i2;
476        }
477      }
478    }
479  }
480}
481
482/// Parse one or more binders
483pub fn parse_binders1(
484  input: Cid,
485  defs: Rc<RefCell<Defs>>,
486  rec: Option<Name>,
487  ctx: Ctx,
488  quasi: Rc<VecDeque<Term>>,
489  nam_opt: bool,
490  terminator: Vec<char>,
491  uses: Uses,
492) -> impl FnMut(Span) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>>
493{
494  move |mut i: Span| {
495    let mut ctx = ctx.clone();
496    let mut res = Vec::new();
497
498    match parse_binder(
499      input,
500      defs.to_owned(),
501      rec.clone(),
502      ctx.clone(),
503      quasi.to_owned(),
504      nam_opt,
505      uses,
506    )(i.to_owned())
507    {
508      Err(e) => return Err(e),
509      Ok((i1, bs)) => {
510        for (u, n, t) in bs {
511          ctx = ctx.cons(n.to_owned());
512          res.push((u, n, t));
513        }
514        i = i1;
515      }
516    }
517    let (i, mut res2) = parse_binders(
518      input,
519      defs.to_owned(),
520      rec.clone(),
521      ctx.clone(),
522      quasi.to_owned(),
523      nam_opt,
524      terminator.clone(),
525      uses,
526    )(i)?;
527    res.append(&mut res2);
528    Ok((i, res))
529  }
530}
531
532/// Parses a forall (∀)
533pub fn parse_all(
534  input: Cid,
535  defs: Rc<RefCell<Defs>>,
536  rec: Option<Name>,
537  ctx: Ctx,
538  quasi: Rc<VecDeque<Term>>,
539) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
540  move |from: Span| {
541    let (i, _) = alt((tag("∀"), tag("forall")))(from)?;
542    let (i, _) = parse_space(i)?;
543    let (i, bs) = parse_binders1(
544      input,
545      defs.clone(),
546      rec.clone(),
547      ctx.clone(),
548      quasi.clone(),
549      true,
550      vec!['-'],
551      Uses::Many,
552    )(i)?;
553    let (i, _) = tag("->")(i)?;
554    let (i, _) = parse_space(i)?;
555    let mut ctx2 = ctx.clone();
556    for (_, n, _) in bs.iter() {
557      ctx2 = ctx2.cons(n.clone());
558    }
559    let (upto, bod) = parse_expression(
560      input,
561      defs.to_owned(),
562      rec.clone(),
563      ctx2,
564      quasi.to_owned(),
565    )(i)?;
566    let pos = Pos::from_upto(input, from, upto);
567    let trm = bs
568      .into_iter()
569      .rev()
570      .fold(bod, |acc, (u, n, t)| Term::All(pos, u, n, Box::new((t, acc))));
571    Ok((upto, trm))
572  }
573}
574
575/// Parses a Typ (type of types) term
576pub fn parse_type(
577  input: Cid,
578) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
579  move |from: Span| {
580    let (upto, _) = tag("Type")(from)?;
581    let pos = Pos::from_upto(input, from, upto);
582    Ok((upto, Term::Typ(pos)))
583  }
584}
585
586/// Parses a self type
587pub fn parse_self(
588  input: Cid,
589  defs: Rc<RefCell<Defs>>,
590  rec: Option<Name>,
591  ctx: Ctx,
592  quasi: Rc<VecDeque<Term>>,
593) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
594  move |from: Span| {
595    let (i, _) = nom::character::complete::char('@')(from)?;
596    let (i, n) = parse_name(i)?;
597    let (i, _) = parse_space(i)?;
598    let mut ctx2 = ctx.clone();
599    ctx2 = ctx2.cons(n.clone());
600    let (upto, bod) = parse_expression(
601      input,
602      defs.to_owned(),
603      rec.clone(),
604      ctx2.clone(),
605      quasi.to_owned(),
606    )(i)?;
607    let pos = Pos::from_upto(input, from, upto);
608    Ok((upto, Term::Slf(pos, n, Box::new(bod))))
609  }
610}
611
612/// Parses a self type destructor
613pub fn parse_case(
614  input: Cid,
615  defs: Rc<RefCell<Defs>>,
616  rec: Option<Name>,
617  ctx: Ctx,
618  quasi: Rc<VecDeque<Term>>,
619) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
620  move |from: Span| {
621    let (i, _) = tag("case")(from)?;
622    let (i, _) = parse_space(i)?;
623    let (upto, bod) = parse_expression(
624      input,
625      defs.to_owned(),
626      rec.clone(),
627      ctx.clone(),
628      quasi.to_owned(),
629    )(i)?;
630    let pos = Pos::from_upto(input, from, upto);
631    Ok((upto, Term::Cse(pos, Box::new(bod))))
632  }
633}
634
635/// Parses a self type constructor
636pub fn parse_data(
637  input: Cid,
638  defs: Rc<RefCell<Defs>>,
639  rec: Option<Name>,
640  ctx: Ctx,
641  quasi: Rc<VecDeque<Term>>,
642) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
643  move |from: Span| {
644    let (i, _) = tag("data")(from)?;
645    let (i, _) = parse_space(i)?;
646    let (upto, bod) = parse_expression(
647      input,
648      defs.to_owned(),
649      rec.clone(),
650      ctx.clone(),
651      quasi.to_owned(),
652    )(i)?;
653    let pos = Pos::from_upto(input, from, upto);
654    Ok((upto, Term::Dat(pos, Box::new(bod))))
655  }
656}
657
658/// The input `(A: Type) (x: A) : A = x` returns:
659///   - type: `∀ (A: Type) (x: A) -> A`
660///   - term: `λ A x => x`
661/// This is useful for parsing lets and defs
662pub fn parse_bound_expression(
663  input: Cid,
664  defs: Rc<RefCell<Defs>>,
665  type_rec: Option<Name>,
666  term_rec: Option<Name>,
667  ctx: Ctx,
668  quasi: Rc<VecDeque<Term>>,
669  nam: Name,
670  letrec: bool,
671) -> impl Fn(Span) -> IResult<Span, (Term, Term), ParseError<Span>> {
672  move |from: Span| {
673    let (i, bs) = parse_binders(
674      input,
675      defs.clone(),
676      type_rec.clone(),
677      ctx.clone(),
678      quasi.clone(),
679      false,
680      vec![':'],
681      Uses::Many,
682    )(from)?;
683    let (i, _) = tag(":")(i)?;
684    let (i, _) = parse_space(i)?;
685    let mut type_ctx = ctx.clone();
686    for (_, n, _) in bs.iter() {
687      type_ctx = type_ctx.cons(n.clone());
688    }
689    let (i, typ) = parse_expression(
690      input,
691      defs.clone(),
692      type_rec.clone(),
693      type_ctx,
694      quasi.clone(),
695    )(i)?;
696    let mut term_ctx = ctx.clone();
697    if letrec {
698      term_ctx = term_ctx.cons(nam.clone());
699    };
700    for (_, n, _) in bs.iter() {
701      term_ctx = term_ctx.cons(n.clone());
702    }
703    let (i, _) = parse_space(i)?;
704    let (i, _) = tag("=")(i)?;
705    let (i, _) = parse_space(i)?;
706    let (upto, trm) = parse_expression(
707      input,
708      defs.clone(),
709      term_rec.clone(),
710      term_ctx,
711      quasi.clone(),
712    )(i)?;
713    let pos = Pos::from_upto(input, from, upto);
714    let trm = bs
715      .iter()
716      .rev()
717      .fold(trm, |acc, (_, n, _)| Term::Lam(pos, n.clone(), Box::new(acc)));
718    let typ = bs
719      .into_iter()
720      .rev()
721      .fold(typ, |acc, (u, n, t)| Term::All(pos, u, n, Box::new((t, acc))));
722    Ok((upto, (typ, trm)))
723  }
724}
725
726/// Parses a local function definition
727pub fn parse_let(
728  input: Cid,
729  defs: Rc<RefCell<Defs>>,
730  rec: Option<Name>,
731  ctx: Ctx,
732  quasi: Rc<VecDeque<Term>>,
733) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
734  move |from: Span| {
735    let (i, letrec) =
736      alt((value(true, tag("letrec")), value(false, tag("let"))))(from)?;
737    let (i, _) = parse_space(i)?;
738    let (i, uses) = parse_uses(Uses::Many)(i)?;
739    let (i, _) = parse_space(i)?;
740    let (i, nam) = parse_name(i)?;
741    let (i, _) = parse_space(i)?;
742    let (i, (typ, exp)) = parse_bound_expression(
743      input,
744      defs.clone(),
745      rec.clone(),
746      rec.clone(),
747      ctx.clone(),
748      quasi.clone(),
749      nam.clone(),
750      letrec,
751    )(i)?;
752    let (i, _) = alt((tag(";"), tag("in")))(i)?;
753    let (i, _) = parse_space(i)?;
754    let mut ctx2 = ctx.clone();
755    ctx2 = ctx2.cons(nam.clone());
756    let (upto, bod) = parse_expression(
757      input,
758      defs.to_owned(),
759      rec.clone(),
760      ctx2,
761      quasi.to_owned(),
762    )(i)?;
763    let pos = Pos::from_upto(input, from, upto);
764    Ok((upto, Term::Let(pos, letrec, uses, nam, Box::new((typ, exp, bod)))))
765  }
766}
767
768/// Parses a syntactical character
769pub fn parse_builtin_symbol_end()
770-> impl Fn(Span) -> IResult<Span, (), ParseError<Span>> {
771  move |from: Span| {
772    alt((
773      peek(value((), parse_space1)),
774      peek(value((), eof)),
775      peek(value((), tag("("))),
776      peek(value((), tag(")"))),
777      peek(value((), tag("{"))),
778      peek(value((), tag("}"))),
779      peek(value((), tag(";"))),
780      peek(value((), tag(":"))),
781      peek(value((), tag(","))),
782    ))(from)
783  }
784}
785
786/// Parses a literal type
787pub fn parse_lty(
788  input: Cid,
789) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
790  move |from: Span| {
791    let (i, lty) = alt((
792      value(LitType::Nat, tag("#Nat")),
793      value(LitType::Int, tag("#Int")),
794      value(LitType::Bits, tag("#Bits")),
795      value(LitType::Bytes, tag("#Bytes")),
796      value(LitType::Bool, tag("#Bool")),
797      value(LitType::Text, tag("#Text")),
798      value(LitType::Char, tag("#Char")),
799      value(LitType::U8, tag("#U8")),
800      value(LitType::U16, tag("#U16")),
801      value(LitType::U32, tag("#U32")),
802      value(LitType::U64, tag("#U64")),
803      value(LitType::U128, tag("#U128")),
804      value(LitType::I8, tag("#I8")),
805      value(LitType::I16, tag("#I16")),
806      value(LitType::I32, tag("#I32")),
807      value(LitType::I64, tag("#I64")),
808      value(LitType::I128, tag("#I128")),
809    ))(from)?;
810    let (upto, _) = throw_err(parse_builtin_symbol_end()(i), |_| {
811      ParseError::new(
812        i,
813        ParseErrorKind::LitTypeLacksWhitespaceTermination(lty.to_owned()),
814      )
815    })?;
816    let pos = Pos::from_upto(input, from, upto);
817    Ok((upto, Term::LTy(pos, lty)))
818  }
819}
820// pub fn parse_exception()
821//-> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
822//  move |from: Span| {
823//    let (i, _) = tag("#!")(from)?;
824//    let p = |i| hashexpr::string::parse_string("\"", i);
825//    let (upto, val) = delimited(tag("\""), p, tag("\""))(i)
826//      .map_err(|e| error::convert(i, e))?;
827//    let pos = Some(Pos::from_upto(input,from, upto));
828//    Ok((upto, Term::Lit(pos, Literal::Exception(val))))
829//  }
830//}
831
832/// Parses a literal
833pub fn parse_lit(
834  input: Cid,
835) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
836  move |from: Span| {
837    let (i, lit) = alt((
838      parse_bits,
839      parse_bytes,
840      parse_bool,
841      parse_text,
842      parse_char,
843      parse_int,
844      parse_nat,
845    ))(from)?;
846    let (upto, _) = throw_err(parse_builtin_symbol_end()(i), |_| {
847      ParseError::new(
848        i,
849        ParseErrorKind::LiteralLacksWhitespaceTermination(lit.to_owned()),
850      )
851    })?;
852    let pos = Pos::from_upto(input, from, upto);
853    Ok((upto, Term::Lit(pos, lit)))
854  }
855}
856
857/// Parse an expression which is an application sequence with a possible type
858/// annotation `f a b c :: F A B C`
859pub fn parse_expression(
860  input: Cid,
861  defs: Rc<RefCell<Defs>>,
862  rec: Option<Name>,
863  ctx: Ctx,
864  quasi: Rc<VecDeque<Term>>,
865) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
866  move |from: Span| {
867    let (i, trm) =
868      parse_apps(input, defs.clone(), rec.clone(), ctx.clone(), quasi.clone())(
869        from,
870      )?;
871    let (i, has_ann) = opt(tag("::"))(i)?;
872    if has_ann.is_some() {
873      let (i, typ) = context(
874        "type annotation",
875        parse_apps(
876          input,
877          defs.clone(),
878          rec.clone(),
879          ctx.clone(),
880          quasi.clone(),
881        ),
882      )(i)?;
883      let pos = Pos::from_upto(input, from, i);
884      Ok((i, Term::Ann(pos, Box::new((typ, trm)))))
885    }
886    else {
887      Ok((i, trm))
888    }
889  }
890}
891/// Parse the termination marker of an application sequence
892pub fn parse_app_end(i: Span) -> IResult<Span, (), ParseError<Span>> {
893  let (i, _) = alt((
894    peek(tag("def")),
895    peek(tag("type")),
896    peek(tag("::")),
897    peek(tag("=")),
898    peek(tag("->")),
899    peek(tag(";")),
900    peek(tag(")")),
901    peek(tag("{")),
902    peek(tag("}")),
903    peek(tag(",")),
904    peek(eof),
905  ))(i)?;
906  Ok((i, ()))
907}
908
909/// Parse an application sequence `f a b c`
910pub fn parse_apps(
911  input: Cid,
912  defs: Rc<RefCell<Defs>>,
913  rec: Option<Name>,
914  ctx: Ctx,
915  quasi: Rc<VecDeque<Term>>,
916) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
917  move |from: Span| {
918    let (i2, _) = parse_space(from)?;
919    let (i2, fun) =
920      parse_term(input, defs.clone(), rec.clone(), ctx.clone(), quasi.clone())(
921        i2,
922      )?;
923    let mut i = i2;
924    let mut args = Vec::new();
925    loop {
926      let (i2, _) = parse_space(i)?;
927      match parse_app_end(i2) {
928        Ok((..)) => {
929          let pos = Pos::from_upto(input, from, i2);
930          let trm = args
931            .into_iter()
932            .fold(fun, |acc, arg| Term::App(pos, Box::new((acc, arg))));
933          return Ok((i2, trm));
934        }
935        _ => {
936          let (i2, arg) = parse_term(
937            input,
938            defs.clone(),
939            rec.clone(),
940            ctx.clone(),
941            quasi.clone(),
942          )(i2)?;
943          args.push(arg);
944          i = i2
945        }
946      }
947    }
948  }
949}
950
951/// Parses each term variant
952pub fn parse_term(
953  input: Cid,
954  defs: Rc<RefCell<Defs>>,
955  rec: Option<Name>,
956  ctx: Ctx,
957  quasi: Rc<VecDeque<Term>>,
958) -> impl Fn(Span) -> IResult<Span, Term, ParseError<Span>> {
959  move |i: Span| {
960    context(
961      "term",
962      alt((
963        delimited(
964          preceded(tag("("), parse_space),
965          context(
966            "expression",
967            parse_expression(
968              input,
969              defs.clone(),
970              rec.clone(),
971              ctx.clone(),
972              quasi.clone(),
973            ),
974          ),
975          context(
976            "close parenthesis ')' of an expression",
977            preceded(parse_space, tag(")")),
978          ),
979        ),
980        parse_self(
981          input,
982          defs.clone(),
983          rec.clone(),
984          ctx.clone(),
985          quasi.clone(),
986        ),
987        parse_data(
988          input,
989          defs.clone(),
990          rec.clone(),
991          ctx.clone(),
992          quasi.clone(),
993        ),
994        parse_case(
995          input,
996          defs.clone(),
997          rec.clone(),
998          ctx.clone(),
999          quasi.clone(),
1000        ),
1001        parse_all(input, defs.clone(), rec.clone(), ctx.clone(), quasi.clone()),
1002        parse_lam(input, defs.clone(), rec.clone(), ctx.clone(), quasi.clone()),
1003        parse_let(input, defs.clone(), rec.clone(), ctx.clone(), quasi.clone()),
1004        parse_type(input),
1005        parse_lty(input),
1006        parse_opr(input),
1007        parse_lit(input),
1008        parse_antiquote(ctx.clone(), quasi.clone()),
1009        parse_var(input, defs.to_owned(), rec.clone(), ctx.clone()),
1010      )),
1011    )(i)
1012  }
1013}
1014
1015/// Generates a content id for an arbitrary string
1016pub fn input_cid(i: &str) -> Cid {
1017  Cid::new_v1(
1018    0x55,
1019    Code::Blake2b256.digest(
1020      DagCborCodec.encode(&i.to_owned()).unwrap().into_inner().as_ref(),
1021    ),
1022  )
1023}
1024
1025/// A convenient top-level parser with default arguments
1026pub fn parse(i: &str, defs: Defs) -> IResult<Span, Term, ParseError<Span>> {
1027  parse_expression(
1028    input_cid(i),
1029    Rc::new(RefCell::new(defs)),
1030    None,
1031    ConsList::new(),
1032    Rc::new(VecDeque::new()),
1033  )(Span::new(i))
1034}
1035
1036/// Parses a quasiquoted expression
1037pub fn parse_quasi(
1038  i: &str,
1039  defs: Rc<RefCell<Defs>>,
1040  quasi: Rc<VecDeque<Term>>,
1041) -> IResult<Span, Term, ParseError<Span>> {
1042  parse_expression(input_cid(i), defs, None, ConsList::new(), quasi)(Span::new(
1043    i,
1044  ))
1045}
1046
1047/// The quasiquotion macro, which allows direct use of Yatima syntax in a Rust
1048/// source file for making Yatima expressions. For example `yatima!("λ x => x")`
1049/// will return `Term::Lam(.., Name::from("x"), Term::Var(.., Name::from("x"),
1050/// 0)`.
1051///
1052/// Antiquotation can be used to directly pass in Rust expressions:
1053/// `yatima!("λ x => #$0", Term::Lit(Literal::U64( 2u64 - 1u64)))` is
1054/// identical to `yatima!("λ x => 1u64")`
1055#[macro_export]
1056macro_rules! yatima {
1057  ($i:literal) => {
1058    parse::term::parse($i, defs::Defs::new()).unwrap().1
1059  };
1060  ($i:literal, $($q: expr),*) => {{
1061    let mut quasi = Vec::new();
1062    $(quasi.push($q);)*
1063    parse::term::parse_quasi($i,
1064      sp_std::rc::Rc::new(sp_std::cell::RefCell::new(defs::Defs::new())),
1065      sp_std::rc::Rc::new(sp_std::collections::vec_deque::VecDeque::from(quasi)))
1066      .unwrap().1
1067  }}
1068}
1069
1070#[cfg(test)]
1071pub mod tests {
1072  use super::*;
1073  use crate::term::tests::test_defs;
1074
1075  #[test]
1076  fn test_parse_apps() {
1077    fn test(i: &str) -> IResult<Span, Term, ParseError<Span>> {
1078      parse_apps(
1079        input_cid(i),
1080        Rc::new(RefCell::new(Defs::new())),
1081        None,
1082        ConsList::new(),
1083        Rc::new(VecDeque::new()),
1084      )(Span::new(i))
1085    }
1086    let res = test("0d1");
1087    assert!(res.is_ok());
1088    let res = test("0d1 0d1");
1089    assert!(res.is_ok());
1090    let res = test("0d1 0d1 def");
1091    assert!(res.is_ok());
1092  }
1093
1094  #[test]
1095  fn test_parse_expression() {
1096    fn test(i: &str) -> IResult<Span, Term, ParseError<Span>> {
1097      parse_expression(
1098        input_cid(i),
1099        Rc::new(RefCell::new(Defs::new())),
1100        None,
1101        ConsList::new(),
1102        Rc::new(VecDeque::new()),
1103      )(Span::new(i))
1104    }
1105    let res = test("(Type :: Type)");
1106    assert!(res.is_ok());
1107    let res = test("(Type (Type Type)  )");
1108    assert!(res.is_ok());
1109    let res = test(
1110      "λ x c n => (c x (c x (c x (c x (c x (c x (c x (c x (c x (c x (c x x (c \
1111       x (c x (c x (c x n)))))))))))))))",
1112    );
1113    assert!(res.is_ok());
1114    let res = test("∀ Type -> Type");
1115    assert!(res.is_ok());
1116    let res = test("∀ (_ :Type) -> Type");
1117    assert!(res.is_ok());
1118  }
1119  #[test]
1120  fn test_parse_binder_full() {
1121    use crate::{
1122      defs,
1123      parse,
1124    };
1125    fn test(
1126      ctx: Vec<Name>,
1127      i: &str,
1128    ) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
1129      parse_binder_full(
1130        input_cid(i),
1131        Rc::new(RefCell::new(Defs::new())),
1132        None,
1133        ConsList::from(ctx),
1134        Rc::new(VecDeque::new()),
1135        Uses::Many,
1136      )(Span::new(i))
1137    }
1138    let res = test(vec![], "(a b c: Type)");
1139    assert!(res.is_ok());
1140    let res = res.unwrap().1;
1141    assert_eq!(res, vec![
1142      (Uses::Many, Name::from("a"), yatima!("Type")),
1143      (Uses::Many, Name::from("b"), yatima!("Type")),
1144      (Uses::Many, Name::from("c"), yatima!("Type"))
1145    ]);
1146    let res = test(vec![Name::from("A")], "(a b c: A)");
1147    assert!(res.is_ok());
1148    let res = res.unwrap().1;
1149    assert_eq!(res, vec![
1150      (Uses::Many, Name::from("a"), Term::Var(Pos::None, Name::from("A"), 0)),
1151      (Uses::Many, Name::from("b"), Term::Var(Pos::None, Name::from("A"), 1)),
1152      (Uses::Many, Name::from("c"), Term::Var(Pos::None, Name::from("A"), 2)),
1153    ]);
1154    let res = test(vec![Name::from("A")], "(a : ∀ (x: A) -> A)");
1155    assert!(res.is_ok());
1156    let res = res.unwrap().1;
1157    assert_eq!(res, vec![(
1158      Uses::Many,
1159      Name::from("a"),
1160      Term::All(
1161        Pos::None,
1162        Uses::Many,
1163        Name::from("x"),
1164        Box::new((
1165          Term::Var(Pos::None, Name::from("A"), 0),
1166          Term::Var(Pos::None, Name::from("A"), 1)
1167        ))
1168      )
1169    ),]);
1170    fn test_binders(
1171      ctx: Vec<Name>,
1172      i: &str,
1173    ) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
1174      parse_binders(
1175        input_cid(i),
1176        Rc::new(RefCell::new(Defs::new())),
1177        None,
1178        Ctx::from(ctx),
1179        Rc::new(VecDeque::new()),
1180        false,
1181        vec![':'],
1182        Uses::Many,
1183      )(Span::new(i))
1184    }
1185    let res1 = test(vec![Name::from("A")], "(a : ∀ (x: A) -> A)");
1186    let res2 = test_binders(vec![Name::from("A")], "(a : ∀ (x: A) -> A):");
1187    assert!(res1.is_ok() && res2.is_ok());
1188    let (res1, res2) = (res1.unwrap().1, res2.unwrap().1);
1189    assert_eq!(res1, res2);
1190    let res1 = test(vec![Name::from("A")], "(a b c: ∀ (x: A) -> A)");
1191    let res2 = test_binders(
1192      vec![Name::from("A")],
1193      "(a : ∀ (x: A) -> A)
1194       (b : ∀ (x: A) -> A)
1195       (c : ∀ (x: A) -> A)
1196    :",
1197    );
1198    assert!(res1.is_ok() && res2.is_ok());
1199    let (res1, res2) = (res1.unwrap().1, res2.unwrap().1);
1200    assert_eq!(res1, res2);
1201    let res1 =
1202      test(vec![Name::from("A")], "(a b c d e f g: ∀ (x y z w: A) -> A)");
1203    let res2 = test_binders(
1204      vec![Name::from("A")],
1205      "(a: ∀ (x y z w: A) -> A)
1206       (b: ∀ (x y z w: A) -> A)
1207       (c: ∀ (x y z w: A) -> A)
1208       (d: ∀ (x y z w: A) -> A)
1209       (e: ∀ (x y z w: A) -> A)
1210       (f: ∀ (x y z w: A) -> A)
1211       (g: ∀ (x y z w: A) -> A)
1212    :",
1213    );
1214    assert!(res1.is_ok() && res2.is_ok());
1215    let (res1, res2) = (res1.unwrap().1, res2.unwrap().1);
1216    assert_eq!(res1, res2)
1217  }
1218
1219  #[test]
1220  fn test_parse_alls() {
1221    fn test(i: &str) -> IResult<Span, Term, ParseError<Span>> {
1222      parse_all(
1223        input_cid(i),
1224        Rc::new(RefCell::new(Defs::new())),
1225        None,
1226        ConsList::new(),
1227        Rc::new(VecDeque::new()),
1228      )(Span::new(i))
1229    }
1230    let res = test("∀ (a b c: Type) -> Type");
1231    println!("res: {:?}", res);
1232    assert!(res.is_ok());
1233  }
1234
1235  #[test]
1236  fn test_parse_let() {
1237    fn test(i: &str) -> IResult<Span, Term, ParseError<Span>> {
1238      parse_let(
1239        input_cid(i),
1240        Rc::new(RefCell::new(Defs::new())),
1241        None,
1242        ConsList::new(),
1243        Rc::new(VecDeque::new()),
1244      )(Span::new(i))
1245    }
1246    let res = test("let 0 x: Type = Type; x");
1247    assert!(res.is_ok());
1248    let res = test("let 0 f (x: Unknown) = Type; x");
1249    println!("res: {:?}", res);
1250    match res.unwrap_err() {
1251      Err::Error(err) => {
1252        assert!(
1253          err.errors
1254            == vec![ParseErrorKind::UndefinedReference(
1255              Name::from("Unknown"),
1256              ConsList::new(),
1257            )]
1258        )
1259      }
1260      _ => {
1261        assert!(false)
1262      }
1263    }
1264  }
1265  #[test]
1266  fn test_parse_bound_expression() {
1267    fn test(
1268      type_rec: Option<Name>,
1269      term_rec: Option<Name>,
1270      i: &str,
1271    ) -> IResult<Span, (Term, Term), ParseError<Span>> {
1272      parse_bound_expression(
1273        input_cid(i),
1274        Rc::new(RefCell::new(Defs::new())),
1275        type_rec,
1276        term_rec,
1277        ConsList::new(),
1278        Rc::new(VecDeque::new()),
1279        Name::from("test"),
1280        false,
1281      )(Span::new(i))
1282    }
1283    let res = test(None, None, ": Type = Type");
1284    assert!(res.is_ok());
1285    let res = test(None, None, "(x: Type): Type = Type");
1286    assert!(res.is_ok());
1287    let res = test(None, None, "(x: Unknown): Type = Type");
1288    match res.unwrap_err() {
1289      Err::Error(err) => {
1290        // println!("err: {:?}", err);
1291        assert!(
1292          err.errors
1293            == vec![ParseErrorKind::UndefinedReference(
1294              Name::from("Unknown"),
1295              ConsList::new()
1296            )]
1297        );
1298      }
1299      _ => {
1300        assert!(false);
1301      }
1302    };
1303    let res = test(Some(Name::from("Test")), None, "(x: Test): Type = Type");
1304    assert!(res.is_ok());
1305    let res = test(Some(Name::from("Test")), None, "(x: Type): Type = Test");
1306    assert!(res.is_err());
1307    let res = test(None, Some(Name::from("Test")), "(x: Test): Type = Type");
1308    assert!(res.is_err());
1309    let res = test(None, Some(Name::from("Test")), "(x: Type): Type = Test");
1310    assert!(res.is_ok());
1311  }
1312  #[test]
1313  fn test_parse_binders1() {
1314    use Term::*;
1315    fn test(
1316      nam_opt: bool,
1317      i: &str,
1318    ) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
1319      parse_binders(
1320        input_cid(i),
1321        Rc::new(RefCell::new(Defs::new())),
1322        None,
1323        ConsList::new(),
1324        Rc::new(VecDeque::new()),
1325        nam_opt,
1326        vec![':'],
1327        Uses::Many,
1328      )(Span::new(i))
1329    }
1330    let res = test(true, "Type #Text:");
1331    assert!(res.is_ok());
1332    assert!(
1333      res.unwrap().1
1334        == vec![
1335          (Uses::Many, Name::from("_"), Typ(Pos::None)),
1336          (Uses::Many, Name::from("_"), LTy(Pos::None, LitType::Text)),
1337        ]
1338    );
1339  }
1340
1341  #[test]
1342  fn test_parse_binders() {
1343    use Term::*;
1344    fn test(
1345      nam_opt: bool,
1346      i: &str,
1347    ) -> IResult<Span, Vec<(Uses, Name, Term)>, ParseError<Span>> {
1348      parse_binders(
1349        input_cid(i),
1350        Rc::new(RefCell::new(Defs::new())),
1351        None,
1352        ConsList::new(),
1353        Rc::new(VecDeque::new()),
1354        nam_opt,
1355        vec![':'],
1356        Uses::Many,
1357      )(Span::new(i))
1358    }
1359    let res = test(true, ":");
1360    assert!(res.is_ok());
1361    let res = test(true, "Type Type:");
1362    assert!(res.is_ok());
1363    assert!(
1364      res.unwrap().1
1365        == vec![
1366          (Uses::Many, Name::from("_"), Typ(Pos::None)),
1367          (Uses::Many, Name::from("_"), Typ(Pos::None)),
1368        ]
1369    );
1370    let res = test(true, "(A: Type) (a b c: A):");
1371    assert!(res.is_ok());
1372    assert!(
1373      res.unwrap().1
1374        == vec![
1375          (Uses::Many, Name::from("A"), Typ(Pos::None)),
1376          (Uses::Many, Name::from("a"), Var(Pos::None, Name::from("A"), 0)),
1377          (Uses::Many, Name::from("b"), Var(Pos::None, Name::from("A"), 1)),
1378          (Uses::Many, Name::from("c"), Var(Pos::None, Name::from("A"), 2)),
1379        ]
1380    );
1381    let res = test(true, "(A: Type) (a b c: Unknown):");
1382    assert!(res.is_err());
1383    match res.unwrap_err() {
1384      Err::Error(err) => {
1385        assert!(
1386          err.errors
1387            == vec![ParseErrorKind::UndefinedReference(
1388              Name::from("Unknown"),
1389              ConsList::from(vec!(Name::from("A")))
1390            )]
1391        )
1392      }
1393      _ => {
1394        assert!(false)
1395      }
1396    }
1397    let res = test(false, "(x: Unknown):");
1398    assert!(res.is_err());
1399    match res.unwrap_err() {
1400      Err::Error(err) => {
1401        assert!(
1402          err.errors
1403            == vec![ParseErrorKind::UndefinedReference(
1404              Name::from("Unknown"),
1405              ConsList::new(),
1406            )]
1407        );
1408      }
1409      _ => {
1410        assert!(false)
1411      }
1412    }
1413  }
1414
1415  #[quickcheck]
1416  fn term_parse_print(x: Term) -> bool {
1417    let i = format!("{}", x);
1418    match parse_expression(
1419      input_cid(&i),
1420      Rc::new(RefCell::new(test_defs())),
1421      None,
1422      ConsList::new(),
1423      Rc::new(VecDeque::new()),
1424    )(Span::new(&i))
1425    {
1426      Ok((_, y)) => x == y,
1427      Err(e) => {
1428        println!("{}", x);
1429        println!("{}", e);
1430        false
1431      }
1432    }
1433  }
1434}