diff options
Diffstat (limited to '')
-rw-r--r-- | dhall/src/semantics/builtins.rs | 105 | ||||
-rw-r--r-- | dhall/src/semantics/mod.rs | 8 | ||||
-rw-r--r-- | dhall/src/semantics/nze/env.rs | 6 | ||||
-rw-r--r-- | dhall/src/semantics/nze/mod.rs | 8 | ||||
-rw-r--r-- | dhall/src/semantics/nze/nir.rs | 140 | ||||
-rw-r--r-- | dhall/src/semantics/nze/normalize.rs | 100 | ||||
-rw-r--r-- | dhall/src/semantics/nze/var.rs | 4 | ||||
-rw-r--r-- | dhall/src/semantics/parse.rs | 10 | ||||
-rw-r--r-- | dhall/src/semantics/resolve/env.rs | 19 | ||||
-rw-r--r-- | dhall/src/semantics/resolve/hir.rs | 28 | ||||
-rw-r--r-- | dhall/src/semantics/resolve/mod.rs | 6 | ||||
-rw-r--r-- | dhall/src/semantics/resolve/resolve.rs | 20 | ||||
-rw-r--r-- | dhall/src/semantics/tck/env.rs | 8 | ||||
-rw-r--r-- | dhall/src/semantics/tck/mod.rs | 6 | ||||
-rw-r--r-- | dhall/src/semantics/tck/tir.rs | 13 | ||||
-rw-r--r-- | dhall/src/semantics/tck/typecheck.rs | 55 |
16 files changed, 217 insertions, 319 deletions
diff --git a/dhall/src/semantics/builtins.rs b/dhall/src/semantics/builtins.rs index 803630b..6007a92 100644 --- a/dhall/src/semantics/builtins.rs +++ b/dhall/src/semantics/builtins.rs @@ -1,48 +1,35 @@ use crate::semantics::{ - skip_resolve, typecheck, Hir, HirKind, Nir, NirKind, NzEnv, VarEnv, + skip_resolve_expr, typecheck, Hir, HirKind, Nir, NirKind, NzEnv, VarEnv, }; use crate::syntax::map::DupTreeMap; use crate::syntax::Const::Type; use crate::syntax::{ BinOp, Builtin, Const, Expr, ExprKind, InterpolatedText, - InterpolatedTextContents, Label, LitKind, NaiveDouble, Span, UnspannedExpr, + InterpolatedTextContents, Label, NaiveDouble, NumKind, Span, UnspannedExpr, V, }; -use crate::Normalized; use std::collections::HashMap; use std::convert::TryInto; /// A partially applied builtin. /// Invariant: the evaluation of the given args must not be able to progress further #[derive(Debug, Clone)] -pub(crate) struct BuiltinClosure<Nir> { - pub env: NzEnv, - pub b: Builtin, +pub struct BuiltinClosure { + env: NzEnv, + b: Builtin, /// Arguments applied to the closure so far. - pub args: Vec<Nir>, + args: Vec<Nir>, } -impl BuiltinClosure<Nir> { - pub fn new(b: Builtin, env: NzEnv) -> Self { - BuiltinClosure { - env, - b, - args: Vec::new(), - } +impl BuiltinClosure { + pub fn new(b: Builtin, env: NzEnv) -> NirKind { + apply_builtin(b, Vec::new(), env) } - pub fn apply(&self, a: Nir) -> NirKind { use std::iter::once; let args = self.args.iter().cloned().chain(once(a)).collect(); apply_builtin(self.b, args, self.env.clone()) } - /// This doesn't break the invariant because we already checked that the appropriate arguments - /// did not normalize to something that allows evaluation to proceed. - pub fn normalize(&self) { - for x in self.args.iter() { - x.normalize(); - } - } pub fn to_hirkind(&self, venv: VarEnv) -> HirKind { HirKind::Expr(self.args.iter().fold( ExprKind::Builtin(self.b), @@ -56,7 +43,7 @@ impl BuiltinClosure<Nir> { } } -pub(crate) fn rc(x: UnspannedExpr) -> Expr { +pub fn rc(x: UnspannedExpr) -> Expr { Expr::new(x, Span::Artificial) } @@ -116,7 +103,7 @@ macro_rules! make_type { }; } -pub(crate) fn type_of_builtin(b: Builtin) -> Hir { +pub fn type_of_builtin(b: Builtin) -> Hir { use Builtin::*; let expr = match b { Bool | Natural | Integer | Double | Text => make_type!(Type), @@ -202,7 +189,7 @@ pub(crate) fn type_of_builtin(b: Builtin) -> Hir { forall (A: Type) -> Optional A ), }; - skip_resolve(&expr).unwrap() + skip_resolve_expr(&expr).unwrap() } // Ad-hoc macro to help construct closures @@ -241,7 +228,7 @@ macro_rules! make_closure { rc(ExprKind::BinOp( BinOp::NaturalPlus, make_closure!($($v)*), - rc(ExprKind::Lit(LitKind::Natural(1))) + rc(ExprKind::Num(NumKind::Natural(1))) )) }; ([ $($head:tt)* ] # $($tail:tt)*) => {{ @@ -257,8 +244,8 @@ macro_rules! make_closure { #[allow(clippy::cognitive_complexity)] fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { - use LitKind::{Bool, Double, Integer, Natural}; use NirKind::*; + use NumKind::{Bool, Double, Integer, Natural}; // Small helper enum enum Ret { @@ -267,46 +254,54 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { DoneAsIs, } let make_closure = |e| { - typecheck(&skip_resolve(&e).unwrap()) + typecheck(&skip_resolve_expr(&e).unwrap()) .unwrap() .eval(env.clone()) }; let ret = match (b, args.as_slice()) { + (Builtin::Bool, []) + | (Builtin::Natural, []) + | (Builtin::Integer, []) + | (Builtin::Double, []) + | (Builtin::Text, []) => Ret::NirKind(BuiltinType(b)), + (Builtin::Optional, [t]) => Ret::NirKind(OptionalType(t.clone())), + (Builtin::List, [t]) => Ret::NirKind(ListType(t.clone())), + (Builtin::OptionalNone, [t]) => { Ret::NirKind(EmptyOptionalLit(t.clone())) } (Builtin::NaturalIsZero, [n]) => match &*n.kind() { - Lit(Natural(n)) => Ret::NirKind(Lit(Bool(*n == 0))), + Num(Natural(n)) => Ret::NirKind(Num(Bool(*n == 0))), _ => Ret::DoneAsIs, }, (Builtin::NaturalEven, [n]) => match &*n.kind() { - Lit(Natural(n)) => Ret::NirKind(Lit(Bool(*n % 2 == 0))), + Num(Natural(n)) => Ret::NirKind(Num(Bool(*n % 2 == 0))), _ => Ret::DoneAsIs, }, (Builtin::NaturalOdd, [n]) => match &*n.kind() { - Lit(Natural(n)) => Ret::NirKind(Lit(Bool(*n % 2 != 0))), + Num(Natural(n)) => Ret::NirKind(Num(Bool(*n % 2 != 0))), _ => Ret::DoneAsIs, }, (Builtin::NaturalToInteger, [n]) => match &*n.kind() { - Lit(Natural(n)) => Ret::NirKind(Lit(Integer(*n as isize))), + Num(Natural(n)) => Ret::NirKind(Num(Integer(*n as isize))), _ => Ret::DoneAsIs, }, (Builtin::NaturalShow, [n]) => match &*n.kind() { - Lit(Natural(n)) => Ret::Nir(Nir::from_text(n)), + Num(Natural(n)) => Ret::Nir(Nir::from_text(n)), _ => Ret::DoneAsIs, }, (Builtin::NaturalSubtract, [a, b]) => match (&*a.kind(), &*b.kind()) { - (Lit(Natural(a)), Lit(Natural(b))) => { - Ret::NirKind(Lit(Natural(if b > a { b - a } else { 0 }))) + (Num(Natural(a)), Num(Natural(b))) => { + Ret::NirKind(Num(Natural(if b > a { b - a } else { 0 }))) } - (Lit(Natural(0)), _) => Ret::Nir(b.clone()), - (_, Lit(Natural(0))) => Ret::NirKind(Lit(Natural(0))), - _ if a == b => Ret::NirKind(Lit(Natural(0))), + (Num(Natural(0)), _) => Ret::Nir(b.clone()), + (_, Num(Natural(0))) => Ret::NirKind(Num(Natural(0))), + _ if a == b => Ret::NirKind(Num(Natural(0))), _ => Ret::DoneAsIs, }, (Builtin::IntegerShow, [n]) => match &*n.kind() { - Lit(Integer(n)) => { + Num(Integer(n)) => { let s = if *n < 0 { n.to_string() } else { @@ -317,30 +312,30 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { _ => Ret::DoneAsIs, }, (Builtin::IntegerToDouble, [n]) => match &*n.kind() { - Lit(Integer(n)) => { - Ret::NirKind(Lit(Double(NaiveDouble::from(*n as f64)))) + Num(Integer(n)) => { + Ret::NirKind(Num(Double(NaiveDouble::from(*n as f64)))) } _ => Ret::DoneAsIs, }, (Builtin::IntegerNegate, [n]) => match &*n.kind() { - Lit(Integer(n)) => Ret::NirKind(Lit(Integer(-n))), + Num(Integer(n)) => Ret::NirKind(Num(Integer(-n))), _ => Ret::DoneAsIs, }, (Builtin::IntegerClamp, [n]) => match &*n.kind() { - Lit(Integer(n)) => { - Ret::NirKind(Lit(Natural((*n).try_into().unwrap_or(0)))) + Num(Integer(n)) => { + Ret::NirKind(Num(Natural((*n).try_into().unwrap_or(0)))) } _ => Ret::DoneAsIs, }, (Builtin::DoubleShow, [n]) => match &*n.kind() { - Lit(Double(n)) => Ret::Nir(Nir::from_text(n)), + Num(Double(n)) => Ret::Nir(Nir::from_text(n)), _ => Ret::DoneAsIs, }, (Builtin::TextShow, [v]) => match &*v.kind() { TextLit(tlit) => { if let Some(s) = tlit.as_text() { // Printing InterpolatedText takes care of all the escaping - let txt: InterpolatedText<Normalized> = + let txt: InterpolatedText<Expr> = std::iter::once(InterpolatedTextContents::Text(s)) .collect(); Ret::Nir(Nir::from_text(txt)) @@ -351,8 +346,8 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { _ => Ret::DoneAsIs, }, (Builtin::ListLength, [_, l]) => match &*l.kind() { - EmptyListLit(_) => Ret::NirKind(Lit(Natural(0))), - NEListLit(xs) => Ret::NirKind(Lit(Natural(xs.len()))), + EmptyListLit(_) => Ret::NirKind(Num(Natural(0))), + NEListLit(xs) => Ret::NirKind(Num(Natural(xs.len()))), _ => Ret::DoneAsIs, }, (Builtin::ListHead, [_, l]) => match &*l.kind() { @@ -398,7 +393,7 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { let mut kvs = HashMap::new(); kvs.insert( "index".into(), - Nir::from_kind(Lit(Natural(i))), + Nir::from_kind(Num(Natural(i))), ); kvs.insert("value".into(), e.clone()); Nir::from_kind(RecordLit(kvs)) @@ -466,14 +461,14 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { λ(x : Natural) -> 1 + var(x) ))) - .app(Lit(Natural(0)).into_nir()), + .app(Num(Natural(0)).into_nir()), ), (Builtin::NaturalFold, [n, t, succ, zero]) => match &*n.kind() { - Lit(Natural(0)) => Ret::Nir(zero.clone()), - Lit(Natural(n)) => { + Num(Natural(0)) => Ret::Nir(zero.clone()), + Num(Natural(n)) => { let fold = Nir::from_builtin(Builtin::NaturalFold) - .app(Lit(Natural(n - 1)).into_nir()) + .app(Num(Natural(n - 1)).into_nir()) .app(t.clone()) .app(succ.clone()) .app(zero.clone()); @@ -490,9 +485,9 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind { } } -impl<Nir: std::cmp::PartialEq> std::cmp::PartialEq for BuiltinClosure<Nir> { +impl std::cmp::PartialEq for BuiltinClosure { fn eq(&self, other: &Self) -> bool { self.b == other.b && self.args == other.args } } -impl<Nir: std::cmp::Eq> std::cmp::Eq for BuiltinClosure<Nir> {} +impl std::cmp::Eq for BuiltinClosure {} diff --git a/dhall/src/semantics/mod.rs b/dhall/src/semantics/mod.rs index 87033c9..468d8b1 100644 --- a/dhall/src/semantics/mod.rs +++ b/dhall/src/semantics/mod.rs @@ -3,7 +3,7 @@ pub mod nze; pub mod parse; pub mod resolve; pub mod tck; -pub(crate) use self::builtins::*; -pub(crate) use self::nze::*; -pub(crate) use self::resolve::*; -pub(crate) use self::tck::*; +pub use self::builtins::*; +pub use self::nze::*; +pub use self::resolve::*; +pub use self::tck::*; diff --git a/dhall/src/semantics/nze/env.rs b/dhall/src/semantics/nze/env.rs index ef2bee6..ec99dbe 100644 --- a/dhall/src/semantics/nze/env.rs +++ b/dhall/src/semantics/nze/env.rs @@ -1,7 +1,7 @@ use crate::semantics::{AlphaVar, Nir, NirKind}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) enum NzVar { +pub enum NzVar { /// Reverse-debruijn index: counts number of binders from the bottom of the stack. Bound(usize), /// Fake fresh variable generated for expression equality checking. @@ -17,11 +17,11 @@ enum EnvItem<Type> { } #[derive(Debug, Clone)] -pub(crate) struct ValEnv<Type> { +pub struct ValEnv<Type> { items: Vec<EnvItem<Type>>, } -pub(crate) type NzEnv = ValEnv<()>; +pub type NzEnv = ValEnv<()>; impl NzVar { pub fn new(idx: usize) -> Self { diff --git a/dhall/src/semantics/nze/mod.rs b/dhall/src/semantics/nze/mod.rs index 2648339..23022e0 100644 --- a/dhall/src/semantics/nze/mod.rs +++ b/dhall/src/semantics/nze/mod.rs @@ -3,7 +3,7 @@ pub mod lazy; pub mod nir; pub mod normalize; pub mod var; -pub(crate) use env::*; -pub(crate) use nir::*; -pub(crate) use normalize::*; -pub(crate) use var::*; +pub use env::*; +pub use nir::*; +pub use normalize::*; +pub use var::*; diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs index 32ef590..e0d227e 100644 --- a/dhall/src/semantics/nze/nir.rs +++ b/dhall/src/semantics/nze/nir.rs @@ -7,10 +7,10 @@ use crate::semantics::{ BuiltinClosure, Hir, HirKind, NzEnv, NzVar, TyEnv, Type, Universe, VarEnv, }; use crate::syntax::{ - BinOp, Builtin, Const, ExprKind, InterpolatedTextContents, Label, LitKind, - Span, + BinOp, Builtin, Const, Expr, ExprKind, InterpolatedTextContents, Label, + NumKind, Span, }; -use crate::{NormalizedExpr, ToExprOptions}; +use crate::ToExprOptions; /// Stores a possibly unevaluated value. Gets (partially) normalized on-demand, sharing computation /// automatically. Uses a Rc<RefCell> to share computation. @@ -19,7 +19,7 @@ use crate::{NormalizedExpr, ToExprOptions}; /// normalize as needed. /// Stands for "Normalized intermediate representation" #[derive(Clone)] -pub(crate) struct Nir(Rc<NirInternal>); +pub struct Nir(Rc<NirInternal>); #[derive(Debug)] struct NirInternal { @@ -28,7 +28,7 @@ struct NirInternal { /// An unevaluated subexpression #[derive(Debug, Clone)] -pub(crate) enum Thunk { +pub enum Thunk { /// A completely unnormalized expression. Thunk { env: NzEnv, body: Hir }, /// A partially normalized expression that may need to go through `normalize_one_layer`. @@ -37,7 +37,7 @@ pub(crate) enum Thunk { /// An unevaluated subexpression that takes an argument. #[derive(Debug, Clone)] -pub(crate) enum Closure { +pub enum Closure { /// Normal closure Closure { env: NzEnv, body: Hir }, /// Closure that ignores the argument passed @@ -48,7 +48,7 @@ pub(crate) enum Closure { // Invariant: this must not contain interpolations that are themselves TextLits, and contiguous // text values must be merged. #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct TextLit(Vec<InterpolatedTextContents<Nir>>); +pub struct TextLit(Vec<InterpolatedTextContents<Nir>>); /// This represents a value in Weak Head Normal Form (WHNF). This means that the value is /// normalized up to the first constructor, but subexpressions may not be fully normalized. @@ -58,7 +58,7 @@ pub(crate) struct TextLit(Vec<InterpolatedTextContents<Nir>>); /// In particular, this means that once we get a `NirKind`, it can be considered immutable, and /// we only need to recursively normalize its sub-`Nir`s to get to the NF. #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum NirKind { +pub enum NirKind { /// Closures LamClosure { binder: Binder, @@ -70,13 +70,17 @@ pub(crate) enum NirKind { annot: Nir, closure: Closure, }, - AppliedBuiltin(BuiltinClosure<Nir>), + AppliedBuiltin(BuiltinClosure), Var(NzVar), Const(Const), - Lit(LitKind), + // Must be a number type, Bool or Text + BuiltinType(Builtin), + Num(NumKind), + OptionalType(Nir), EmptyOptionalLit(Nir), NEOptionalLit(Nir), + ListType(Nir), // EmptyListLit(t) means `[] : List t`, not `[] : t` EmptyListLit(Nir), NEListLit(Vec<Nir>), @@ -93,34 +97,34 @@ pub(crate) enum NirKind { impl Nir { /// Construct a Nir from a completely unnormalized expression. - pub(crate) fn new_thunk(env: NzEnv, hir: Hir) -> Nir { + pub fn new_thunk(env: NzEnv, hir: Hir) -> Nir { NirInternal::from_thunk(Thunk::new(env, hir)).into_nir() } /// Construct a Nir from a partially normalized expression that's not in WHNF. - pub(crate) fn from_partial_expr(e: ExprKind<Nir>) -> Nir { + pub fn from_partial_expr(e: ExprKind<Nir>) -> Nir { // TODO: env let env = NzEnv::new(); NirInternal::from_thunk(Thunk::from_partial_expr(env, e)).into_nir() } /// Make a Nir from a NirKind - pub(crate) fn from_kind(v: NirKind) -> Nir { + pub fn from_kind(v: NirKind) -> Nir { NirInternal::from_whnf(v).into_nir() } - pub(crate) fn from_const(c: Const) -> Self { + pub fn from_const(c: Const) -> Self { let v = NirKind::Const(c); NirInternal::from_whnf(v).into_nir() } - pub(crate) fn from_builtin(b: Builtin) -> Self { + pub fn from_builtin(b: Builtin) -> Self { Self::from_builtin_env(b, &NzEnv::new()) } - pub(crate) fn from_builtin_env(b: Builtin, env: &NzEnv) -> Self { + pub fn from_builtin_env(b: Builtin, env: &NzEnv) -> Self { Nir::from_kind(NirKind::from_builtin_env(b, env.clone())) } - pub(crate) fn from_text(txt: impl ToString) -> Self { + pub fn from_text(txt: impl ToString) -> Self { Nir::from_kind(NirKind::TextLit(TextLit::from_text(txt.to_string()))) } - pub(crate) fn as_const(&self) -> Option<Const> { + pub fn as_const(&self) -> Option<Const> { match &*self.kind() { NirKind::Const(c) => Some(*c), _ => None, @@ -128,26 +132,22 @@ impl Nir { } /// This is what you want if you want to pattern-match on the value. - pub(crate) fn kind(&self) -> &NirKind { + pub fn kind(&self) -> &NirKind { self.0.kind() } - pub(crate) fn to_type(&self, u: impl Into<Universe>) -> Type { + pub fn to_type(&self, u: impl Into<Universe>) -> Type { Type::new(self.clone(), u.into()) } /// Converts a value back to the corresponding AST expression. - pub(crate) fn to_expr(&self, opts: ToExprOptions) -> NormalizedExpr { + pub fn to_expr(&self, opts: ToExprOptions) -> Expr { self.to_hir_noenv().to_expr(opts) } - pub(crate) fn to_expr_tyenv(&self, tyenv: &TyEnv) -> NormalizedExpr { + pub fn to_expr_tyenv(&self, tyenv: &TyEnv) -> Expr { self.to_hir(tyenv.as_varenv()).to_expr_tyenv(tyenv) } - pub(crate) fn normalize(&self) { - self.0.normalize() - } - - pub(crate) fn app(&self, v: Nir) -> Nir { + pub fn app(&self, v: Nir) -> Nir { Nir::from_kind(apply_any(self.clone(), v)) } @@ -188,12 +188,21 @@ impl Nir { closure.to_hir(venv), ), NirKind::Const(c) => ExprKind::Const(*c), - NirKind::Lit(l) => ExprKind::Lit(l.clone()), + NirKind::BuiltinType(b) => ExprKind::Builtin(*b), + NirKind::Num(l) => ExprKind::Num(l.clone()), + NirKind::OptionalType(t) => ExprKind::App( + Nir::from_builtin(Builtin::Optional).to_hir(venv), + t.to_hir(venv), + ), NirKind::EmptyOptionalLit(n) => ExprKind::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( + Nir::from_builtin(Builtin::List).to_hir(venv), + t.to_hir(venv), + ), NirKind::EmptyListLit(n) => ExprKind::EmptyListLit(Hir::new( HirKind::Expr(ExprKind::App( Nir::from_builtin(Builtin::List).to_hir(venv), @@ -274,75 +283,18 @@ impl NirInternal { fn kind(&self) -> &NirKind { &self.kind } - fn normalize(&self) { - self.kind().normalize(); - } } impl NirKind { - pub(crate) fn into_nir(self) -> Nir { + pub fn into_nir(self) -> Nir { Nir::from_kind(self) } - pub(crate) fn normalize(&self) { - match self { - NirKind::Var(..) | NirKind::Const(_) | NirKind::Lit(_) => {} - - NirKind::EmptyOptionalLit(tth) | NirKind::EmptyListLit(tth) => { - tth.normalize(); - } - - NirKind::NEOptionalLit(th) => { - th.normalize(); - } - NirKind::LamClosure { annot, closure, .. } - | NirKind::PiClosure { annot, closure, .. } => { - annot.normalize(); - closure.normalize(); - } - NirKind::AppliedBuiltin(closure) => closure.normalize(), - NirKind::NEListLit(elts) => { - for x in elts.iter() { - x.normalize(); - } - } - NirKind::RecordLit(kvs) => { - for x in kvs.values() { - x.normalize(); - } - } - NirKind::RecordType(kvs) => { - for x in kvs.values() { - x.normalize(); - } - } - NirKind::UnionType(kts) | NirKind::UnionConstructor(_, kts) => { - for x in kts.values().flatten() { - x.normalize(); - } - } - NirKind::UnionLit(_, v, kts) => { - v.normalize(); - for x in kts.values().flatten() { - x.normalize(); - } - } - NirKind::TextLit(tlit) => tlit.normalize(), - NirKind::Equivalence(x, y) => { - x.normalize(); - y.normalize(); - } - NirKind::PartialExpr(e) => { - e.map_ref(Nir::normalize); - } - } - } - - pub(crate) fn from_builtin(b: Builtin) -> NirKind { + pub fn from_builtin(b: Builtin) -> NirKind { NirKind::from_builtin_env(b, NzEnv::new()) } - pub(crate) fn from_builtin_env(b: Builtin, env: NzEnv) -> NirKind { - NirKind::AppliedBuiltin(BuiltinClosure::new(b, env)) + pub fn from_builtin_env(b: Builtin, env: NzEnv) -> NirKind { + BuiltinClosure::new(b, env) } } @@ -390,9 +342,6 @@ impl Closure { } } - // TODO: somehow normalize the body. Might require to pass an env. - pub fn normalize(&self) {} - /// Convert this closure to a Hir expression pub fn to_hir(&self, venv: VarEnv) -> Hir { self.apply_var(NzVar::new(venv.size())) @@ -456,13 +405,6 @@ impl TextLit { pub fn iter(&self) -> impl Iterator<Item = &InterpolatedTextContents<Nir>> { self.0.iter() } - /// Normalize the contained values. This does not break the invariant because we have already - /// ensured that no contained values normalize to a TextLit. - pub fn normalize(&self) { - for x in self.0.iter() { - x.map_ref(Nir::normalize); - } - } } impl lazy::Eval<NirKind> for Thunk { diff --git a/dhall/src/semantics/nze/normalize.rs b/dhall/src/semantics/nze/normalize.rs index 79d55e8..570e106 100644 --- a/dhall/src/semantics/nze/normalize.rs +++ b/dhall/src/semantics/nze/normalize.rs @@ -2,14 +2,10 @@ use itertools::Itertools; use std::collections::HashMap; use crate::semantics::NzEnv; -use crate::semantics::{ - Binder, BuiltinClosure, Closure, Hir, HirKind, Nir, NirKind, TextLit, -}; -use crate::syntax::{ - BinOp, Builtin, ExprKind, InterpolatedTextContents, LitKind, -}; +use crate::semantics::{Binder, Closure, Hir, HirKind, Nir, NirKind, TextLit}; +use crate::syntax::{BinOp, ExprKind, InterpolatedTextContents, NumKind}; -pub(crate) fn apply_any(f: Nir, a: Nir) -> NirKind { +pub fn apply_any(f: Nir, a: Nir) -> NirKind { match f.kind() { NirKind::LamClosure { closure, .. } => closure.apply(a).kind().clone(), NirKind::AppliedBuiltin(closure) => closure.apply(a), @@ -20,7 +16,7 @@ pub(crate) fn apply_any(f: Nir, a: Nir) -> NirKind { } } -pub(crate) fn squash_textlit( +pub fn squash_textlit( elts: impl Iterator<Item = InterpolatedTextContents<Nir>>, ) -> Vec<InterpolatedTextContents<Nir>> { use std::mem::replace; @@ -58,7 +54,7 @@ pub(crate) fn squash_textlit( ret } -pub(crate) fn merge_maps<K, V, F>( +pub fn merge_maps<K, V, F>( map1: &HashMap<K, V>, map2: &HashMap<K, V>, mut f: F, @@ -99,40 +95,40 @@ fn apply_binop<'a>(o: BinOp, x: &'a Nir, y: &'a Nir) -> Option<Ret<'a>> { NaturalTimes, RecursiveRecordMerge, RecursiveRecordTypeMerge, RightBiasedRecordMerge, TextAppend, }; - use LitKind::{Bool, Natural}; - use NirKind::{EmptyListLit, Lit, NEListLit, RecordLit, RecordType}; + use NirKind::{EmptyListLit, NEListLit, Num, RecordLit, RecordType}; + use NumKind::{Bool, Natural}; Some(match (o, x.kind(), y.kind()) { - (BoolAnd, Lit(Bool(true)), _) => Ret::NirRef(y), - (BoolAnd, _, Lit(Bool(true))) => Ret::NirRef(x), - (BoolAnd, Lit(Bool(false)), _) => Ret::NirKind(Lit(Bool(false))), - (BoolAnd, _, Lit(Bool(false))) => Ret::NirKind(Lit(Bool(false))), + (BoolAnd, Num(Bool(true)), _) => Ret::NirRef(y), + (BoolAnd, _, Num(Bool(true))) => Ret::NirRef(x), + (BoolAnd, Num(Bool(false)), _) => Ret::NirKind(Num(Bool(false))), + (BoolAnd, _, Num(Bool(false))) => Ret::NirKind(Num(Bool(false))), (BoolAnd, _, _) if x == y => Ret::NirRef(x), - (BoolOr, Lit(Bool(true)), _) => Ret::NirKind(Lit(Bool(true))), - (BoolOr, _, Lit(Bool(true))) => Ret::NirKind(Lit(Bool(true))), - (BoolOr, Lit(Bool(false)), _) => Ret::NirRef(y), - (BoolOr, _, Lit(Bool(false))) => Ret::NirRef(x), + (BoolOr, Num(Bool(true)), _) => Ret::NirKind(Num(Bool(true))), + (BoolOr, _, Num(Bool(true))) => Ret::NirKind(Num(Bool(true))), + (BoolOr, Num(Bool(false)), _) => Ret::NirRef(y), + (BoolOr, _, Num(Bool(false))) => Ret::NirRef(x), (BoolOr, _, _) if x == y => Ret::NirRef(x), - (BoolEQ, Lit(Bool(true)), _) => Ret::NirRef(y), - (BoolEQ, _, Lit(Bool(true))) => Ret::NirRef(x), - (BoolEQ, Lit(Bool(x)), Lit(Bool(y))) => Ret::NirKind(Lit(Bool(x == y))), - (BoolEQ, _, _) if x == y => Ret::NirKind(Lit(Bool(true))), - (BoolNE, Lit(Bool(false)), _) => Ret::NirRef(y), - (BoolNE, _, Lit(Bool(false))) => Ret::NirRef(x), - (BoolNE, Lit(Bool(x)), Lit(Bool(y))) => Ret::NirKind(Lit(Bool(x != y))), - (BoolNE, _, _) if x == y => Ret::NirKind(Lit(Bool(false))), + (BoolEQ, Num(Bool(true)), _) => Ret::NirRef(y), + (BoolEQ, _, Num(Bool(true))) => Ret::NirRef(x), + (BoolEQ, Num(Bool(x)), Num(Bool(y))) => Ret::NirKind(Num(Bool(x == y))), + (BoolEQ, _, _) if x == y => Ret::NirKind(Num(Bool(true))), + (BoolNE, Num(Bool(false)), _) => Ret::NirRef(y), + (BoolNE, _, Num(Bool(false))) => Ret::NirRef(x), + (BoolNE, Num(Bool(x)), Num(Bool(y))) => Ret::NirKind(Num(Bool(x != y))), + (BoolNE, _, _) if x == y => Ret::NirKind(Num(Bool(false))), - (NaturalPlus, Lit(Natural(0)), _) => Ret::NirRef(y), - (NaturalPlus, _, Lit(Natural(0))) => Ret::NirRef(x), - (NaturalPlus, Lit(Natural(x)), Lit(Natural(y))) => { - Ret::NirKind(Lit(Natural(x + y))) + (NaturalPlus, Num(Natural(0)), _) => Ret::NirRef(y), + (NaturalPlus, _, Num(Natural(0))) => Ret::NirRef(x), + (NaturalPlus, Num(Natural(x)), Num(Natural(y))) => { + Ret::NirKind(Num(Natural(x + y))) } - (NaturalTimes, Lit(Natural(0)), _) => Ret::NirKind(Lit(Natural(0))), - (NaturalTimes, _, Lit(Natural(0))) => Ret::NirKind(Lit(Natural(0))), - (NaturalTimes, Lit(Natural(1)), _) => Ret::NirRef(y), - (NaturalTimes, _, Lit(Natural(1))) => Ret::NirRef(x), - (NaturalTimes, Lit(Natural(x)), Lit(Natural(y))) => { - Ret::NirKind(Lit(Natural(x * y))) + (NaturalTimes, Num(Natural(0)), _) => Ret::NirKind(Num(Natural(0))), + (NaturalTimes, _, Num(Natural(0))) => Ret::NirKind(Num(Natural(0))), + (NaturalTimes, Num(Natural(1)), _) => Ret::NirRef(y), + (NaturalTimes, _, Num(Natural(1))) => Ret::NirRef(x), + (NaturalTimes, Num(Natural(x)), Num(Natural(y))) => { + Ret::NirKind(Num(Natural(x * y))) } (ListAppend, EmptyListLit(_), _) => Ret::NirRef(y), @@ -211,13 +207,13 @@ fn apply_binop<'a>(o: BinOp, x: &'a Nir, y: &'a Nir) -> Option<Ret<'a>> { } #[allow(clippy::cognitive_complexity)] -pub(crate) fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind { - use LitKind::Bool; +pub fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind { use NirKind::{ - EmptyListLit, EmptyOptionalLit, Lit, NEListLit, NEOptionalLit, + EmptyListLit, EmptyOptionalLit, NEListLit, NEOptionalLit, Num, PartialExpr, RecordLit, RecordType, UnionConstructor, UnionLit, UnionType, }; + use NumKind::Bool; let ret = match expr { ExprKind::Import(..) | ExprKind::Completion(..) => { @@ -235,15 +231,11 @@ pub(crate) fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind { 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::Lit(l) => Ret::NirKind(Lit(l)), + ExprKind::Num(l) => Ret::NirKind(Num(l)), ExprKind::SomeLit(e) => Ret::NirKind(NEOptionalLit(e)), ExprKind::EmptyListLit(t) => { let arg = match t.kind() { - NirKind::AppliedBuiltin(BuiltinClosure { - b: Builtin::List, - args, - .. - }) if args.len() == 1 => args[0].clone(), + NirKind::ListType(t) => t.clone(), _ => panic!("internal type error"), }; Ret::NirKind(NirKind::EmptyListLit(arg)) @@ -271,12 +263,12 @@ pub(crate) fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind { } ExprKind::BoolIf(ref b, ref e1, ref e2) => { match b.kind() { - Lit(Bool(true)) => Ret::NirRef(e1), - Lit(Bool(false)) => Ret::NirRef(e2), + Num(Bool(true)) => Ret::NirRef(e1), + Num(Bool(false)) => Ret::NirRef(e2), _ => { match (e1.kind(), e2.kind()) { // Simplify `if b then True else False` - (Lit(Bool(true)), Lit(Bool(false))) => Ret::NirRef(b), + (Num(Bool(true)), Num(Bool(false))) => Ret::NirRef(b), _ if e1 == e2 => Ret::NirRef(e1), _ => Ret::Expr(expr), } @@ -442,12 +434,8 @@ pub(crate) fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind { ExprKind::ToMap(ref v, ref annot) => match v.kind() { RecordLit(kvs) if kvs.is_empty() => { match annot.as_ref().map(|v| v.kind()) { - Some(NirKind::AppliedBuiltin(BuiltinClosure { - b: Builtin::List, - args, - .. - })) if args.len() == 1 => { - Ret::NirKind(EmptyListLit(args[0].clone())) + Some(NirKind::ListType(t)) => { + Ret::NirKind(EmptyListLit(t.clone())) } _ => Ret::Expr(expr), } @@ -476,7 +464,7 @@ pub(crate) fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind { } /// Normalize Hir into WHNF -pub(crate) fn normalize_hir_whnf(env: &NzEnv, hir: &Hir) -> NirKind { +pub fn normalize_hir_whnf(env: &NzEnv, hir: &Hir) -> NirKind { match hir.kind() { HirKind::Var(var) => env.lookup_val(*var), HirKind::Import(hir, _) => normalize_hir_whnf(env, hir), diff --git a/dhall/src/semantics/nze/var.rs b/dhall/src/semantics/nze/var.rs index 413c759..302dbb7 100644 --- a/dhall/src/semantics/nze/var.rs +++ b/dhall/src/semantics/nze/var.rs @@ -8,10 +8,10 @@ pub struct Binder { } impl Binder { - pub(crate) fn new(name: Label) -> Self { + pub fn new(name: Label) -> Self { Binder { name } } - pub(crate) fn to_label(&self) -> Label { + pub fn to_label(&self) -> Label { self.clone().into() } } diff --git a/dhall/src/semantics/parse.rs b/dhall/src/semantics/parse.rs index 45860d0..2326471 100644 --- a/dhall/src/semantics/parse.rs +++ b/dhall/src/semantics/parse.rs @@ -9,33 +9,33 @@ use crate::syntax::binary; use crate::syntax::parse_expr; use crate::Parsed; -pub(crate) fn parse_file(f: &Path) -> Result<Parsed, Error> { +pub fn parse_file(f: &Path) -> Result<Parsed, Error> { let text = std::fs::read_to_string(f)?; let expr = parse_expr(&text)?; let root = ImportLocation::Local(f.to_owned()); Ok(Parsed(expr, root)) } -pub(crate) fn parse_remote(url: Url) -> Result<Parsed, Error> { +pub fn parse_remote(url: Url) -> Result<Parsed, Error> { let body = reqwest::blocking::get(url.clone()).unwrap().text().unwrap(); let expr = parse_expr(&body)?; let root = ImportLocation::Remote(url); Ok(Parsed(expr, root)) } -pub(crate) fn parse_str(s: &str) -> Result<Parsed, Error> { +pub fn parse_str(s: &str) -> Result<Parsed, Error> { let expr = parse_expr(s)?; let root = ImportLocation::Missing; Ok(Parsed(expr, root)) } -pub(crate) fn parse_binary(data: &[u8]) -> Result<Parsed, Error> { +pub fn parse_binary(data: &[u8]) -> Result<Parsed, Error> { let expr = binary::decode(data)?; let root = ImportLocation::Missing; Ok(Parsed(expr, root)) } -pub(crate) fn parse_binary_file(f: &Path) -> Result<Parsed, Error> { +pub fn parse_binary_file(f: &Path) -> Result<Parsed, Error> { let mut buffer = Vec::new(); File::open(f)?.read_to_end(&mut buffer)?; let expr = binary::decode(&buffer)?; diff --git a/dhall/src/semantics/resolve/env.rs b/dhall/src/semantics/resolve/env.rs index fe8c178..d7ff0ae 100644 --- a/dhall/src/semantics/resolve/env.rs +++ b/dhall/src/semantics/resolve/env.rs @@ -5,24 +5,24 @@ use crate::semantics::{AlphaVar, ImportLocation, TypedHir, VarEnv}; use crate::syntax::{Label, V}; /// Environment for resolving names. -#[derive(Debug, Clone)] -pub(crate) struct NameEnv { +#[derive(Debug, Clone, Default)] +pub struct NameEnv { names: Vec<Label>, } -pub(crate) type ImportCache = HashMap<ImportLocation, TypedHir>; -pub(crate) type ImportStack = Vec<ImportLocation>; +pub type ImportCache = HashMap<ImportLocation, TypedHir>; +pub type ImportStack = Vec<ImportLocation>; /// Environment for resolving imports -#[derive(Debug, Clone)] -pub(crate) struct ImportEnv { +#[derive(Debug, Clone, Default)] +pub struct ImportEnv { cache: ImportCache, stack: ImportStack, } impl NameEnv { pub fn new() -> Self { - NameEnv { names: Vec::new() } + NameEnv::default() } pub fn as_varenv(&self) -> VarEnv { VarEnv::from_size(self.names.len()) @@ -66,10 +66,7 @@ impl NameEnv { impl ImportEnv { pub fn new() -> Self { - ImportEnv { - cache: HashMap::new(), - stack: Vec::new(), - } + ImportEnv::default() } pub fn handle_import( diff --git a/dhall/src/semantics/resolve/hir.rs b/dhall/src/semantics/resolve/hir.rs index fa2989f..9256425 100644 --- a/dhall/src/semantics/resolve/hir.rs +++ b/dhall/src/semantics/resolve/hir.rs @@ -1,7 +1,7 @@ use crate::error::TypeError; use crate::semantics::{type_with, NameEnv, Nir, NzEnv, Tir, TyEnv, Type}; use crate::syntax::{Expr, ExprKind, Span, V}; -use crate::{NormalizedExpr, ToExprOptions}; +use crate::ToExprOptions; /// Stores an alpha-normalized variable. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -10,7 +10,7 @@ pub struct AlphaVar { } #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum HirKind { +pub enum HirKind { /// A resolved variable (i.e. a DeBruijn index) Var(AlphaVar), /// Result of resolving an import. @@ -21,16 +21,16 @@ pub(crate) enum HirKind { // An expression with resolved variables and imports. #[derive(Debug, Clone)] -pub(crate) struct Hir { +pub struct Hir { kind: Box<HirKind>, span: Span, } impl AlphaVar { - pub(crate) fn new(idx: usize) -> Self { + pub fn new(idx: usize) -> Self { AlphaVar { idx } } - pub(crate) fn idx(self) -> usize { + pub fn idx(self) -> usize { self.idx } } @@ -51,15 +51,15 @@ impl Hir { } /// Converts a closed Hir expr back to the corresponding AST expression. - pub fn to_expr(&self, opts: ToExprOptions) -> NormalizedExpr { + pub fn to_expr(&self, opts: ToExprOptions) -> Expr { hir_to_expr(self, opts, &mut NameEnv::new()) } /// Converts a closed Hir expr back to the corresponding AST expression. - pub fn to_expr_noopts(&self) -> NormalizedExpr { + pub fn to_expr_noopts(&self) -> Expr { let opts = ToExprOptions { alpha: false }; self.to_expr(opts) } - pub fn to_expr_tyenv(&self, env: &TyEnv) -> NormalizedExpr { + pub fn to_expr_tyenv(&self, env: &TyEnv) -> Expr { let opts = ToExprOptions { alpha: false }; let mut env = env.as_nameenv().clone(); hir_to_expr(self, opts, &mut env) @@ -85,19 +85,9 @@ impl Hir { pub fn eval_closed_expr(&self) -> Nir { self.eval(NzEnv::new()) } - /// Eval a closed Hir fully and recursively; - pub fn rec_eval_closed_expr(&self) -> Nir { - let val = self.eval_closed_expr(); - val.normalize(); - val - } } -fn hir_to_expr( - hir: &Hir, - opts: ToExprOptions, - env: &mut NameEnv, -) -> NormalizedExpr { +fn hir_to_expr(hir: &Hir, opts: ToExprOptions, env: &mut NameEnv) -> Expr { let kind = match hir.kind() { HirKind::Var(v) if opts.alpha => ExprKind::Var(V("_".into(), v.idx())), HirKind::Var(v) => ExprKind::Var(env.label_var(*v)), diff --git a/dhall/src/semantics/resolve/mod.rs b/dhall/src/semantics/resolve/mod.rs index 517907b..33b477e 100644 --- a/dhall/src/semantics/resolve/mod.rs +++ b/dhall/src/semantics/resolve/mod.rs @@ -1,6 +1,6 @@ pub mod env; pub mod hir; pub mod resolve; -pub(crate) use env::*; -pub(crate) use hir::*; -pub(crate) use resolve::*; +pub use env::*; +pub use hir::*; +pub use resolve::*; diff --git a/dhall/src/semantics/resolve/resolve.rs b/dhall/src/semantics/resolve/resolve.rs index f3fda4b..7745e0b 100644 --- a/dhall/src/semantics/resolve/resolve.rs +++ b/dhall/src/semantics/resolve/resolve.rs @@ -13,17 +13,17 @@ use crate::syntax::{ BinOp, Builtin, Expr, ExprKind, FilePath, FilePrefix, ImportMode, ImportTarget, Span, UnspannedExpr, URL, }; -use crate::{Parsed, ParsedExpr, Resolved}; +use crate::{Parsed, Resolved}; // TODO: evaluate import headers -pub(crate) type Import = syntax::Import<()>; +pub type Import = syntax::Import<()>; /// Owned Hir with a type. Different from Tir because the Hir is owned. -pub(crate) type TypedHir = (Hir, Type); +pub type TypedHir = (Hir, Type); /// The location of some data, usually some dhall code. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum ImportLocation { +pub enum ImportLocation { /// Local file Local(PathBuf), /// Remote file @@ -227,7 +227,7 @@ fn resolve_one_import( } ImportMode::Location => { let expr = location.into_location(); - let hir = skip_resolve(&expr)?; + let hir = skip_resolve_expr(&expr)?; let ty = hir.typecheck_noenv()?.ty().clone(); Ok((hir, ty)) } @@ -329,16 +329,22 @@ fn resolve_with_env( Ok(Resolved(resolved)) } -pub(crate) fn resolve(parsed: Parsed) -> Result<Resolved, Error> { +pub fn resolve(parsed: Parsed) -> Result<Resolved, Error> { resolve_with_env(&mut ImportEnv::new(), parsed) } -pub(crate) fn skip_resolve(expr: &ParsedExpr) -> Result<Hir, Error> { +pub fn skip_resolve_expr(expr: &Expr) -> Result<Hir, Error> { traverse_resolve_expr(&mut NameEnv::new(), expr, &mut |import| { Err(ImportError::UnexpectedImport(import).into()) }) } +pub fn skip_resolve(parsed: Parsed) -> Result<Resolved, Error> { + let Parsed(expr, _) = parsed; + let resolved = skip_resolve_expr(&expr)?; + Ok(Resolved(resolved)) +} + pub trait Canonicalize { fn canonicalize(&self) -> Self; } diff --git a/dhall/src/semantics/tck/env.rs b/dhall/src/semantics/tck/env.rs index 6dd5076..1fa66f0 100644 --- a/dhall/src/semantics/tck/env.rs +++ b/dhall/src/semantics/tck/env.rs @@ -2,21 +2,21 @@ use crate::semantics::{AlphaVar, NameEnv, Nir, NzEnv, NzVar, Type, ValEnv}; use crate::syntax::Label; /// Environment for indexing variables. -#[derive(Debug, Clone, Copy)] -pub(crate) struct VarEnv { +#[derive(Debug, Clone, Copy, Default)] +pub struct VarEnv { size: usize, } /// Environment for typing expressions. #[derive(Debug, Clone)] -pub(crate) struct TyEnv { +pub struct TyEnv { names: NameEnv, items: ValEnv<Type>, } impl VarEnv { pub fn new() -> Self { - VarEnv { size: 0 } + VarEnv::default() } pub fn from_size(size: usize) -> Self { VarEnv { size } diff --git a/dhall/src/semantics/tck/mod.rs b/dhall/src/semantics/tck/mod.rs index 93c8f48..6dddfc5 100644 --- a/dhall/src/semantics/tck/mod.rs +++ b/dhall/src/semantics/tck/mod.rs @@ -1,6 +1,6 @@ pub mod env; pub mod tir; pub mod typecheck; -pub(crate) use env::*; -pub(crate) use tir::*; -pub(crate) use typecheck::*; +pub use env::*; +pub use tir::*; +pub use typecheck::*; diff --git a/dhall/src/semantics/tck/tir.rs b/dhall/src/semantics/tck/tir.rs index aeb7bf9..89a8027 100644 --- a/dhall/src/semantics/tck/tir.rs +++ b/dhall/src/semantics/tck/tir.rs @@ -1,15 +1,14 @@ use crate::error::{ErrorBuilder, TypeError}; use crate::semantics::{mkerr, Hir, Nir, NirKind, NzEnv, TyEnv, VarEnv}; -use crate::syntax::{Builtin, Const, Span}; -use crate::NormalizedExpr; +use crate::syntax::{Builtin, Const, Expr, Span}; /// The type of a type. 0 is `Type`, 1 is `Kind`, etc... #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)] -pub(crate) struct Universe(u8); +pub struct Universe(u8); /// An expression representing a type #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct Type { +pub struct Type { val: Nir, univ: Universe, } @@ -17,7 +16,7 @@ pub(crate) struct Type { /// A hir expression plus its inferred type. /// Stands for "Typed intermediate representation" #[derive(Debug, Clone)] -pub(crate) struct Tir<'hir> { +pub struct Tir<'hir> { hir: &'hir Hir, ty: Type, } @@ -101,7 +100,7 @@ impl Type { pub fn to_hir(&self, venv: VarEnv) -> Hir { self.val.to_hir(venv) } - pub fn to_expr_tyenv(&self, tyenv: &TyEnv) -> NormalizedExpr { + pub fn to_expr_tyenv(&self, tyenv: &TyEnv) -> Expr { self.val.to_hir(tyenv.as_varenv()).to_expr_tyenv(tyenv) } } @@ -124,7 +123,7 @@ impl<'hir> Tir<'hir> { pub fn as_hir(&self) -> &Hir { &self.hir } - pub fn to_expr_tyenv(&self, env: &TyEnv) -> NormalizedExpr { + pub fn to_expr_tyenv(&self, env: &TyEnv) -> Expr { self.as_hir().to_expr_tyenv(env) } diff --git a/dhall/src/semantics/tck/typecheck.rs b/dhall/src/semantics/tck/typecheck.rs index 173b76d..c3334b5 100644 --- a/dhall/src/semantics/tck/typecheck.rs +++ b/dhall/src/semantics/tck/typecheck.rs @@ -5,11 +5,11 @@ use std::collections::HashMap; use crate::error::{ErrorBuilder, TypeError, TypeMessage}; use crate::semantics::merge_maps; use crate::semantics::{ - type_of_builtin, Binder, BuiltinClosure, Closure, Hir, HirKind, Nir, - NirKind, Tir, TyEnv, Type, + type_of_builtin, Binder, Closure, Hir, HirKind, Nir, NirKind, Tir, TyEnv, + Type, }; use crate::syntax::{ - BinOp, Builtin, Const, ExprKind, InterpolatedTextContents, LitKind, Span, + BinOp, Builtin, Const, ExprKind, InterpolatedTextContents, NumKind, Span, }; fn check_rectymerge( @@ -53,14 +53,11 @@ fn function_check(a: Const, b: Const) -> Const { } } -pub(crate) fn mkerr<T, S: ToString>(msg: S) -> Result<T, TypeError> { +pub fn mkerr<T, S: ToString>(msg: S) -> Result<T, TypeError> { Err(TypeError::new(TypeMessage::Custom(msg.to_string()))) } -pub(crate) fn mk_span_err<T, S: ToString>( - span: Span, - msg: S, -) -> Result<T, TypeError> { +pub fn mk_span_err<T, S: ToString>(span: Span, msg: S) -> Result<T, TypeError> { mkerr( ErrorBuilder::new(msg.to_string()) .span_err(span, msg.to_string()) @@ -96,14 +93,14 @@ fn type_one_layer( let t_hir = type_of_builtin(*b); typecheck(&t_hir)?.eval_to_type(env)? } - ExprKind::Lit(LitKind::Bool(_)) => Type::from_builtin(Builtin::Bool), - ExprKind::Lit(LitKind::Natural(_)) => { + ExprKind::Num(NumKind::Bool(_)) => Type::from_builtin(Builtin::Bool), + ExprKind::Num(NumKind::Natural(_)) => { Type::from_builtin(Builtin::Natural) } - ExprKind::Lit(LitKind::Integer(_)) => { + ExprKind::Num(NumKind::Integer(_)) => { Type::from_builtin(Builtin::Integer) } - ExprKind::Lit(LitKind::Double(_)) => { + ExprKind::Num(NumKind::Double(_)) => { Type::from_builtin(Builtin::Double) } ExprKind::TextLit(interpolated) => { @@ -121,11 +118,7 @@ fn type_one_layer( ExprKind::EmptyListLit(t) => { let t = t.eval_to_type(env)?; match t.kind() { - NirKind::AppliedBuiltin(BuiltinClosure { - b: Builtin::List, - args, - .. - }) if args.len() == 1 => {} + NirKind::ListType(..) => {} _ => return span_err("InvalidListType"), }; t @@ -376,10 +369,7 @@ fn type_one_layer( } ExprKind::BinOp(BinOp::ListAppend, l, r) => { match l.ty().kind() { - NirKind::AppliedBuiltin(BuiltinClosure { - b: Builtin::List, - .. - }) => {} + NirKind::ListType(..) => {} _ => return span_err("BinOpTypeMismatch"), } @@ -435,12 +425,7 @@ fn type_one_layer( let union_type = union.ty(); let variants = match union_type.kind() { NirKind::UnionType(kts) => Cow::Borrowed(kts), - NirKind::AppliedBuiltin(BuiltinClosure { - b: Builtin::Optional, - args, - .. - }) if args.len() == 1 => { - let ty = &args[0]; + NirKind::OptionalType(ty) => { let mut kts = HashMap::new(); kts.insert("None".into(), None); kts.insert("Some".into(), Some(ty.clone())); @@ -595,11 +580,7 @@ fn type_one_layer( let err_msg = "The type of `toMap x` must be of the form \ `List { mapKey : Text, mapValue : T }`"; let arg = match annot_val.kind() { - NirKind::AppliedBuiltin(BuiltinClosure { - b: Builtin::List, - args, - .. - }) if args.len() == 1 => &args[0], + NirKind::ListType(t) => t, _ => return span_err(err_msg), }; let kts = match arg.kind() { @@ -704,7 +685,7 @@ fn type_one_layer( /// `type_with` typechecks an expression in the provided environment. Optionally pass an annotation /// to compare with. -pub(crate) fn type_with<'hir>( +pub fn type_with<'hir>( env: &TyEnv, hir: &'hir Hir, annot: Option<Type>, @@ -801,15 +782,15 @@ pub(crate) fn type_with<'hir>( /// Typecheck an expression and return the expression annotated with types if type-checking /// succeeded, or an error if type-checking failed. -pub(crate) fn typecheck<'hir>(hir: &'hir Hir) -> Result<Tir<'hir>, TypeError> { +pub fn typecheck<'hir>(hir: &'hir Hir) -> Result<Tir<'hir>, TypeError> { type_with(&TyEnv::new(), hir, None) } /// Like `typecheck`, but additionally checks that the expression's type matches the provided type. -pub(crate) fn typecheck_with<'hir>( +pub fn typecheck_with<'hir>( hir: &'hir Hir, - ty: Hir, + ty: &Hir, ) -> Result<Tir<'hir>, TypeError> { - let ty = typecheck(&ty)?.eval_to_type(&TyEnv::new())?; + let ty = typecheck(ty)?.eval_to_type(&TyEnv::new())?; type_with(&TyEnv::new(), hir, Some(ty)) } |