diff options
-rw-r--r-- | dhall/build.rs | 23 | ||||
-rw-r--r-- | dhall/src/phase/binary.rs | 10 | ||||
-rw-r--r-- | dhall/src/phase/normalize.rs | 1 | ||||
-rw-r--r-- | dhall/src/phase/typecheck.rs | 1 | ||||
-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 |
8 files changed, 42 insertions, 35 deletions
diff --git a/dhall/build.rs b/dhall/build.rs index 337480f..a0106de 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -125,12 +125,6 @@ fn main() -> std::io::Result<()> { || path == "largeExpression" // Pretty sure the test is incorrect || path == "unit/import/urls/quotedPathFakeUrlEncode" - // TODO: projection by expression - || path == "recordProjectionByExpression" - || path == "RecordProjectionByType" - || path == "unit/RecordProjectionByType" - || path == "unit/RecordProjectionByTypeEmpty" - || path == "unit/RecordProjectFields" // TODO: RFC3986 URLs || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" @@ -163,11 +157,6 @@ fn main() -> std::io::Result<()> { false // Too slow in debug mode || path == "largeExpression" - // TODO: projection by expression - || path == "recordProjectionByExpression" - || path == "RecordProjectionByType" - || path == "unit/RecordProjectionByType" - || path == "unit/RecordProjectionByTypeEmpty" // TODO: RFC3986 URLs || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" @@ -194,11 +183,6 @@ fn main() -> std::io::Result<()> { || path == "double" || path == "unit/DoubleLitExponentNoDot" || path == "unit/DoubleLitSecretelyInt" - // TODO: projection by expression - || path == "recordProjectionByExpression" - || path == "RecordProjectionByType" - || path == "unit/RecordProjectionByType" - || path == "unit/RecordProjectionByTypeEmpty" // TODO: RFC3986 URLs || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" @@ -215,12 +199,7 @@ fn main() -> std::io::Result<()> { module_name: "binary_decoding_success", directory: spec_tests_dir.join("binary-decode/success/"), variant: "BinaryDecodingSuccess", - path_filter: |path: &str| { - false - // TODO: projection by expression - || path == "unit/RecordProjectFields" - || path == "unit/recordProjectionByExpression" - }, + path_filter: |_path: &str| false, input_type: FileType::Binary, output_type: Some(FileType::Text), }, diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs index b4f18da..464d71a 100644 --- a/dhall/src/phase/binary.rs +++ b/dhall/src/phase/binary.rs @@ -181,6 +181,15 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> { let l = Label::from(l.as_str()); Field(x, l) } + [U64(10), x, Array(arr)] => { + let x = cbor_value_to_dhall(&x)?; + if let [y] = arr.as_slice() { + let y = cbor_value_to_dhall(&y)?; + ProjectionByExpr(x, y) + } else { + Err(DecodeError::WrongFormatError("projection-by-expr".to_owned()))? + } + } [U64(10), x, rest @ ..] => { let x = cbor_value_to_dhall(&x)?; let labels = rest @@ -577,6 +586,7 @@ where .chain(once(expr(x))) .chain(ls.iter().map(label)), ), + ProjectionByExpr(x, y) => ser_seq!(ser; tag(10), expr(x), vec![expr(y)]), Import(import) => serialize_import(ser, import), Embed(_) => unimplemented!( "An expression with resolved imports cannot be binary-encoded" diff --git a/dhall/src/phase/normalize.rs b/dhall/src/phase/normalize.rs index 0992f74..ae1aefe 100644 --- a/dhall/src/phase/normalize.rs +++ b/dhall/src/phase/normalize.rs @@ -738,6 +738,7 @@ pub(crate) fn normalize_one_layer( } } } + ExprF::ProjectionByExpr(_, _) => unimplemented!("selection by expression"), ExprF::Merge(ref handlers, ref variant, _) => { let handlers_borrow = handlers.as_whnf(); diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index 33919e4..265a20e 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -787,6 +787,7 @@ fn type_last_layer( record_type.get_type()?, )) } + ProjectionByExpr(_, _) => unimplemented!("selection by expression"), }; Ok(match ret { 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, }; |