diff options
author | Nadrieril | 2019-12-27 16:05:47 +0000 |
---|---|---|
committer | Nadrieril | 2020-01-17 10:06:00 +0000 |
commit | 654d752c65f0e221d225ed045a0aee62f223855e (patch) | |
tree | b982c70d01fc32494f0bf1ebcb838ba6cdc8a425 /dhall | |
parent | 8e2da26650e202f9ccb1531fc8a88cfd89e54b6d (diff) |
Introduce a notion of binder
Diffstat (limited to '')
-rw-r--r-- | dhall/src/semantics/core/context.rs | 25 | ||||
-rw-r--r-- | dhall/src/semantics/core/value.rs | 8 | ||||
-rw-r--r-- | dhall/src/semantics/core/var.rs | 34 | ||||
-rw-r--r-- | dhall/src/semantics/core/visitor.rs | 8 | ||||
-rw-r--r-- | dhall/src/semantics/phase/typecheck.rs | 27 |
5 files changed, 56 insertions, 46 deletions
diff --git a/dhall/src/semantics/core/context.rs b/dhall/src/semantics/core/context.rs index ed63b63..3a7930e 100644 --- a/dhall/src/semantics/core/context.rs +++ b/dhall/src/semantics/core/context.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use crate::error::TypeError; use crate::semantics::core::value::Value; use crate::semantics::core::value::ValueKind; -use crate::semantics::core::var::{AlphaVar, Shift, Subst}; +use crate::semantics::core::var::{AlphaVar, Binder, Shift, Subst}; use crate::syntax::{Label, V}; #[derive(Debug, Clone)] @@ -14,22 +14,26 @@ enum CtxItem { #[derive(Debug, Clone)] pub(crate) struct TyCtx { - ctx: Vec<(Label, CtxItem)>, + ctx: Vec<(Binder, CtxItem)>, } impl TyCtx { pub fn new() -> Self { TyCtx { ctx: Vec::new() } } - fn with_vec(&self, vec: Vec<(Label, CtxItem)>) -> Self { + fn with_vec(&self, vec: Vec<(Binder, CtxItem)>) -> Self { TyCtx { ctx: vec } } - pub fn insert_type(&self, x: &Label, t: Value) -> Self { + pub fn insert_type(&self, x: &Binder, t: Value) -> Self { let mut vec = self.ctx.clone(); vec.push((x.clone(), CtxItem::Kept(x.into(), t.under_binder(x)))); self.with_vec(vec) } - pub fn insert_value(&self, x: &Label, e: Value) -> Result<Self, TypeError> { + pub fn insert_value( + &self, + x: &Binder, + e: Value, + ) -> Result<Self, TypeError> { let mut vec = self.ctx.clone(); vec.push((x.clone(), CtxItem::Replaced(e))); Ok(self.with_vec(vec)) @@ -37,8 +41,9 @@ impl TyCtx { pub fn lookup(&self, var: &V<Label>) -> Option<Value> { let mut var = var.clone(); let mut shift_map: HashMap<Label, _> = HashMap::new(); - for (l, i) in self.ctx.iter().rev() { - match var.over_binder(l) { + for (b, i) in self.ctx.iter().rev() { + let l = b.to_label(); + match var.over_binder(&l) { None => { let i = i.under_multiple_binders(&shift_map); return Some(match i { @@ -51,12 +56,16 @@ impl TyCtx { Some(newvar) => var = newvar, }; if let CtxItem::Kept(_, _) = i { - *shift_map.entry(l.clone()).or_insert(0) += 1; + *shift_map.entry(l).or_insert(0) += 1; } } // Unbound variable None } + pub fn new_binder(&self, l: &Label) -> Binder { + Binder::new(l.clone()) + } + /// Given a var that makes sense in the current context, map the given function in such a way /// that the passed variable always makes sense in the context of the passed item. /// Once we pass the variable definition, the variable doesn't make sense anymore so we just diff --git a/dhall/src/semantics/core/value.rs b/dhall/src/semantics/core/value.rs index f7c2fbf..687fcfe 100644 --- a/dhall/src/semantics/core/value.rs +++ b/dhall/src/semantics/core/value.rs @@ -4,7 +4,7 @@ use std::rc::Rc; use crate::error::{TypeError, TypeMessage}; use crate::semantics::core::context::TyCtx; -use crate::semantics::core::var::{AlphaLabel, AlphaVar, Shift, Subst}; +use crate::semantics::core::var::{AlphaVar, Binder, Shift, Subst}; use crate::semantics::phase::normalize::{apply_any, normalize_whnf}; use crate::semantics::phase::typecheck::{builtin_to_value, const_to_value}; use crate::semantics::phase::{Normalized, NormalizedExpr, Typed}; @@ -54,8 +54,8 @@ pub(crate) enum Form { #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum ValueKind<Value> { /// Closures - Lam(AlphaLabel, Value, Value), - Pi(AlphaLabel, Value, Value), + Lam(Binder, Value, Value), + Pi(Binder, Value, Value), // Invariant: in whnf, the evaluation must not be able to progress further. AppliedBuiltin(Builtin, Vec<Value>), @@ -393,7 +393,7 @@ impl<V> ValueKind<V> { pub(crate) fn map_ref_with_special_handling_of_binders<'a, V2>( &'a self, mut map_val: impl FnMut(&'a V) -> V2, - mut map_under_binder: impl FnMut(&'a AlphaLabel, &'a V) -> V2, + mut map_under_binder: impl FnMut(&'a Binder, &'a V) -> V2, ) -> ValueKind<V2> { use crate::semantics::visitor; use crate::syntax::trivial_result; diff --git a/dhall/src/semantics/core/var.rs b/dhall/src/semantics/core/var.rs index 017a689..add0500 100644 --- a/dhall/src/semantics/core/var.rs +++ b/dhall/src/semantics/core/var.rs @@ -14,7 +14,9 @@ pub struct AlphaVar { // Exactly like a Label, but equality returns always true. // This is so that ValueKind equality is exactly alpha-equivalence. #[derive(Clone, Eq)] -pub struct AlphaLabel(Label); +pub struct Binder { + name: Label, +} pub(crate) trait Shift: Sized { // Shift an expression to move it around binders without changing the meaning of its free @@ -64,7 +66,10 @@ impl AlphaVar { } } -impl AlphaLabel { +impl Binder { + pub(crate) fn new(name: Label) -> Self { + Binder { name } + } pub(crate) fn to_label_maybe_alpha(&self, alpha: bool) -> Label { if alpha { "_".into() @@ -92,7 +97,7 @@ impl std::cmp::PartialEq for AlphaVar { self.alpha == other.alpha } } -impl std::cmp::PartialEq for AlphaLabel { +impl std::cmp::PartialEq for Binder { fn eq(&self, _other: &Self) -> bool { true } @@ -104,9 +109,9 @@ impl std::fmt::Debug for AlphaVar { } } -impl std::fmt::Debug for AlphaLabel { +impl std::fmt::Debug for Binder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "AlphaLabel({})", &self.0) + write!(f, "Binder({})", &self.name) } } @@ -123,26 +128,21 @@ impl<'a> From<&'a Label> for AlphaVar { x.clone().into() } } -impl From<AlphaLabel> for AlphaVar { - fn from(x: AlphaLabel) -> AlphaVar { +impl From<Binder> for AlphaVar { + fn from(x: Binder) -> AlphaVar { let l: Label = x.into(); l.into() } } -impl<'a> From<&'a AlphaLabel> for AlphaVar { - fn from(x: &'a AlphaLabel) -> AlphaVar { +impl<'a> From<&'a Binder> for AlphaVar { + fn from(x: &'a Binder) -> AlphaVar { x.clone().into() } } -impl From<Label> for AlphaLabel { - fn from(x: Label) -> AlphaLabel { - AlphaLabel(x) - } -} -impl From<AlphaLabel> for Label { - fn from(x: AlphaLabel) -> Label { - x.0 +impl From<Binder> for Label { + fn from(x: Binder) -> Label { + x.name } } impl Shift for () { diff --git a/dhall/src/semantics/core/visitor.rs b/dhall/src/semantics/core/visitor.rs index c7cf79e..2c9ba92 100644 --- a/dhall/src/semantics/core/visitor.rs +++ b/dhall/src/semantics/core/visitor.rs @@ -1,6 +1,6 @@ use std::iter::FromIterator; -use crate::semantics::{AlphaLabel, ValueKind}; +use crate::semantics::{Binder, ValueKind}; use crate::syntax::Label; /// A visitor trait that can be used to traverse `ValueKind`s. We need this pattern so that Rust lets @@ -12,7 +12,7 @@ pub(crate) trait ValueKindVisitor<'a, V1, V2>: Sized { fn visit_val(&mut self, val: &'a V1) -> Result<V2, Self::Error>; fn visit_val_under_binder( mut self, - _label: &'a AlphaLabel, + _label: &'a Binder, val: &'a V1, ) -> Result<V2, Self::Error> { self.visit_val(val) @@ -117,7 +117,7 @@ impl<'a, V1, V2, Err, F1, F2> ValueKindVisitor<'a, V1, V2> where V1: 'a, F1: FnMut(&'a V1) -> Result<V2, Err>, - F2: FnOnce(&'a AlphaLabel, &'a V1) -> Result<V2, Err>, + F2: FnOnce(&'a Binder, &'a V1) -> Result<V2, Err>, { type Error = Err; @@ -126,7 +126,7 @@ where } fn visit_val_under_binder( self, - label: &'a AlphaLabel, + label: &'a Binder, val: &'a V1, ) -> Result<V2, Self::Error> { (self.visit_under_binder)(label, val) diff --git a/dhall/src/semantics/phase/typecheck.rs b/dhall/src/semantics/phase/typecheck.rs index 2e1cc02..926598d 100644 --- a/dhall/src/semantics/phase/typecheck.rs +++ b/dhall/src/semantics/phase/typecheck.rs @@ -4,11 +4,9 @@ use std::collections::HashMap; use crate::error::{TypeError, TypeMessage}; use crate::semantics::core::context::TyCtx; -use crate::semantics::core::value::Value; -use crate::semantics::core::value::ValueKind; -use crate::semantics::core::var::{Shift, Subst}; use crate::semantics::phase::normalize::merge_maps; use crate::semantics::phase::Normalized; +use crate::semantics::{Binder, Shift, Subst, Value, ValueKind}; use crate::syntax; use crate::syntax::{ Builtin, Const, Expr, ExprKind, InterpolatedTextContents, Label, Span, @@ -17,12 +15,12 @@ use crate::syntax::{ fn tck_pi_type( ctx: &TyCtx, - x: Label, + binder: Binder, tx: Value, te: Value, ) -> Result<Value, TypeError> { use TypeMessage::*; - let ctx2 = ctx.insert_type(&x, tx.clone()); + let ctx2 = ctx.insert_type(&binder, tx.clone()); let ka = match tx.get_type()?.as_const() { Some(k) => k, @@ -42,7 +40,7 @@ fn tck_pi_type( let k = function_check(ka, kb); Ok(Value::from_kind_and_type( - ValueKind::Pi(x.into(), tx, te), + ValueKind::Pi(binder, tx, te), Value::from_const(k), )) } @@ -307,21 +305,23 @@ fn type_with(ctx: &TyCtx, e: Expr<Normalized>) -> Result<Value, TypeError> { match e.as_ref() { Lam(var, annot, body) => { + let binder = ctx.new_binder(var); let annot = type_with(ctx, annot.clone())?; annot.normalize_nf(); - let ctx2 = ctx.insert_type(var, annot.clone()); + let ctx2 = ctx.insert_type(&binder, annot.clone()); let body = type_with(&ctx2, body.clone())?; let body_type = body.get_type()?; Ok(Value::from_kind_and_type( - ValueKind::Lam(var.clone().into(), annot.clone(), body), - tck_pi_type(ctx, var.clone(), annot, body_type)?, + ValueKind::Lam(binder.clone(), annot.clone(), body), + tck_pi_type(ctx, binder, annot, body_type)?, )) } Pi(x, ta, tb) => { + let binder = ctx.new_binder(x); let ta = type_with(ctx, ta.clone())?; - let ctx2 = ctx.insert_type(x, ta.clone()); + let ctx2 = ctx.insert_type(&binder, ta.clone()); let tb = type_with(&ctx2, tb.clone())?; - tck_pi_type(ctx, x.clone(), ta, tb) + tck_pi_type(ctx, binder, ta, tb) } Let(x, t, v, e) => { let v = if let Some(t) = t { @@ -331,7 +331,8 @@ fn type_with(ctx: &TyCtx, e: Expr<Normalized>) -> Result<Value, TypeError> { }; let v = type_with(ctx, v)?; - type_with(&ctx.insert_value(x, v.clone())?, e.clone()) + let binder = ctx.new_binder(x); + type_with(&ctx.insert_value(&binder, v.clone())?, e.clone()) } Embed(p) => Ok(p.clone().into_typed().into_value()), Var(var) => match ctx.lookup(&var) { @@ -496,7 +497,7 @@ fn type_last_layer( RetTypeOnly( tck_pi_type( ctx, - x.clone(), + ctx.new_binder(x), t.clone(), r.under_binder(x), )? |