summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/build.rs23
-rw-r--r--dhall/src/phase/binary.rs10
-rw-r--r--dhall/src/phase/normalize.rs1
-rw-r--r--dhall/src/phase/typecheck.rs1
-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
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,
};