From ec28905d32c23109da17696faefab284fde3e103 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 18 Jan 2020 18:46:09 +0000 Subject: Introduce intermediate representation that stores typed expr --- dhall/src/semantics/tck/mod.rs | 2 + dhall/src/semantics/tck/tyexpr.rs | 83 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 dhall/src/semantics/tck/mod.rs create mode 100644 dhall/src/semantics/tck/tyexpr.rs (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/mod.rs b/dhall/src/semantics/tck/mod.rs new file mode 100644 index 0000000..407605d --- /dev/null +++ b/dhall/src/semantics/tck/mod.rs @@ -0,0 +1,2 @@ +pub mod tyexpr; +pub(crate) use tyexpr::*; diff --git a/dhall/src/semantics/tck/tyexpr.rs b/dhall/src/semantics/tck/tyexpr.rs new file mode 100644 index 0000000..a8b8e58 --- /dev/null +++ b/dhall/src/semantics/tck/tyexpr.rs @@ -0,0 +1,83 @@ +#![allow(dead_code)] +use crate::semantics::core::var::AlphaVar; +use crate::semantics::phase::typecheck::rc; +use crate::semantics::phase::Normalized; +use crate::semantics::phase::{NormalizedExpr, ToExprOptions}; +use crate::semantics::Value; +use crate::syntax::{ExprKind, Label, Span, V}; + +pub(crate) type Type = Value; + +// An expression with inferred types at every node and resolved variables. +pub(crate) struct TyExpr { + kind: Box, + ty: Option, + span: Span, +} + +pub(crate) enum TyExprKind { + Var(AlphaVar), + // Forbidden ExprKind variants: Var + Expr(ExprKind), +} + +impl TyExpr { + pub fn new(kind: TyExprKind, ty: Option, span: Span) -> Self { + TyExpr { + kind: Box::new(kind), + ty, + span, + } + } + + pub fn kind(&self) -> &TyExprKind { + &*self.kind + } + + /// Converts a value back to the corresponding AST expression. + pub fn to_expr<'a>(&'a self, opts: ToExprOptions) -> NormalizedExpr { + tyexpr_to_expr(self, opts, &Vec::new()) + } +} + +// TODO: mutate context once map_ref gets simplified +fn tyexpr_to_expr<'a>( + tyexpr: &'a TyExpr, + opts: ToExprOptions, + ctx: &Vec<&'a Label>, +) -> NormalizedExpr { + rc(match tyexpr.kind() { + TyExprKind::Var(v) if opts.alpha => { + ExprKind::Var(V("_".into(), v.idx())) + } + TyExprKind::Var(v) => { + let name = ctx[ctx.len() - 1 - v.idx()]; + let mut idx = 0; + for l in ctx.iter().rev().take(v.idx()) { + if *l == name { + idx += 1; + } + } + ExprKind::Var(V(name.clone(), idx)) + } + TyExprKind::Expr(e) => { + let e = e.map_ref_with_special_handling_of_binders( + |tye| tyexpr_to_expr(tye, opts, ctx), + |l, tye| { + let ctx = ctx.iter().copied().chain(Some(l)).collect(); + tyexpr_to_expr(tye, opts, &ctx) + }, + ); + + match e { + ExprKind::Lam(_, t, e) if opts.alpha => { + ExprKind::Lam("_".into(), t, e) + } + ExprKind::Pi(_, t, e) if opts.alpha => { + ExprKind::Pi("_".into(), t, e) + } + e => e, + } + } + }) +} -- cgit v1.2.3 From d6e5c56a5ef1d5f2b7cafd4a8fb44ce038932547 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 18 Jan 2020 19:08:34 +0000 Subject: Add Expr visitor and improve tyexpr_to_expr --- dhall/src/semantics/tck/tyexpr.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/tyexpr.rs b/dhall/src/semantics/tck/tyexpr.rs index a8b8e58..f0fcdd1 100644 --- a/dhall/src/semantics/tck/tyexpr.rs +++ b/dhall/src/semantics/tck/tyexpr.rs @@ -36,15 +36,14 @@ impl TyExpr { /// Converts a value back to the corresponding AST expression. pub fn to_expr<'a>(&'a self, opts: ToExprOptions) -> NormalizedExpr { - tyexpr_to_expr(self, opts, &Vec::new()) + tyexpr_to_expr(self, opts, &mut Vec::new()) } } -// TODO: mutate context once map_ref gets simplified fn tyexpr_to_expr<'a>( tyexpr: &'a TyExpr, opts: ToExprOptions, - ctx: &Vec<&'a Label>, + ctx: &mut Vec<&'a Label>, ) -> NormalizedExpr { rc(match tyexpr.kind() { TyExprKind::Var(v) if opts.alpha => { @@ -61,13 +60,16 @@ fn tyexpr_to_expr<'a>( ExprKind::Var(V(name.clone(), idx)) } TyExprKind::Expr(e) => { - let e = e.map_ref_with_special_handling_of_binders( - |tye| tyexpr_to_expr(tye, opts, ctx), - |l, tye| { - let ctx = ctx.iter().copied().chain(Some(l)).collect(); - tyexpr_to_expr(tye, opts, &ctx) - }, - ); + let e = e.map_ref_maybe_binder(|l, tye| { + if let Some(l) = l { + ctx.push(l); + } + let e = tyexpr_to_expr(tye, opts, ctx); + if let Some(_) = l { + ctx.pop(); + } + e + }); match e { ExprKind::Lam(_, t, e) if opts.alpha => { -- cgit v1.2.3 From aec80599f161096b68cac88ffb8852a61b62fcfa Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 19 Jan 2020 18:30:13 +0000 Subject: Restore more types in value_to_tyexpr --- dhall/src/semantics/tck/mod.rs | 2 ++ dhall/src/semantics/tck/tyexpr.rs | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/mod.rs b/dhall/src/semantics/tck/mod.rs index 407605d..ba95847 100644 --- a/dhall/src/semantics/tck/mod.rs +++ b/dhall/src/semantics/tck/mod.rs @@ -1,2 +1,4 @@ +pub mod context; pub mod tyexpr; +pub mod typecheck; pub(crate) use tyexpr::*; diff --git a/dhall/src/semantics/tck/tyexpr.rs b/dhall/src/semantics/tck/tyexpr.rs index f0fcdd1..36cae04 100644 --- a/dhall/src/semantics/tck/tyexpr.rs +++ b/dhall/src/semantics/tck/tyexpr.rs @@ -1,4 +1,6 @@ #![allow(dead_code)] +use crate::error::{TypeError, TypeMessage}; +use crate::semantics::core::context::TyCtx; use crate::semantics::core::var::AlphaVar; use crate::semantics::phase::typecheck::rc; use crate::semantics::phase::Normalized; @@ -33,11 +35,21 @@ impl TyExpr { pub fn kind(&self) -> &TyExprKind { &*self.kind } + pub fn get_type(&self) -> Result { + match &self.ty { + Some(t) => Ok(t.clone()), + None => Err(TypeError::new(&TyCtx::new(), TypeMessage::Sort)), + } + } /// Converts a value back to the corresponding AST expression. - pub fn to_expr<'a>(&'a self, opts: ToExprOptions) -> NormalizedExpr { + pub fn to_expr(&self, opts: ToExprOptions) -> NormalizedExpr { tyexpr_to_expr(self, opts, &mut Vec::new()) } + // TODO: temporary hack + pub fn to_value(&self) -> Value { + todo!() + } } fn tyexpr_to_expr<'a>( -- cgit v1.2.3 From c448698f797f2304dca0e0b8b833959de00ca079 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 20 Jan 2020 15:27:19 +0000 Subject: Reimplement basic tck/nze with proper environments Inspired from dhall_haskell --- dhall/src/semantics/tck/tyexpr.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/tyexpr.rs b/dhall/src/semantics/tck/tyexpr.rs index 36cae04..72f5b1d 100644 --- a/dhall/src/semantics/tck/tyexpr.rs +++ b/dhall/src/semantics/tck/tyexpr.rs @@ -11,15 +11,17 @@ use crate::syntax::{ExprKind, Label, Span, V}; pub(crate) type Type = Value; // An expression with inferred types at every node and resolved variables. +#[derive(Debug, Clone)] pub(crate) struct TyExpr { kind: Box, ty: Option, span: Span, } +#[derive(Debug, Clone)] pub(crate) enum TyExprKind { Var(AlphaVar), - // Forbidden ExprKind variants: Var + // Forbidden ExprKind variants: Var, Import, Embed Expr(ExprKind), } @@ -63,12 +65,12 @@ fn tyexpr_to_expr<'a>( } TyExprKind::Var(v) => { let name = ctx[ctx.len() - 1 - v.idx()]; - let mut idx = 0; - for l in ctx.iter().rev().take(v.idx()) { - if *l == name { - idx += 1; - } - } + let idx = ctx + .iter() + .rev() + .take(v.idx()) + .filter(|l| **l == name) + .count(); ExprKind::Var(V(name.clone(), idx)) } TyExprKind::Expr(e) => { -- cgit v1.2.3 From 015b24b04128cbf5a60fbc8ac3f526306ca27378 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 21 Jan 2020 17:43:44 +0000 Subject: Simplify type error type --- dhall/src/semantics/tck/tyexpr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/tyexpr.rs b/dhall/src/semantics/tck/tyexpr.rs index 72f5b1d..983f3f8 100644 --- a/dhall/src/semantics/tck/tyexpr.rs +++ b/dhall/src/semantics/tck/tyexpr.rs @@ -1,6 +1,5 @@ #![allow(dead_code)] use crate::error::{TypeError, TypeMessage}; -use crate::semantics::core::context::TyCtx; use crate::semantics::core::var::AlphaVar; use crate::semantics::phase::typecheck::rc; use crate::semantics::phase::Normalized; @@ -40,7 +39,7 @@ impl TyExpr { pub fn get_type(&self) -> Result { match &self.ty { Some(t) => Ok(t.clone()), - None => Err(TypeError::new(&TyCtx::new(), TypeMessage::Sort)), + None => Err(TypeError::new(TypeMessage::Sort)), } } -- cgit v1.2.3 From 9e7cc77b6a25569b61340f39a2058e23cdc4a437 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 23 Jan 2020 22:22:01 +0000 Subject: Implement basic env-based normalization for Value-based TyExpr --- dhall/src/semantics/tck/tyexpr.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/tyexpr.rs b/dhall/src/semantics/tck/tyexpr.rs index 983f3f8..c8be3a3 100644 --- a/dhall/src/semantics/tck/tyexpr.rs +++ b/dhall/src/semantics/tck/tyexpr.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use crate::error::{TypeError, TypeMessage}; use crate::semantics::core::var::AlphaVar; +use crate::semantics::phase::normalize::{normalize_tyexpr_whnf, NzEnv}; use crate::semantics::phase::typecheck::rc; use crate::semantics::phase::Normalized; use crate::semantics::phase::{NormalizedExpr, ToExprOptions}; @@ -51,6 +52,13 @@ impl TyExpr { pub fn to_value(&self) -> Value { todo!() } + + pub fn normalize_whnf(&self, env: &NzEnv) -> Value { + normalize_tyexpr_whnf(self, env) + } + pub fn normalize_whnf_noenv(&self) -> Value { + normalize_tyexpr_whnf(self, &NzEnv::new()) + } } fn tyexpr_to_expr<'a>( -- cgit v1.2.3 From b72f0968ac19058b9cc513ab0ed1785133232a3d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 24 Jan 2020 21:33:21 +0000 Subject: Implement basic typecheck with new approach --- dhall/src/semantics/tck/typecheck.rs | 147 +++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 dhall/src/semantics/tck/typecheck.rs (limited to 'dhall/src/semantics/tck') diff --git a/dhall/src/semantics/tck/typecheck.rs b/dhall/src/semantics/tck/typecheck.rs new file mode 100644 index 0000000..aab5f83 --- /dev/null +++ b/dhall/src/semantics/tck/typecheck.rs @@ -0,0 +1,147 @@ +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unreachable_code)] +#![allow(unused_imports)] +use std::borrow::Cow; +use std::cmp::max; +use std::collections::HashMap; + +use crate::error::{TypeError, TypeMessage}; +use crate::semantics::core::context::TyCtx; +use crate::semantics::nze::{NameEnv, QuoteEnv}; +use crate::semantics::phase::normalize::{merge_maps, NzEnv}; +use crate::semantics::phase::Normalized; +use crate::semantics::{ + AlphaVar, Binder, Closure, TyExpr, TyExprKind, Type, Value, ValueKind, +}; +use crate::syntax; +use crate::syntax::{ + Builtin, Const, Expr, ExprKind, InterpolatedTextContents, Label, Span, + UnspannedExpr, V, +}; + +#[derive(Debug, Clone)] +pub(crate) struct TyEnv { + names: NameEnv, + items: NzEnv, +} + +impl TyEnv { + pub fn new() -> Self { + TyEnv { + names: NameEnv::new(), + items: NzEnv::new(), + } + } + pub fn as_quoteenv(&self) -> QuoteEnv { + self.names.as_quoteenv() + } + pub fn as_nzenv(&self) -> &NzEnv { + &self.items + } + pub fn as_nameenv(&self) -> &NameEnv { + &self.names + } + + pub fn insert_type(&self, x: &Label, t: Value) -> Self { + TyEnv { + names: self.names.insert(x), + items: self.items.insert_type(t), + } + } + pub fn insert_value(&self, x: &Label, e: Value) -> Self { + TyEnv { + names: self.names.insert(x), + items: self.items.insert_value(e), + } + } + pub fn lookup_var(&self, var: &V