diff options
Diffstat (limited to '')
-rw-r--r-- | dhall/src/semantics/resolve/resolve.rs | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/dhall/src/semantics/resolve/resolve.rs b/dhall/src/semantics/resolve/resolve.rs index 114bd9b..036e9a0 100644 --- a/dhall/src/semantics/resolve/resolve.rs +++ b/dhall/src/semantics/resolve/resolve.rs @@ -2,6 +2,7 @@ use itertools::Itertools; use std::borrow::Cow; use std::collections::BTreeMap; use std::env; +use std::iter::once; use std::path::PathBuf; use url::Url; @@ -12,8 +13,8 @@ use crate::operations::{BinOp, OpKind}; use crate::semantics::{mkerr, Cache, Hir, HirKind, ImportEnv, NameEnv, Type}; use crate::syntax; use crate::syntax::{ - Expr, ExprKind, FilePath, FilePrefix, Hash, ImportMode, ImportTarget, Span, - UnspannedExpr, URL, + Expr, ExprKind, FilePath, FilePrefix, Hash, ImportMode, ImportTarget, + Label, Span, UnspannedExpr, URL, }; use crate::{Parsed, Resolved}; @@ -276,6 +277,30 @@ fn resolve_one_import( }) } +/// Desugar a `with` expression. +fn desugar_with(x: Expr, path: &[Label], y: Expr, span: Span) -> Expr { + use crate::operations::BinOp::RightBiasedRecordMerge; + use ExprKind::{Op, RecordLit}; + use OpKind::{BinOp, Field}; + let expr = |k| Expr::new(k, span.clone()); + match path { + [] => y, + [l, rest @ ..] => { + let res = desugar_with( + expr(Op(Field(x.clone(), l.clone()))), + rest, + y, + span.clone(), + ); + expr(Op(BinOp( + RightBiasedRecordMerge, + x, + expr(RecordLit(once((l.clone(), res)).collect())), + ))) + } + } +} + /// Desugar the first level of the expression. fn desugar(expr: &Expr) -> Cow<'_, Expr> { match expr.kind() { @@ -301,6 +326,9 @@ fn desugar(expr: &Expr) -> Cow<'_, Expr> { expr.span(), )) } + ExprKind::Op(OpKind::With(x, path, y)) => { + Cow::Owned(desugar_with(x.clone(), path, y.clone(), expr.span())) + } _ => Cow::Borrowed(expr), } } |