From 0169e9347ec7ffcf86066e1e5753ce5f77e71bc7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 10 Mar 2020 16:34:59 +0000 Subject: Add support for `with` keyword --- dhall/src/syntax/ast/span.rs | 1 + dhall/src/syntax/text/dhall.pest.visibility | 3 +++ dhall/src/syntax/text/parser.rs | 41 ++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'dhall/src/syntax') 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, 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 = { use Rule::*; @@ -759,6 +777,27 @@ impl DhallParser { Ok(()) } + #[alias(expression, shortcut = true)] + fn with_expression(input: ParseInput) -> ParseResult { + 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