summaryrefslogtreecommitdiff
path: root/dhall_syntax
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dhall_syntax/src/core/expr.rs2
-rw-r--r--dhall_syntax/src/core/visitor.rs5
-rw-r--r--dhall_syntax/src/parser.rs27
-rw-r--r--dhall_syntax/src/printer.rs8
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,
};