diff --git a/bidir/src/bidir_debruijn.rs b/bidir/src/bidir_debruijn.rs index 34b2aa7..c026266 100644 --- a/bidir/src/bidir_debruijn.rs +++ b/bidir/src/bidir_debruijn.rs @@ -1,7 +1,7 @@ -use anyhow::{bail, Result}; +use anyhow::{bail, ensure, Result}; use crate::data_debruijn::{ - Context, ContextEntry, ContextIndex, Monotype, Term, Type, + Context, ContextEntry, ContextIndex, Monotype, Term, Type, Visitor, }; use crate::DEPTH; @@ -105,6 +105,11 @@ pub fn instantiate_left( .get_mut(b.debruijn_level) .expect("should exist"); + ensure!( + matches!(b_entry, ContextEntry::ExistentialVar), + "not an existential variable" + ); + *b_entry = ContextEntry::ExistentialSolved(Monotype::Existential(a.to_owned())); } @@ -173,37 +178,59 @@ pub fn synthesize(ctx: &Context, term: &Term) -> Result<(Type, Context)> { // →I⇒' rule Term::Lam(e) => { - let (aug_ctx, marker_idx) = ctx.add(ContextEntry::Marker); - let (aug_ctx_at_a, ex_a_idx) = aug_ctx.add(ContextEntry::ExistentialVar); + let (aug_ctx, marker_idx) = ctx.add(ContextEntry::Marker)?; + let (aug_ctx_at_a, ex_a_idx) = + aug_ctx.add(ContextEntry::ExistentialVar)?; let (aug_ctx_at_b, ex_b_idx) = - aug_ctx_at_a.add(ContextEntry::ExistentialVar); + aug_ctx_at_a.add(ContextEntry::ExistentialVar)?; let ex_a = Type::Existential(ex_a_idx.clone()); let ex_b = Type::Existential(ex_b_idx.clone()); let (aug_ctx, _annot_idx) = - aug_ctx_at_b.add(ContextEntry::TermAnnot(ex_a.clone())); + aug_ctx_at_b.add(ContextEntry::TermAnnot(ex_a.clone()))?; - let ex_a_2 = ex_b.bump_indexes(&aug_ctx_at_a, &aug_ctx, 2); - let ex_b_2 = ex_b.bump_indexes(&aug_ctx_at_b, &aug_ctx, 1); + struct V(usize, usize); + impl Visitor for V { + fn visit_index(&self, index: &mut ContextIndex) -> Result<()> { + index.debruijn_index += self.0; + index.debruijn_level = self.1 - 1 - index.debruijn_index; + Ok(()) + } + } - // TODO: Rewrite all indexes in this term - let e_2 = e.bump_indexes(ctx, &aug_ctx, 0); + let ex_a_2 = ex_b.transform_with_visitor(&V(2, aug_ctx.size()))?; + let ex_b_2 = ex_b.transform_with_visitor(&V(1, aug_ctx.size()))?; + let e_2 = e.transform_with_visitor(&V(0, aug_ctx.size()))?; + println!("---"); let wtf_ctx = typecheck(&aug_ctx, &e_2, &ex_b_2)?; let (before_marker, after_marker) = wtf_ctx.split_at(&marker_idx); - let tau = Type::Arrow(Box::new(ex_a_2), Box::new(ex_b)); - let mut tau = app_ctx(&after_marker, &tau)?; - let (final_ctx, gen_idx) = - before_marker.add(ContextEntry::ExistentialVar); - - for index in after_marker.unsolved_existentials() { - tau = tau.subst(&index, Type::Var(gen_idx.clone())); + // Bump the levels down since we're splitting teh array + struct V2(usize); + impl Visitor for V2 { + fn visit_index(&self, index: &mut ContextIndex) -> Result<()> { + index.debruijn_level -= 1; + index.debruijn_index = self.0 - 1 - index.debruijn_level; + Ok(()) + } } + let after_marker = + after_marker.transform_with_visitor(&V2(after_marker.size()))?; - Ok((Type::Polytype(Box::new(tau)), final_ctx)) + let tau = Type::Arrow(Box::new(ex_a_2), Box::new(ex_b)); + println!("pre-tau: {tau:?} (in {after_marker:?})"); + let tau = app_ctx(&after_marker, &tau)?; + + // let (final_ctx, gen_idx) = + // before_marker.add(ContextEntry::ExistentialVar); + // for index in after_marker.unsolved_existentials() { + // tau = tau.subst(&index, Type::Var(gen_idx.clone())); + // } + + Ok((Type::Polytype(Box::new(tau)), before_marker)) } Term::Annot(_, _) => todo!(), @@ -224,7 +251,7 @@ pub fn app_synthesize( // ∀App rule (Type::Polytype(ty_a), e) => { - let (aug_ctx, a_idx) = ctx.add(ContextEntry::ExistentialVar); + let (aug_ctx, a_idx) = ctx.add(ContextEntry::ExistentialVar)?; let aug_ty = ty_a.subst(&a_idx, Type::Existential(a_idx.clone())); let (ty, ctx_delta) = app_synthesize(&aug_ctx, &aug_ty, e)?; diff --git a/bidir/src/data_debruijn.rs b/bidir/src/data_debruijn.rs index bfc9ad6..bdf9f57 100644 --- a/bidir/src/data_debruijn.rs +++ b/bidir/src/data_debruijn.rs @@ -1,5 +1,6 @@ use std::fmt::{self}; +use anyhow::Result; use im::Vector; use crate::{data, gensym::gensym_type}; @@ -37,36 +38,57 @@ impl fmt::Debug for Term { } impl Term { - pub fn bump_indexes( + // pub fn bump_indexes( + // &self, + // old_ctx: &Context, + // new_ctx: &Context, + // by: usize, + // ) -> Term { + // match self { + // Term::Unit => Term::Unit, + // Term::Var(index) => { + // let debruijn_index = index.debruijn_index + by; + // let debruijn_level = new_ctx.vector.len() - 1 - debruijn_index; + // let new_index = ContextIndex { + // debruijn_index, + // debruijn_level, + // }; + // Term::Var(new_index) + // } + // Term::Lam(body) => { + // Term::Lam(Box::new(body.bump_indexes(old_ctx, new_ctx, by))) + // } + // Term::App(e1, e2) => Term::App( + // Box::new(e1.bump_indexes(old_ctx, new_ctx, by)), + // Box::new(e2.bump_indexes(old_ctx, new_ctx, by)), + // ), + // Term::Annot(e, ty) => + // // TODO: Should i bump indexes in the type too (PROBABLY) + // { + // Term::Annot(Box::new(e.bump_indexes(old_ctx, new_ctx, by)), ty.clone()) + // } + // } + // } + + pub fn transform_with_visitor( &self, - old_ctx: &Context, - new_ctx: &Context, - by: usize, - ) -> Term { - match self { - Term::Unit => Term::Unit, + visitor: &V, + ) -> Result { + let mut expr = self.clone(); + visitor.visit_term_before(&mut expr)?; + let mut expr = match expr { Term::Var(index) => { - let debruijn_index = index.debruijn_index + by; - let debruijn_level = new_ctx.vector.len() - 1 - debruijn_index; - let new_index = ContextIndex { - debruijn_index, - debruijn_level, - }; - Term::Var(new_index) + let mut index = index.clone(); + visitor.visit_index(&mut index)?; + Term::Var(index) } - Term::Lam(body) => { - Term::Lam(Box::new(body.bump_indexes(old_ctx, new_ctx, by))) - } - Term::App(e1, e2) => Term::App( - Box::new(e1.bump_indexes(old_ctx, new_ctx, by)), - Box::new(e2.bump_indexes(old_ctx, new_ctx, by)), - ), - Term::Annot(e, ty) => - // TODO: Should i bump indexes in the type too (PROBABLY) - { - Term::Annot(Box::new(e.bump_indexes(old_ctx, new_ctx, by)), ty.clone()) - } - } + Term::Lam(_) => todo!(), + Term::App(_, _) => todo!(), + Term::Annot(_, _) => todo!(), + _ => expr, + }; + visitor.visit_term_after(&mut expr)?; + Ok(expr) } } @@ -116,31 +138,23 @@ impl Type { self.try_into_mono().is_some() } - pub fn bump_indexes( - &self, - old_ctx: &Context, - new_ctx: &Context, - by: usize, - ) -> Type { - match self { - Type::Unit => Type::Unit, - Type::Var(_) => todo!(), - Type::Existential(index) => { - let debruijn_index = index.debruijn_index + by; - let debruijn_level = new_ctx.vector.len() - 1 - debruijn_index; - let new_index = ContextIndex { - debruijn_index, - debruijn_level, - }; - Type::Existential(new_index) - } - Type::Polytype(_) => todo!(), - Type::Arrow(_, _) => todo!(), - } - } -} + // pub fn bump_indexes(&self, by: usize) -> Type { + // match self { + // Type::Unit => Type::Unit, + // Type::Var(_) => todo!(), + // Type::Existential(index) => { + // let debruijn_index = index.debruijn_index + by; + // let new_index = ContextIndex { + // debruijn_index, + // debruijn_level: index.debruijn_level, + // }; + // Type::Existential(new_index) + // } + // Type::Polytype(_) => todo!(), + // Type::Arrow(_, _) => todo!(), + // } + // } -impl Type { // pub fn free_vars(&self) -> HashSet { // fn free_vars_with_context(ctx: &Context, ty: &Type) -> HashSet { // match ty { @@ -203,6 +217,27 @@ impl Type { ), } } + + pub fn transform_with_visitor( + &self, + visitor: &V, + ) -> Result { + let mut ty = self.clone(); + visitor.visit_type_before(&mut ty)?; + let mut ty = match ty { + Type::Var(_) => todo!(), + Type::Existential(index) => { + let mut index = index.clone(); + visitor.visit_index(&mut index)?; + Type::Existential(index) + } + Type::Polytype(_) => todo!(), + Type::Arrow(_, _) => todo!(), + _ => ty, + }; + visitor.visit_type_after(&mut ty)?; + Ok(ty) + } } #[derive(Debug, Clone)] @@ -224,6 +259,54 @@ impl Monotype { } } } + + // pub fn bump_indexes(&self, by: isize) -> Monotype { + // match self { + // Monotype::Unit => Monotype::Unit, + // Monotype::Var(index) => { + // let debruijn_index = (index.debruijn_index as isize + by) as usize; + // // let debruijn_level = new_ctx.vector.len() - 1 - debruijn_index; + // let new_index = ContextIndex { + // debruijn_index, + // debruijn_level: index.debruijn_level, + // }; + // Monotype::Var(new_index) + // } + // Monotype::Existential(index) => { + // let debruijn_index = (index.debruijn_index as isize + by) as usize; + // // let debruijn_level = new_ctx.vector.len() - 1 - debruijn_index; + // let new_index = ContextIndex { + // debruijn_index, + // debruijn_level: index.debruijn_level, + // }; + // Monotype::Var(new_index) + // } + // Monotype::Arrow(a, b) => Monotype::Arrow( + // Box::new(a.bump_indexes(by)), + // Box::new(b.bump_indexes(by)), + // ), + // } + // } + + pub fn transform_with_visitor( + &self, + visitor: &V, + ) -> Result { + let mut ty = self.clone(); + visitor.visit_monotype_before(&mut ty)?; + let mut ty = match ty { + Monotype::Var(_) => todo!(), + Monotype::Existential(index) => { + let mut index = index.clone(); + visitor.visit_index(&mut index)?; + Monotype::Existential(index) + } + Monotype::Arrow(_, _) => todo!(), + _ => ty, + }; + visitor.visit_monotype_after(&mut ty)?; + Ok(ty) + } } #[derive(Clone)] @@ -289,18 +372,34 @@ impl Default for Context { } impl Context { - pub fn add(&self, item: ContextEntry) -> (Context, ContextIndex) { + #[inline] + pub fn size(&self) -> usize { + self.vector.len() + } + + pub fn add(&self, item: ContextEntry) -> Result<(Context, ContextIndex)> { let idx = self.vector.len(); - let mut new_ctx = self.bump_indexes(1); + struct V; + impl Visitor for V { + fn visit_index(&self, index: &mut ContextIndex) -> Result<()> { + index.debruijn_index += 1; + Ok(()) + } + } + let mut new_ctx = self.transform_with_visitor(&V)?; new_ctx.vector.push_back(item); let idx = ContextIndex { debruijn_index: 0, debruijn_level: idx, }; - (new_ctx, idx) + Ok((new_ctx, idx)) } + // /// Pops items from the end of the context, changing all of the indexes in the + // /// process + // pub fn pop(&self) -> Context {} + pub fn get<'a>(&'a self, index: &ContextIndex) -> Option<&ContextEntry> { let item = self.vector.get(index.debruijn_level)?; Some(item) @@ -347,10 +446,7 @@ impl Context { /// Splits the context pub fn split_at(&self, index: &ContextIndex) -> (Context, Context) { - let (before, after) = { - // let idx = self.vector.iter().position(p)?; - self.vector.clone().split_at(index.debruijn_level) - }; + let (before, after) = self.vector.clone().split_at(index.debruijn_level); (Context { vector: before }, Context { vector: after }) } @@ -411,21 +507,56 @@ impl Context { .all(|item| ensure_item_validity(self, item)) } - pub fn bump_indexes(&self, by: usize) -> Context { - Context { + pub fn transform_with_visitor( + &self, + visitor: &V, + ) -> Result { + Ok(Context { vector: self .vector .iter() - .map(|entry| match entry { - ContextEntry::TypeVar => ContextEntry::TypeVar, - ContextEntry::TermAnnot(_) => todo!(), - ContextEntry::ExistentialVar => ContextEntry::ExistentialVar, - ContextEntry::ExistentialSolved(_) => todo!(), - ContextEntry::Marker => ContextEntry::Marker, + .map(|entry| { + let mut entry = entry.clone(); + visitor.visit_context_entry_before(&mut entry)?; + let mut entry = match entry { + ContextEntry::TermAnnot(ty) => { + ContextEntry::TermAnnot(ty.transform_with_visitor(visitor)?) + } + ContextEntry::ExistentialSolved(ty) => { + ContextEntry::ExistentialSolved( + ty.transform_with_visitor(visitor)?, + ) + } + _ => entry, + }; + visitor.visit_context_entry_after(&mut entry)?; + Ok(entry) }) - .collect(), - } + .collect::>()?, + }) } + + // pub fn bump_indexes(&self, by: isize) -> Context { + // Context { + // vector: self + // .vector + // .iter() + // .map(|entry| match entry { + // ContextEntry::TypeVar => ContextEntry::TypeVar, + // ContextEntry::TermAnnot(ty) => { + // todo!() + // // ContextEntry::TermAnnot(ty.bump_indexes(by)) + // } + // ContextEntry::ExistentialVar => ContextEntry::ExistentialVar, + // ContextEntry::ExistentialSolved(ty) => { + // todo!() + // // ContextEntry::ExistentialSolved(ty.bump_indexes(-1)) + // } + // ContextEntry::Marker => ContextEntry::Marker, + // }) + // .collect(), + // } + // } } /// An index into the context. @@ -507,3 +638,33 @@ pub fn convert_term(term: &data::Term) -> Term { term, ) } + +pub trait Visitor { + fn visit_context_entry_before(&self, expr: &mut ContextEntry) -> Result<()> { + Ok(()) + } + fn visit_context_entry_after(&self, expr: &mut ContextEntry) -> Result<()> { + Ok(()) + } + fn visit_type_before(&self, expr: &mut Type) -> Result<()> { + Ok(()) + } + fn visit_type_after(&self, expr: &mut Type) -> Result<()> { + Ok(()) + } + fn visit_monotype_before(&self, expr: &mut Monotype) -> Result<()> { + Ok(()) + } + fn visit_monotype_after(&self, expr: &mut Monotype) -> Result<()> { + Ok(()) + } + fn visit_term_before(&self, expr: &mut Term) -> Result<()> { + Ok(()) + } + fn visit_term_after(&self, expr: &mut Term) -> Result<()> { + Ok(()) + } + fn visit_index(&self, index: &mut ContextIndex) -> Result<()> { + Ok(()) + } +}