summaryrefslogtreecommitdiff
path: root/dhall/src
diff options
context:
space:
mode:
authorNadrieril2020-03-10 16:34:59 +0000
committerNadrieril2020-03-10 16:35:53 +0000
commit0169e9347ec7ffcf86066e1e5753ce5f77e71bc7 (patch)
tree7d179c9300d7c46a1251bb0e819157107528e316 /dhall/src
parent3f9194f47185fe30c9e410aa7c5e651df9694b3f (diff)
Add support for `with` keyword
Diffstat (limited to 'dhall/src')
-rw-r--r--dhall/src/syntax/ast/span.rs1
-rw-r--r--dhall/src/syntax/text/dhall.pest.visibility3
-rw-r--r--dhall/src/syntax/text/parser.rs41
3 files changed, 44 insertions, 1 deletions
diff --git a/dhall/src/syntax/ast/span.rs b/dhall/src/syntax/ast/span.rs
index 7c004c5..50985e1 100644
--- a/dhall/src/syntax/ast/span.rs
+++ b/dhall/src/syntax/ast/span.rs
@@ -21,6 +21,7 @@ pub(crate) enum Span {
/// Desugarings
DuplicateRecordFieldsSugar,
DottedFieldSugar,
+ WithSugar,
/// For expressions obtained from decoding binary
Decoded,
/// For expressions constructed during normalization/typecheck
diff --git a/dhall/src/syntax/text/dhall.pest.visibility b/dhall/src/syntax/text/dhall.pest.visibility
index 03a000b..0ff1bfe 100644
--- a/dhall/src/syntax/text/dhall.pest.visibility
+++ b/dhall/src/syntax/text/dhall.pest.visibility
@@ -95,6 +95,7 @@ equivalent
prefer
lambda
forall
+# with
arrow
# complete
# exponent
@@ -164,6 +165,8 @@ times_expression
equal_expression
not_equal_expression
equivalent_expression
+with_expression
+with_clause
application_expression
first_application_expression
# import_expression
diff --git a/dhall/src/syntax/text/parser.rs b/dhall/src/syntax/text/parser.rs
index 7140332..f59cf06 100644
--- a/dhall/src/syntax/text/parser.rs
+++ b/dhall/src/syntax/text/parser.rs
@@ -2,6 +2,7 @@ use itertools::Itertools;
use pest::prec_climber as pcl;
use pest::prec_climber::PrecClimber;
use std::collections::BTreeMap;
+use std::iter::once;
use std::rc::Rc;
use pest_consume::{match_nodes, Parser};
@@ -144,6 +145,23 @@ fn insert_recordlit_entry(map: &mut BTreeMap<Label, Expr>, l: Label, e: Expr) {
}
}
+fn desugar_with_expr(x: Expr, labels: &[Label], y: Expr) -> Expr {
+ use crate::syntax::BinOp::RightBiasedRecordMerge;
+ let expr = |k| Expr::new(k, Span::WithSugar);
+ match labels {
+ [] => y,
+ [l, rest @ ..] => {
+ let res =
+ desugar_with_expr(expr(Field(x.clone(), l.clone())), rest, y);
+ expr(BinOp(
+ RightBiasedRecordMerge,
+ x,
+ expr(RecordLit(once((l.clone(), res)).collect())),
+ ))
+ }
+ }
+}
+
lazy_static::lazy_static! {
static ref PRECCLIMBER: PrecClimber<Rule> = {
use Rule::*;
@@ -760,6 +778,27 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
+ fn with_expression(input: ParseInput) -> ParseResult<Expr> {
+ Ok(match_nodes!(input.children();
+ [expression(e)] => e,
+ [expression(first), with_clause(clauses)..] => {
+ clauses.fold(
+ first,
+ |acc, (labels, e)| {
+ desugar_with_expr(acc, &labels, e)
+ }
+ )
+ },
+ ))
+ }
+
+ fn with_clause(input: ParseInput) -> ParseResult<(Vec<Label>, Expr)> {
+ Ok(match_nodes!(input.children();
+ [label(labels).., expression(e)] => (labels.collect(), e),
+ ))
+ }
+
+ #[alias(expression, shortcut = true)]
fn application_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => e,
@@ -919,7 +958,7 @@ impl DhallParser {
[label(first_name), label(names).., expression(expr)] => {
// Desugar dotted field syntax into nested records
let expr = names.rev().fold(expr, |e, l| {
- let map = Some((l, e)).into_iter().collect();
+ let map = once((l, e)).collect();
Expr::new(
RecordLit(map),
Span::DottedFieldSugar,