From 08e1d8ece4314b56d64fa08595c2e043b97896d1 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 6 Apr 2020 17:19:31 +0100 Subject: Split off operations from main expr enum --- dhall/src/semantics/builtins.rs | 28 ++--- dhall/src/semantics/nze/nir.rs | 46 +++++---- dhall/src/semantics/nze/normalize.rs | 182 +++++++++++++++++++-------------- dhall/src/semantics/resolve/resolve.rs | 21 ++-- dhall/src/semantics/tck/typecheck.rs | 35 ++++--- dhall/src/syntax/ast/expr.rs | 121 +++++++++++++++------- dhall/src/syntax/ast/visitor.rs | 100 ++++++------------ dhall/src/syntax/binary/decode.rs | 34 +++--- dhall/src/syntax/binary/encode.rs | 33 +++--- dhall/src/syntax/text/parser.rs | 36 ++++--- dhall/src/syntax/text/printer.rs | 141 ++++++++++++++----------- serde_dhall/src/value.rs | 13 +-- 12 files changed, 431 insertions(+), 359 deletions(-) diff --git a/dhall/src/semantics/builtins.rs b/dhall/src/semantics/builtins.rs index 6007a92..45be448 100644 --- a/dhall/src/semantics/builtins.rs +++ b/dhall/src/semantics/builtins.rs @@ -5,8 +5,8 @@ use crate::syntax::map::DupTreeMap; use crate::syntax::Const::Type; use crate::syntax::{ BinOp, Builtin, Const, Expr, ExprKind, InterpolatedText, - InterpolatedTextContents, Label, NaiveDouble, NumKind, Span, UnspannedExpr, - V, + InterpolatedTextContents, Label, NaiveDouble, NumKind, OpKind, Span, + UnspannedExpr, V, }; use std::collections::HashMap; use std::convert::TryInto; @@ -34,10 +34,10 @@ impl BuiltinClosure { HirKind::Expr(self.args.iter().fold( ExprKind::Builtin(self.b), |acc, v| { - ExprKind::App( + ExprKind::Op(OpKind::App( Hir::new(HirKind::Expr(acc), Span::Artificial), v.to_hir(venv), - ) + )) }, )) } @@ -59,16 +59,16 @@ macro_rules! make_type { rc(ExprKind::Var(V(stringify!($var).into(), 0))) }; (Optional $ty:ident) => { - rc(ExprKind::App( + rc(ExprKind::Op(OpKind::App( rc(ExprKind::Builtin(Builtin::Optional)), make_type!($ty) - )) + ))) }; (List $($rest:tt)*) => { - rc(ExprKind::App( + rc(ExprKind::Op(OpKind::App( rc(ExprKind::Builtin(Builtin::List)), make_type!($($rest)*) - )) + ))) }; ({ $($label:ident : $ty:ident),* }) => {{ let mut kts = DupTreeMap::new(); @@ -214,10 +214,10 @@ macro_rules! make_closure { }; (List $($ty:tt)*) => {{ let ty = make_closure!($($ty)*); - rc(ExprKind::App( + rc(ExprKind::Op(OpKind::App( rc(ExprKind::Builtin(Builtin::List)), ty - )) + ))) }}; (Some($($v:tt)*)) => { rc(ExprKind::SomeLit( @@ -225,20 +225,20 @@ macro_rules! make_closure { )) }; (1 + $($v:tt)*) => { - rc(ExprKind::BinOp( + rc(ExprKind::Op(OpKind::BinOp( BinOp::NaturalPlus, make_closure!($($v)*), rc(ExprKind::Num(NumKind::Natural(1))) - )) + ))) }; ([ $($head:tt)* ] # $($tail:tt)*) => {{ let head = make_closure!($($head)*); let tail = make_closure!($($tail)*); - rc(ExprKind::BinOp( + rc(ExprKind::Op(OpKind::BinOp( BinOp::ListAppend, rc(ExprKind::NEListLit(vec![head])), tail, - )) + ))) }}; } diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs index e0d227e..73c3f30 100644 --- a/dhall/src/semantics/nze/nir.rs +++ b/dhall/src/semantics/nze/nir.rs @@ -8,7 +8,7 @@ use crate::semantics::{ }; use crate::syntax::{ BinOp, Builtin, Const, Expr, ExprKind, InterpolatedTextContents, Label, - NumKind, Span, + NumKind, OpKind, Span, }; use crate::ToExprOptions; @@ -190,24 +190,24 @@ impl Nir { NirKind::Const(c) => ExprKind::Const(*c), NirKind::BuiltinType(b) => ExprKind::Builtin(*b), NirKind::Num(l) => ExprKind::Num(l.clone()), - NirKind::OptionalType(t) => ExprKind::App( + NirKind::OptionalType(t) => ExprKind::Op(OpKind::App( Nir::from_builtin(Builtin::Optional).to_hir(venv), t.to_hir(venv), - ), - NirKind::EmptyOptionalLit(n) => ExprKind::App( + )), + NirKind::EmptyOptionalLit(n) => ExprKind::Op(OpKind::App( Nir::from_builtin(Builtin::OptionalNone).to_hir(venv), n.to_hir(venv), - ), + )), NirKind::NEOptionalLit(n) => ExprKind::SomeLit(n.to_hir(venv)), - NirKind::ListType(t) => ExprKind::App( + NirKind::ListType(t) => ExprKind::Op(OpKind::App( Nir::from_builtin(Builtin::List).to_hir(venv), t.to_hir(venv), - ), + )), NirKind::EmptyListLit(n) => ExprKind::EmptyListLit(Hir::new( - HirKind::Expr(ExprKind::App( + HirKind::Expr(ExprKind::Op(OpKind::App( Nir::from_builtin(Builtin::List).to_hir(venv), n.to_hir(venv), - )), + ))), Span::Artificial, )), NirKind::NEListLit(elts) => ExprKind::NEListLit( @@ -229,31 +229,33 @@ impl Nir { .collect(), ), NirKind::UnionType(kts) => map_uniontype(kts), - NirKind::UnionConstructor(l, kts) => ExprKind::Field( - Hir::new( - HirKind::Expr(map_uniontype(kts)), - Span::Artificial, - ), - l.clone(), - ), - NirKind::UnionLit(l, v, kts) => ExprKind::App( + NirKind::UnionConstructor(l, kts) => { + ExprKind::Op(OpKind::Field( + Hir::new( + HirKind::Expr(map_uniontype(kts)), + Span::Artificial, + ), + l.clone(), + )) + } + NirKind::UnionLit(l, v, kts) => ExprKind::Op(OpKind::App( Hir::new( - HirKind::Expr(ExprKind::Field( + HirKind::Expr(ExprKind::Op(OpKind::Field( Hir::new( HirKind::Expr(map_uniontype(kts)), Span::Artificial, ), l.clone(), - )), + ))), Span::Artificial, ), v.to_hir(venv), - ), - NirKind::Equivalence(x, y) => ExprKind::BinOp( + )), + NirKind::Equivalence(x, y) => ExprKind::Op(OpKind::BinOp( BinOp::Equivalence, x.to_hir(venv), y.to_hir(venv), - ), + )), NirKind::PartialExpr(e) => e.map_ref(|v| v.to_hir(venv)), }), }; diff --git a/dhall/src/semantics/nze/normalize.rs b/dhall/src/semantics/nze/normalize.rs index 570e106..ebf4ae1 100644 --- a/dhall/src/semantics/nze/normalize.rs +++ b/dhall/src/semantics/nze/normalize.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use crate::semantics::NzEnv; use crate::semantics::{Binder, Closure, Hir, HirKind, Nir, NirKind, TextLit}; -use crate::syntax::{BinOp, ExprKind, InterpolatedTextContents, NumKind}; +use crate::syntax::{ + BinOp, ExprKind, InterpolatedTextContents, NumKind, OpKind, +}; pub fn apply_any(f: Nir, a: Nir) -> NirKind { match f.kind() { @@ -12,7 +14,7 @@ pub fn apply_any(f: Nir, a: Nir) -> NirKind { NirKind::UnionConstructor(l, kts) => { NirKind::UnionLit(l.clone(), a, kts.clone()) } - _ => NirKind::PartialExpr(ExprKind::App(f, a)), + _ => NirKind::PartialExpr(ExprKind::Op(OpKind::App(f, a))), } } @@ -173,11 +175,11 @@ fn apply_binop<'a>(o: BinOp, x: &'a Nir, y: &'a Nir) -> Option> { } (RecursiveRecordMerge, RecordLit(kvs1), RecordLit(kvs2)) => { let kvs = merge_maps(kvs1, kvs2, |_, v1, v2| { - Nir::from_partial_expr(ExprKind::BinOp( + Nir::from_partial_expr(ExprKind::Op(OpKind::BinOp( RecursiveRecordMerge, v1.clone(), v2.clone(), - )) + ))) }); Ret::NirKind(RecordLit(kvs)) } @@ -188,11 +190,11 @@ fn apply_binop<'a>(o: BinOp, x: &'a Nir, y: &'a Nir) -> Option> { kts_y, // If the Label exists for both records, then we hit the recursive case. |_, l: &Nir, r: &Nir| { - Nir::from_partial_expr(ExprKind::BinOp( + Nir::from_partial_expr(ExprKind::Op(OpKind::BinOp( RecursiveRecordTypeMerge, l.clone(), r.clone(), - )) + ))) }, ); Ret::NirKind(RecordType(kts)) @@ -216,7 +218,7 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { use NumKind::Bool; let ret = match expr { - ExprKind::Import(..) | ExprKind::Completion(..) => { + ExprKind::Import(..) | ExprKind::Op(OpKind::Completion(..)) => { unreachable!("This case should have been handled in resolution") } ExprKind::Var(..) @@ -230,7 +232,7 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { ExprKind::Const(c) => Ret::Nir(Nir::from_const(c)), ExprKind::Builtin(b) => Ret::Nir(Nir::from_builtin_env(b, env)), ExprKind::Assert(_) => Ret::Expr(expr), - ExprKind::App(v, a) => Ret::Nir(v.app(a)), + ExprKind::Op(OpKind::App(v, a)) => Ret::Nir(v.app(a)), ExprKind::Num(l) => Ret::NirKind(Num(l)), ExprKind::SomeLit(e) => Ret::NirKind(NEOptionalLit(e)), ExprKind::EmptyListLit(t) => { @@ -261,7 +263,7 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { Ret::NirKind(NirKind::TextLit(tlit)) } } - ExprKind::BoolIf(ref b, ref e1, ref e2) => { + ExprKind::Op(OpKind::BoolIf(ref b, ref e1, ref e2)) => { match b.kind() { Num(Bool(true)) => Ret::NirRef(e1), Num(Bool(false)) => Ret::NirRef(e2), @@ -275,12 +277,14 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { } } } - ExprKind::BinOp(o, ref x, ref y) => match apply_binop(o, x, y) { - Some(ret) => ret, - None => Ret::Expr(expr), - }, + ExprKind::Op(OpKind::BinOp(o, ref x, ref y)) => { + match apply_binop(o, x, y) { + Some(ret) => ret, + None => Ret::Expr(expr), + } + } - ExprKind::Field(ref v, ref field) => match v.kind() { + ExprKind::Op(OpKind::Field(ref v, ref field)) => match v.kind() { RecordLit(kvs) => match kvs.get(field) { Some(r) => Ret::Nir(r.clone()), None => Ret::Expr(expr), @@ -288,53 +292,65 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { UnionType(kts) => { Ret::NirKind(UnionConstructor(field.clone(), kts.clone())) } - PartialExpr(ExprKind::Projection(x, _)) => { + PartialExpr(ExprKind::Op(OpKind::Projection(x, _))) => { return normalize_one_layer( - ExprKind::Field(x.clone(), field.clone()), + ExprKind::Op(OpKind::Field(x.clone(), field.clone())), env, ) } - PartialExpr(ExprKind::BinOp( + PartialExpr(ExprKind::Op(OpKind::BinOp( BinOp::RightBiasedRecordMerge, x, y, - )) => match (x.kind(), y.kind()) { + ))) => match (x.kind(), y.kind()) { (_, RecordLit(kvs)) => match kvs.get(field) { Some(r) => Ret::Nir(r.clone()), None => { return normalize_one_layer( - ExprKind::Field(x.clone(), field.clone()), + ExprKind::Op(OpKind::Field( + x.clone(), + field.clone(), + )), env, ) } }, (RecordLit(kvs), _) => match kvs.get(field) { - Some(r) => Ret::Expr(ExprKind::Field( - Nir::from_kind(PartialExpr(ExprKind::BinOp( - BinOp::RightBiasedRecordMerge, - Nir::from_kind(RecordLit( - Some((field.clone(), r.clone())) - .into_iter() - .collect(), - )), - y.clone(), + Some(r) => Ret::Expr(ExprKind::Op(OpKind::Field( + Nir::from_kind(PartialExpr(ExprKind::Op( + OpKind::BinOp( + BinOp::RightBiasedRecordMerge, + Nir::from_kind(RecordLit( + Some((field.clone(), r.clone())) + .into_iter() + .collect(), + )), + y.clone(), + ), ))), field.clone(), - )), + ))), None => { return normalize_one_layer( - ExprKind::Field(y.clone(), field.clone()), + ExprKind::Op(OpKind::Field( + y.clone(), + field.clone(), + )), env, ) } }, _ => Ret::Expr(expr), }, - PartialExpr(ExprKind::BinOp(BinOp::RecursiveRecordMerge, x, y)) => { - match (x.kind(), y.kind()) { - (RecordLit(kvs), _) => match kvs.get(field) { - Some(r) => Ret::Expr(ExprKind::Field( - Nir::from_kind(PartialExpr(ExprKind::BinOp( + PartialExpr(ExprKind::Op(OpKind::BinOp( + BinOp::RecursiveRecordMerge, + x, + y, + ))) => match (x.kind(), y.kind()) { + (RecordLit(kvs), _) => match kvs.get(field) { + Some(r) => Ret::Expr(ExprKind::Op(OpKind::Field( + Nir::from_kind(PartialExpr(ExprKind::Op( + OpKind::BinOp( BinOp::RecursiveRecordMerge, Nir::from_kind(RecordLit( Some((field.clone(), r.clone())) @@ -342,19 +358,24 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { .collect(), )), y.clone(), - ))), - field.clone(), - )), - None => { - return normalize_one_layer( - ExprKind::Field(y.clone(), field.clone()), - env, - ) - } - }, - (_, RecordLit(kvs)) => match kvs.get(field) { - Some(r) => Ret::Expr(ExprKind::Field( - Nir::from_kind(PartialExpr(ExprKind::BinOp( + ), + ))), + field.clone(), + ))), + None => { + return normalize_one_layer( + ExprKind::Op(OpKind::Field( + y.clone(), + field.clone(), + )), + env, + ) + } + }, + (_, RecordLit(kvs)) => match kvs.get(field) { + Some(r) => Ret::Expr(ExprKind::Op(OpKind::Field( + Nir::from_kind(PartialExpr(ExprKind::Op( + OpKind::BinOp( BinOp::RecursiveRecordMerge, x.clone(), Nir::from_kind(RecordLit( @@ -362,52 +383,57 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { .into_iter() .collect(), )), - ))), - field.clone(), - )), - None => { - return normalize_one_layer( - ExprKind::Field(x.clone(), field.clone()), - env, - ) - } - }, - _ => Ret::Expr(expr), - } - } + ), + ))), + field.clone(), + ))), + None => { + return normalize_one_layer( + ExprKind::Op(OpKind::Field( + x.clone(), + field.clone(), + )), + env, + ) + } + }, + _ => Ret::Expr(expr), + }, _ => Ret::Expr(expr), }, - ExprKind::Projection(_, ref ls) if ls.is_empty() => { + ExprKind::Op(OpKind::Projection(_, ref ls)) if ls.is_empty() => { Ret::NirKind(RecordLit(HashMap::new())) } - ExprKind::Projection(ref v, ref ls) => match v.kind() { + ExprKind::Op(OpKind::Projection(ref v, ref ls)) => match v.kind() { RecordLit(kvs) => Ret::NirKind(RecordLit( ls.iter() .filter_map(|l| kvs.get(l).map(|x| (l.clone(), x.clone()))) .collect(), )), - PartialExpr(ExprKind::Projection(v2, _)) => { + PartialExpr(ExprKind::Op(OpKind::Projection(v2, _))) => { return normalize_one_layer( - ExprKind::Projection(v2.clone(), ls.clone()), + ExprKind::Op(OpKind::Projection(v2.clone(), ls.clone())), env, ) } _ => Ret::Expr(expr), }, - ExprKind::ProjectionByExpr(ref v, ref t) => match t.kind() { - RecordType(kts) => { - return normalize_one_layer( - ExprKind::Projection( - v.clone(), - kts.keys().cloned().collect(), - ), - env, - ) + ExprKind::Op(OpKind::ProjectionByExpr(ref v, ref t)) => { + match t.kind() { + RecordType(kts) => { + return normalize_one_layer( + ExprKind::Op(OpKind::Projection( + v.clone(), + kts.keys().cloned().collect(), + )), + env, + ) + } + _ => Ret::Expr(expr), } - _ => Ret::Expr(expr), - }, + } - ExprKind::Merge(ref handlers, ref variant, _) => { + ExprKind::Op(OpKind::Merge(ref handlers, ref variant, _)) => { match handlers.kind() { RecordLit(kvs) => match variant.kind() { UnionConstructor(l, _) => match kvs.get(l) { @@ -431,7 +457,7 @@ pub fn normalize_one_layer(expr: ExprKind, env: &NzEnv) -> NirKind { _ => Ret::Expr(expr), } } - ExprKind::ToMap(ref v, ref annot) => match v.kind() { + ExprKind::Op(OpKind::ToMap(ref v, ref annot)) => match v.kind() { RecordLit(kvs) if kvs.is_empty() => { match annot.as_ref().map(|v| v.kind()) { Some(NirKind::ListType(t)) => { diff --git a/dhall/src/semantics/resolve/resolve.rs b/dhall/src/semantics/resolve/resolve.rs index 6e50fa6..3e0022f 100644 --- a/dhall/src/semantics/resolve/resolve.rs +++ b/dhall/src/semantics/resolve/resolve.rs @@ -11,7 +11,7 @@ use crate::syntax; use crate::syntax::map::DupTreeMap; use crate::syntax::{ BinOp, Builtin, Expr, ExprKind, FilePath, FilePrefix, Hash, ImportMode, - ImportTarget, Span, UnspannedExpr, URL, + ImportTarget, OpKind, Span, UnspannedExpr, URL, }; use crate::{Parsed, Resolved}; @@ -179,12 +179,13 @@ impl ImportLocation { }; let asloc_ty = make_aslocation_uniontype(); - let expr = mkexpr(ExprKind::Field(asloc_ty, field_name.into())); + let expr = + mkexpr(ExprKind::Op(OpKind::Field(asloc_ty, field_name.into()))); match arg { - Some(arg) => mkexpr(ExprKind::App( + Some(arg) => mkexpr(ExprKind::Op(OpKind::App( expr, mkexpr(ExprKind::TextLit(arg.into())), - )), + ))), None => expr, } } @@ -261,21 +262,21 @@ fn resolve_one_import( /// Desugar the first level of the expression. fn desugar(expr: &Expr) -> Cow<'_, Expr> { match expr.kind() { - ExprKind::Completion(ty, compl) => { + ExprKind::Op(OpKind::Completion(ty, compl)) => { let ty_field_default = Expr::new( - ExprKind::Field(ty.clone(), "default".into()), + ExprKind::Op(OpKind::Field(ty.clone(), "default".into())), expr.span(), ); let merged = Expr::new( - ExprKind::BinOp( + ExprKind::Op(OpKind::BinOp( BinOp::RightBiasedRecordMerge, ty_field_default, compl.clone(), - ), + )), expr.span(), ); let ty_field_type = Expr::new( - ExprKind::Field(ty.clone(), "Type".into()), + ExprKind::Op(OpKind::Field(ty.clone(), "Type".into())), expr.span(), ); Cow::Owned(Expr::new( @@ -304,7 +305,7 @@ fn traverse_resolve_expr( .format(), )?, }, - ExprKind::BinOp(BinOp::ImportAlt, l, r) => { + ExprKind::Op(OpKind::BinOp(BinOp::ImportAlt, l, r)) => { match traverse_resolve_expr(name_env, l, f) { Ok(l) => l, Err(_) => { diff --git a/dhall/src/semantics/tck/typecheck.rs b/dhall/src/semantics/tck/typecheck.rs index c3334b5..8f3fcb2 100644 --- a/dhall/src/semantics/tck/typecheck.rs +++ b/dhall/src/semantics/tck/typecheck.rs @@ -9,7 +9,8 @@ use crate::semantics::{ Type, }; use crate::syntax::{ - BinOp, Builtin, Const, ExprKind, InterpolatedTextContents, NumKind, Span, + BinOp, Builtin, Const, ExprKind, InterpolatedTextContents, NumKind, OpKind, + Span, }; fn check_rectymerge( @@ -75,7 +76,7 @@ fn type_one_layer( let span_err = |msg: &str| mk_span_err(span.clone(), msg); let ty = match &ekind { - ExprKind::Import(..) | ExprKind::Completion(..) => { + ExprKind::Import(..) | ExprKind::Op(OpKind::Completion(..)) => { unreachable!("This case should have been handled in resolution") } ExprKind::Var(..) @@ -222,7 +223,7 @@ fn type_one_layer( Type::from_const(k) } - ExprKind::Field(scrut, x) => { + ExprKind::Op(OpKind::Field(scrut, x)) => { match scrut.ty().kind() { NirKind::RecordType(kts) => match kts.get(&x) { Some(val) => Type::new_infer_universe(env, val.clone())?, @@ -261,7 +262,7 @@ fn type_one_layer( } t } - ExprKind::App(f, arg) => { + ExprKind::Op(OpKind::App(f, arg)) => { match f.ty().kind() { // TODO: store Type in closure NirKind::PiClosure { annot, closure, .. } => { @@ -309,7 +310,7 @@ fn type_one_layer( ), } } - ExprKind::BoolIf(x, y, z) => { + ExprKind::Op(OpKind::BoolIf(x, y, z)) => { if *x.ty().kind() != NirKind::from_builtin(Builtin::Bool) { return span_err("InvalidPredicate"); } @@ -322,7 +323,7 @@ fn type_one_layer( y.ty().clone() } - ExprKind::BinOp(BinOp::RightBiasedRecordMerge, x, y) => { + ExprKind::Op(OpKind::BinOp(BinOp::RightBiasedRecordMerge, x, y)) => { let x_type = x.ty(); let y_type = y.ty(); @@ -344,22 +345,22 @@ fn type_one_layer( let u = max(x.ty().ty(), y.ty().ty()); Nir::from_kind(NirKind::RecordType(kts)).to_type(u) } - ExprKind::BinOp(BinOp::RecursiveRecordMerge, x, y) => { + ExprKind::Op(OpKind::BinOp(BinOp::RecursiveRecordMerge, x, y)) => { check_rectymerge(&span, env, x.ty().to_nir(), y.ty().to_nir())?; let hir = Hir::new( - HirKind::Expr(ExprKind::BinOp( + HirKind::Expr(ExprKind::Op(OpKind::BinOp( BinOp::RecursiveRecordTypeMerge, x.ty().to_hir(env.as_varenv()), y.ty().to_hir(env.as_varenv()), - )), + ))), span.clone(), ); let x_u = x.ty().ty(); let y_u = y.ty().ty(); Type::new(hir.eval(env), max(x_u, y_u)) } - ExprKind::BinOp(BinOp::RecursiveRecordTypeMerge, x, y) => { + ExprKind::Op(OpKind::BinOp(BinOp::RecursiveRecordTypeMerge, x, y)) => { check_rectymerge(&span, env, x.eval(env), y.eval(env))?; // A RecordType's type is always a const @@ -367,7 +368,7 @@ fn type_one_layer( let yk = y.ty().as_const().unwrap(); Type::from_const(max(xk, yk)) } - ExprKind::BinOp(BinOp::ListAppend, l, r) => { + ExprKind::Op(OpKind::BinOp(BinOp::ListAppend, l, r)) => { match l.ty().kind() { NirKind::ListType(..) => {} _ => return span_err("BinOpTypeMismatch"), @@ -379,7 +380,7 @@ fn type_one_layer( l.ty().clone() } - ExprKind::BinOp(BinOp::Equivalence, l, r) => { + ExprKind::Op(OpKind::BinOp(BinOp::Equivalence, l, r)) => { if l.ty() != r.ty() { return span_err("EquivalenceTypeMismatch"); } @@ -389,7 +390,7 @@ fn type_one_layer( Type::from_const(Const::Type) } - ExprKind::BinOp(o, l, r) => { + ExprKind::Op(OpKind::BinOp(o, l, r)) => { let t = Type::from_builtin(match o { BinOp::BoolAnd | BinOp::BoolOr @@ -415,7 +416,7 @@ fn type_one_layer( t } - ExprKind::Merge(record, union, type_annot) => { + ExprKind::Op(OpKind::Merge(record, union, type_annot)) => { let record_type = record.ty(); let handlers = match record_type.kind() { NirKind::RecordType(kts) => kts, @@ -554,7 +555,7 @@ fn type_one_layer( (None, None) => return span_err("MergeEmptyNeedsAnnotation"), } } - ExprKind::ToMap(record, annot) => { + ExprKind::Op(OpKind::ToMap(record, annot)) => { if record.ty().ty().as_const() != Some(Const::Type) { return span_err("`toMap` only accepts records of type `Type`"); } @@ -624,7 +625,7 @@ fn type_one_layer( output_type } } - ExprKind::Projection(record, labels) => { + ExprKind::Op(OpKind::Projection(record, labels)) => { let record_type = record.ty(); let kts = match record_type.kind() { NirKind::RecordType(kts) => kts, @@ -652,7 +653,7 @@ fn type_one_layer( Nir::from_kind(NirKind::RecordType(new_kts)), )? } - ExprKind::ProjectionByExpr(record, selection) => { + ExprKind::Op(OpKind::ProjectionByExpr(record, selection)) => { let record_type = record.ty(); let rec_kts = match record_type.kind() { NirKind::RecordType(kts) => kts, diff --git a/dhall/src/syntax/ast/expr.rs b/dhall/src/syntax/ast/expr.rs index 9e935dc..51426ce 100644 --- a/dhall/src/syntax/ast/expr.rs +++ b/dhall/src/syntax/ast/expr.rs @@ -126,63 +126,73 @@ pub enum NumKind { Double(Double), } +/// Operations +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum OpKind { + /// `f a` + App(SubExpr, SubExpr), + /// Binary operations + BinOp(BinOp, SubExpr, SubExpr), + /// `if x then y else z` + BoolIf(SubExpr, SubExpr, SubExpr), + /// `merge x y : t` + Merge(SubExpr, SubExpr, Option), + /// `toMap x : t` + ToMap(SubExpr, Option), + /// `e.x` + Field(SubExpr, Label), + /// `e.{ x, y, z }` + Projection(SubExpr, DupTreeSet