diff options
author | Nadrieril | 2019-03-23 23:24:11 +0100 |
---|---|---|
committer | Nadrieril | 2019-03-23 23:24:11 +0100 |
commit | 062fc44a93a18ee432e51db852290ab5849f4dd9 (patch) | |
tree | c9dd53daf9cd99f5dcf982e1d98099a078f63110 /dhall_core | |
parent | f610bc0aac5eaa365c95b489fb2d06cab449ec77 (diff) |
Handle merge and record projection
Diffstat (limited to 'dhall_core')
-rw-r--r-- | dhall_core/src/core.rs | 15 | ||||
-rw-r--r-- | dhall_core/src/parser.rs | 21 | ||||
-rw-r--r-- | dhall_core/src/printer.rs | 5 |
3 files changed, 32 insertions, 9 deletions
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index bc5a666..502a9bc 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -241,8 +241,10 @@ pub enum Expr<Note, Embed> { SubExpr<Note, Embed>, Option<SubExpr<Note, Embed>>, ), - /// `Field e x ~ e.x` + /// e.x Field(SubExpr<Note, Embed>, Label), + /// e.{ x, y, z } + Projection(SubExpr<Note, Embed>, Vec<Label>), /// Annotation on the AST. Unused for now but could hold e.g. file location information Note(Note, SubExpr<Note, Embed>), /// Embeds an import or the result of resolving the import @@ -353,9 +355,9 @@ where }; match e { Const(k) => Const(*k), - Var(V(x, n)) => Var(V(map_label(x), *n)), - Lam(x, t, b) => Lam(map_label(x), map(t), map_under_binder(x, b)), - Pi(x, t, b) => Pi(map_label(x), map(t), map_under_binder(x, b)), + Var(V(l, n)) => Var(V(map_label(l), *n)), + Lam(l, t, b) => Lam(map_label(l), map(t), map_under_binder(l, b)), + Pi(l, t, b) => Pi(map_label(l), map(t), map_under_binder(l, b)), App(f, args) => App(map(f), vec(args)), Let(l, t, a, b) => { Let(map_label(l), opt(t), map(a), map_under_binder(l, b)) @@ -378,7 +380,10 @@ where UnionType(kts) => UnionType(btmap(kts)), UnionLit(k, v, kvs) => UnionLit(map_label(k), map(v), btmap(kvs)), Merge(x, y, t) => Merge(map(x), map(y), opt(t)), - Field(r, x) => Field(map(r), map_label(x)), + Field(e, l) => Field(map(e), map_label(l)), + Projection(e, ls) => { + Projection(map(e), ls.iter().map(&map_label).collect()) + } Note(n, e) => Note(map_note(n), map(e)), Embed(a) => Embed(map_embed(a)), } diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index f959d2e..a62f861 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -19,6 +19,12 @@ pub type ParseError = pest::error::Error<Rule>; pub type ParseResult<T> = Result<T, ParseError>; +#[derive(Debug)] +enum Either<A, B> { + Left(A), + Right(B), +} + impl Builtin { pub fn parse(s: &str) -> Option<Self> { use self::Builtin::*; @@ -649,13 +655,20 @@ make_parser! { rule!(selector_expression<ParsedExpr> as expression; children!( [expression(e)] => e, [expression(first), selector(rest..)] => { - rest.fold(first, |acc, e| bx(Expr::Field(acc, e))) + rest.fold(first, |acc, e| match e { + Either::Left(l) => bx(Expr::Field(acc, l)), + Either::Right(ls) => bx(Expr::Projection(acc, ls)), + }) } )); - // TODO: handle record projection - rule!(selector<Label>; children!( - [label(l)] => l + rule!(selector<Either<Label, Vec<Label>>>; children!( + [label(l)] => Either::Left(l), + [labels(ls)] => Either::Right(ls), + )); + + rule!(labels<Vec<Label>>; children!( + [label(ls..)] => ls.collect(), )); rule!(literal_expression<ParsedExpr> as expression; children!( diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs index 5ecf5ce..d93336e 100644 --- a/dhall_core/src/printer.rs +++ b/dhall_core/src/printer.rs @@ -165,6 +165,11 @@ impl<S, A: Display> Expr<S, A> { a.fmt_e(f)?; write!(f, ".{}", b) } + &Projection(ref e, ref ls) => { + e.fmt_e(f)?; + write!(f, ".")?; + fmt_list("{ ", ", ", " }", ls, f, |l, f| write!(f, "{}", l)) + } &Note(_, ref b) => b.fmt_e(f), a => a.fmt_f(f), } |