diff options
Diffstat (limited to '')
-rw-r--r-- | dhall_syntax/src/core/expr.rs | 2 | ||||
-rw-r--r-- | dhall_syntax/src/core/visitor.rs | 5 | ||||
-rw-r--r-- | dhall_syntax/src/parser.rs | 27 | ||||
-rw-r--r-- | dhall_syntax/src/printer.rs | 8 |
4 files changed, 29 insertions, 13 deletions
diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 750b58b..131f97e 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -223,6 +223,8 @@ pub enum ExprF<SubExpr, Embed> { Field(SubExpr, Label), /// `e.{ x, y, z }` Projection(SubExpr, DupTreeSet<Label>), + /// `e.(t)` + ProjectionByExpr(SubExpr, SubExpr), /// `./some/path` Import(Import<SubExpr>), /// Embeds the result of resolving an import diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs index 39a027f..6189f26 100644 --- a/dhall_syntax/src/core/visitor.rs +++ b/dhall_syntax/src/core/visitor.rs @@ -161,6 +161,7 @@ where } Field(e, l) => Field(v.visit_subexpr(e)?, l.clone()), Projection(e, ls) => Projection(v.visit_subexpr(e)?, ls.clone()), + ProjectionByExpr(e, x) => ProjectionByExpr(v.visit_subexpr(e)?, v.visit_subexpr(x)?), Assert(e) => Assert(v.visit_subexpr(e)?), Import(i) => Import(i.traverse_ref(|e| v.visit_subexpr(e))?), Embed(a) => Embed(v.visit_embed(a)?), @@ -274,6 +275,10 @@ where } Field(e, _) => v.visit_subexpr(e)?, Projection(e, _) => v.visit_subexpr(e)?, + ProjectionByExpr(e, x) => { + v.visit_subexpr(e)?; + v.visit_subexpr(x)?; + } Assert(e) => v.visit_subexpr(e)?, Import(i) => i.traverse_mut(|e| v.visit_subexpr(e))?, Embed(a) => v.visit_embed(a)?, diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index eaded50..f5d161f 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -24,9 +24,10 @@ pub type ParseError = pest::error::Error<Rule>; pub type ParseResult<T> = Result<T, ParseError>; #[derive(Debug)] -enum Either<A, B> { - Left(A), - Right(B), +enum Selector<E> { + Field(Label), + Projection(DupTreeSet<Label>), + ProjectionByExpr(Expr<E>), } impl crate::Builtin { @@ -777,8 +778,9 @@ impl DhallParser { acc.span(), e.1, match e.0 { - Either::Left(l) => Field(acc, l), - Either::Right(ls) => Projection(acc, ls), + Selector::Field(l) => Field(acc, l), + Selector::Projection(ls) => Projection(acc, ls), + Selector::ProjectionByExpr(e) => ProjectionByExpr(acc, e) } ) } @@ -787,14 +789,15 @@ impl DhallParser { )) } - fn selector( + fn selector<E: Clone>( input: ParseInput, - ) -> ParseResult<(Either<Label, DupTreeSet<Label>>, Span)> { - Ok(match_nodes!(input.children(); - [label(l)] => (Either::Left(l), input_to_span(input)), - [labels(ls)] => (Either::Right(ls), input_to_span(input)), - // [expression(_e)] => unimplemented!("selection by expression"), // TODO - )) + ) -> ParseResult<(Selector<E>, Span)> { + let stor = match_nodes!(input.children(); + [label(l)] => Selector::Field(l), + [labels(ls)] => Selector::Projection(ls), + [expression(e)] => Selector::ProjectionByExpr(e), + ); + Ok((stor, input_to_span(input))) } fn labels(input: ParseInput) -> ParseResult<DupTreeSet<Label>> { diff --git a/dhall_syntax/src/printer.rs b/dhall_syntax/src/printer.rs index 19ec781..ce6ff97 100644 --- a/dhall_syntax/src/printer.rs +++ b/dhall_syntax/src/printer.rs @@ -66,6 +66,9 @@ impl<SE: Display + Clone, E: Display> Display for ExprF<SE, E> { write!(f, "{}.", e)?; fmt_list("{ ", ", ", " }", ls, f, Display::fmt)?; } + ProjectionByExpr(a, b) => { + write!(f, "{}.({})", a, b)?; + } Var(a) => a.fmt(f)?, Const(k) => k.fmt(f)?, Builtin(v) => v.fmt(f)?, @@ -159,7 +162,9 @@ impl<A: Display + Clone> RawExpr<A> { // Precedence is magically handled by the ordering of BinOps. ExprF::BinOp(op, _, _) if phase > PrintPhase::BinOp(*op) => true, ExprF::App(_, _) if phase > PrintPhase::App => true, - Field(_, _) | Projection(_, _) if phase > PrintPhase::Import => { + Field(_, _) | Projection(_, _) | ProjectionByExpr(_, _) + if phase > PrintPhase::Import => + { true } _ => false, @@ -196,6 +201,7 @@ impl<A: Display + Clone> RawExpr<A> { ), Field(a, b) => Field(a.phase(Primitive), b), Projection(e, ls) => Projection(e.phase(Primitive), ls), + ProjectionByExpr(a, b) => ProjectionByExpr(a.phase(Primitive), b), e => e, }; |