main
Avery 1 month ago
parent 987102ac44
commit b1b7d46358
Signed by: Avery
GPG Key ID: 4E53F4CB69B2CC8D

@ -1,4 +1,4 @@
use std::{collections::HashMap, rc::Rc, usize}; use std::{collections::HashMap, rc::Rc};
use crate::{ use crate::{
parse::Constant, parse::Constant,
@ -83,9 +83,9 @@ impl DeBrujinBuiltInAst {
} }
} }
impl Into<DeBrujinAst> for DeBrujinBuiltInAst { impl From<DeBrujinBuiltInAst> for DeBrujinAst {
fn into(self) -> DeBrujinAst { fn from(val: DeBrujinBuiltInAst) -> Self {
match self { match val {
DeBrujinBuiltInAst::Abstraction(i, t, ast) => { DeBrujinBuiltInAst::Abstraction(i, t, ast) => {
DeBrujinAst::Abstraction(i, t, Box::new((*ast).into())) DeBrujinAst::Abstraction(i, t, Box::new((*ast).into()))
} }

@ -14,25 +14,25 @@ use crate::{
vec_map::VecMap, vec_map::VecMap,
}; };
impl Into<DeBrujinAst> for Ast { impl From<Ast> for DeBrujinAst {
fn into(self) -> DeBrujinAst { fn from(val: Ast) -> Self {
self.to_de_brujin_inter(Rc::new(HashMap::new())) val.into_de_brujin_inter(Rc::new(HashMap::new()))
} }
} }
impl Ast { impl Ast {
fn to_de_brujin_inter(self, mut gamma: Rc<HashMap<String, usize>>) -> DeBrujinAst { fn into_de_brujin_inter(self, mut gamma: Rc<HashMap<String, usize>>) -> DeBrujinAst {
match self { match self {
Ast::Abstraction(var, t, ast) => { Ast::Abstraction(var, t, ast) => {
let gamma_ref = Rc::make_mut(&mut gamma); let gamma_ref = Rc::make_mut(&mut gamma);
gamma_ref.values_mut().for_each(|v| *v += 1); gamma_ref.values_mut().for_each(|v| *v += 1);
gamma_ref.insert(var.clone(), 1); gamma_ref.insert(var.clone(), 1);
DeBrujinAst::Abstraction(var, t, Box::new(ast.to_de_brujin_inter(gamma))) DeBrujinAst::Abstraction(var, t, Box::new(ast.into_de_brujin_inter(gamma)))
} }
Ast::Application(lhs, rhs) => DeBrujinAst::Application( Ast::Application(lhs, rhs) => DeBrujinAst::Application(
Box::new(lhs.to_de_brujin_inter(gamma.clone())), Box::new(lhs.into_de_brujin_inter(gamma.clone())),
Box::new(rhs.to_de_brujin_inter(gamma)), Box::new(rhs.into_de_brujin_inter(gamma)),
), ),
Ast::Variable(v) => { Ast::Variable(v) => {
if let Some(c) = gamma.get(&v) { if let Some(c) = gamma.get(&v) {
@ -55,9 +55,9 @@ pub enum DeBrujinAst {
Constant(Constant), // true | false | n Constant(Constant), // true | false | n
} }
impl Into<Ast> for DeBrujinAst { impl From<DeBrujinAst> for Ast {
fn into(self) -> Ast { fn from(val: DeBrujinAst) -> Self {
self.to_ast(Rc::new(VecMap::new())) val.into_ast(Rc::new(VecMap::new()))
} }
} }
@ -65,18 +65,18 @@ impl DeBrujinAst {
// Vec<(usize, String)> as opposed to a HashMap here since we need to mutate // Vec<(usize, String)> as opposed to a HashMap here since we need to mutate
// all the keys every time recuse into an Abstraction, which would be suuper // all the keys every time recuse into an Abstraction, which would be suuper
// expensive if not impossible with a HashMap // expensive if not impossible with a HashMap
fn to_ast(self, mut gamma: Rc<VecMap<usize, String>>) -> Ast { fn into_ast(self, mut gamma: Rc<VecMap<usize, String>>) -> Ast {
match self { match self {
DeBrujinAst::Abstraction(i, t, de_brujin_ast) => { DeBrujinAst::Abstraction(i, t, de_brujin_ast) => {
let gamma_ref = Rc::make_mut(&mut gamma); let gamma_ref = Rc::make_mut(&mut gamma);
gamma_ref.map_keys(|i| *i += 1); gamma_ref.map_keys(|i| *i += 1);
gamma_ref.insert(1, i.clone()); gamma_ref.insert(1, i.clone());
Ast::Abstraction(i, t, Box::new(de_brujin_ast.to_ast(gamma))) Ast::Abstraction(i, t, Box::new(de_brujin_ast.into_ast(gamma)))
} }
DeBrujinAst::Application(lhs, rhs) => Ast::Application( DeBrujinAst::Application(lhs, rhs) => Ast::Application(
Box::new(lhs.to_ast(gamma.clone())), Box::new(lhs.into_ast(gamma.clone())),
Box::new(rhs.to_ast(gamma)), Box::new(rhs.into_ast(gamma)),
), ),
DeBrujinAst::FreeVariable(i) => Ast::Variable(i), DeBrujinAst::FreeVariable(i) => Ast::Variable(i),
DeBrujinAst::BoundVariable(n) => Ast::Variable( DeBrujinAst::BoundVariable(n) => Ast::Variable(

@ -25,7 +25,7 @@ fn infer_type_debrujin_int(
DeBrujinAst::Abstraction(_, arg_type, ast) => { DeBrujinAst::Abstraction(_, arg_type, ast) => {
let gamma_ref = Rc::make_mut(&mut gamma_bound); let gamma_ref = Rc::make_mut(&mut gamma_bound);
gamma_ref.map_keys(|i| *i += 1); gamma_ref.map_keys(|i| *i += 1);
gamma_ref.insert(1, arg_type.clone().unwrap().into()); gamma_ref.insert(1, arg_type.clone().unwrap());
let out_type = infer_type_debrujin_int(gamma_free, gamma_bound, *ast)?; let out_type = infer_type_debrujin_int(gamma_free, gamma_bound, *ast)?;
// TODO: Fix this hack // TODO: Fix this hack
@ -38,7 +38,7 @@ fn infer_type_debrujin_int(
return Err(InferError::NotAFunction); return Err(InferError::NotAFunction);
}; };
let Some(right_type) = let Some(right_type) =
infer_type_debrujin_int(gamma_free, gamma_bound.clone(), *rhs)?.to_concrete() infer_type_debrujin_int(gamma_free, gamma_bound.clone(), *rhs)?.into_concrete()
else { else {
return Err(InferError::ExpectedConreteType); return Err(InferError::ExpectedConreteType);
}; };

@ -32,10 +32,10 @@ fn infer_add_nat_rec() {
TypeTag::Num, TypeTag::Num,
"a".to_string(), "a".to_string(),
Box::new(TaggedType::Concrete(Type::Arrow( Box::new(TaggedType::Concrete(Type::Arrow(
Box::new(Type::TypeVariable("a".to_string())), Box::new(Type::Variable("a".to_string())),
Box::new(Type::Arrow( Box::new(Type::Arrow(
Box::new(Type::TypeVariable("a".to_string())), Box::new(Type::Variable("a".to_string())),
Box::new(Type::TypeVariable("a".to_string())), Box::new(Type::Variable("a".to_string())),
)), )),
))), ))),
), ),
@ -63,10 +63,10 @@ fn infer_add_nat_partial_rec() {
TypeTag::Num, TypeTag::Num,
"a".to_string(), "a".to_string(),
Box::new(TaggedType::Concrete(Type::Arrow( Box::new(TaggedType::Concrete(Type::Arrow(
Box::new(Type::TypeVariable("a".to_string())), Box::new(Type::Variable("a".to_string())),
Box::new(Type::Arrow( Box::new(Type::Arrow(
Box::new(Type::TypeVariable("a".to_string())), Box::new(Type::Variable("a".to_string())),
Box::new(Type::TypeVariable("a".to_string())), Box::new(Type::Variable("a".to_string())),
)), )),
))), ))),
), ),
@ -95,7 +95,7 @@ fn subtype_constraints() {
assert_eq!( assert_eq!(
st_constraints st_constraints
.borrow() .borrow()
.get(&Type::TypeVariable("?typ_0".to_string())), .get(&Type::Variable("?typ_0".to_string())),
vec![&TypeTag::Num] vec![&TypeTag::Num]
); );
@ -231,11 +231,9 @@ fn subst_type_var() {
TaggedType::Tagged(TypeTag::Any, b, tagged_type) => match *tagged_type { TaggedType::Tagged(TypeTag::Any, b, tagged_type) => match *tagged_type {
TaggedType::Concrete(typ) => match typ { TaggedType::Concrete(typ) => match typ {
Type::Arrow(lhs, rhs) => match (*lhs, *rhs) { Type::Arrow(lhs, rhs) => match (*lhs, *rhs) {
(Type::TypeVariable(a1), Type::Arrow(b1, b2)) if a1 == a => { (Type::Variable(a1), Type::Arrow(b1, b2)) if a1 == a => {
match (*b1, *b2) { match (*b1, *b2) {
(Type::TypeVariable(b1), Type::TypeVariable(b2)) => { (Type::Variable(b1), Type::Variable(b2)) => (b1 == b) && (b2 == b),
(b1 == b) && (b2 == b)
}
_ => false, _ => false,
} }
} }

@ -22,6 +22,12 @@ pub struct TypeVarCtx {
counter: RefCell<usize>, counter: RefCell<usize>,
} }
impl Default for TypeVarCtx {
fn default() -> Self {
Self::new()
}
}
impl TypeVarCtx { impl TypeVarCtx {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -33,7 +39,7 @@ impl TypeVarCtx {
let mut num = self.counter.borrow_mut(); let mut num = self.counter.borrow_mut();
let res = format!("?typ_{num}"); let res = format!("?typ_{num}");
*num += 1; *num += 1;
Type::TypeVariable(res) Type::Variable(res)
} }
} }
@ -164,8 +170,7 @@ pub(super) fn step_1(
Constant::Nat(_) => Type::Primitive(PrimitiveType::Nat), Constant::Nat(_) => Type::Primitive(PrimitiveType::Nat),
Constant::Float(_) => Type::Primitive(PrimitiveType::Float), Constant::Float(_) => Type::Primitive(PrimitiveType::Float),
Constant::Bool(_) => Type::Primitive(PrimitiveType::Bool), Constant::Bool(_) => Type::Primitive(PrimitiveType::Bool),
} };
.into();
RefCell::borrow_mut(&eq_constraints).insert(var.clone(), typ); RefCell::borrow_mut(&eq_constraints).insert(var.clone(), typ);
@ -230,14 +235,13 @@ impl Subst for TypeVarAst {
Box::new(rhs.subst(var, subst)?), Box::new(rhs.subst(var, subst)?),
)), )),
TypeVarAst::FreeVariable(typ, x) => { TypeVarAst::FreeVariable(typ, x) => {
Ok(TypeVarAst::FreeVariable(typ.subst_typevar(var, &subst)?, x)) Ok(TypeVarAst::FreeVariable(typ.subst_typevar(var, subst)?, x))
}
TypeVarAst::BoundVariable(typ, i) => {
Ok(TypeVarAst::BoundVariable(typ.subst_typevar(var, subst)?, i))
} }
TypeVarAst::BoundVariable(typ, i) => Ok(TypeVarAst::BoundVariable(
typ.subst_typevar(var, &subst)?,
i,
)),
TypeVarAst::Constant(typ, constant) => Ok(TypeVarAst::Constant( TypeVarAst::Constant(typ, constant) => Ok(TypeVarAst::Constant(
typ.subst_typevar(var, &subst)?, typ.subst_typevar(var, subst)?,
constant, constant,
)), )),
} }
@ -248,7 +252,7 @@ impl Subst for Constraints<TypeTag> {
fn subst(mut self, var: &str, subst: &Type) -> Result<Constraints<TypeTag>, InferError> { fn subst(mut self, var: &str, subst: &Type) -> Result<Constraints<TypeTag>, InferError> {
self.into_iter() self.into_iter()
.map::<Result<(Type, TypeTag), InferError>, _>(|(k, v)| { .map::<Result<(Type, TypeTag), InferError>, _>(|(k, v)| {
Ok((k.subst_typevar(var, &subst)?, v)) Ok((k.subst_typevar(var, subst)?, v))
}) })
.collect() .collect()
} }
@ -342,15 +346,13 @@ pub fn infer_type(
let mut typ: TaggedType = typ.into(); let mut typ: TaggedType = typ.into();
for free_var in typ.free_vars() { for free_var in typ.free_vars() {
let tags = st_constraints.get(&Type::TypeVariable(free_var.clone())); let tags = st_constraints.get(&Type::Variable(free_var.clone()));
if tags.is_empty() { if tags.is_empty() {
typ = TaggedType::Tagged(TypeTag::Any, free_var, Box::new(typ)); typ = TaggedType::Tagged(TypeTag::Any, free_var, Box::new(typ));
} else { } else {
let tag = tags let tag = tags
.into_iter() .into_iter()
.fold(Some(TypeTag::Any), |acc, t| { .try_fold(TypeTag::Any, |acc, t| acc.tightens(t.clone()))
acc.map(|acc| acc.tightens(t.clone())).flatten()
})
.ok_or(InferError::ConfilictingTags)?; .ok_or(InferError::ConfilictingTags)?;
typ = TaggedType::Tagged(tag, free_var, Box::new(typ)); typ = TaggedType::Tagged(tag, free_var, Box::new(typ));
} }
@ -438,7 +440,7 @@ impl TaggedType {
impl Type { impl Type {
pub fn subst_typevar(self, var: &str, subst: &Type) -> Result<Type, InferError> { pub fn subst_typevar(self, var: &str, subst: &Type) -> Result<Type, InferError> {
match self { match self {
Type::TypeVariable(v) if v == var => Ok(subst.clone()), Type::Variable(v) if v == var => Ok(subst.clone()),
Type::Arrow(lhs, rhs) => Ok(Type::Arrow( Type::Arrow(lhs, rhs) => Ok(Type::Arrow(
Box::new(lhs.subst_typevar(var, subst)?), Box::new(lhs.subst_typevar(var, subst)?),
Box::new(rhs.subst_typevar(var, subst)?), Box::new(rhs.subst_typevar(var, subst)?),

@ -1,5 +1,5 @@
use std::{ use std::{
collections::HashMap, collections::{HashMap, hash_map},
io::{Write, stdin, stdout}, io::{Write, stdin, stdout},
rc::Rc, rc::Rc,
}; };
@ -48,14 +48,14 @@ fn main() {
if !is_ident(&ident) { if !is_ident(&ident) {
repl_err!("{ident} is not a valid identifer"); repl_err!("{ident} is not a valid identifer");
} }
let typ = match parse_type_str(&typ) { let typ = match parse_type_str(typ) {
Ok(t) => t, Ok(t) => t,
Err(e) => repl_err!("type could not be parsed {e}"), Err(e) => repl_err!("type could not be parsed {e}"),
}; };
if !gamma.contains_key(&ident) { if let hash_map::Entry::Vacant(e) = gamma.entry(ident.clone()) {
println!("Added {ident} with type {typ} to the context"); println!("Added {ident} with type {typ} to the context");
gamma.insert(ident, typ.into()); e.insert(typ);
} else { } else {
println!("Cannot override existing ctx"); println!("Cannot override existing ctx");
} }

@ -98,7 +98,7 @@ impl<K: Eq + Clone, V: Clone> Clone for MultiMap<K, V> {
impl<K: Eq + Debug, V: Debug> Debug for MultiMap<K, V> { impl<K: Eq + Debug, V: Debug> Debug for MultiMap<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_map() f.debug_map()
.entries(self.map.iter().map(|&(ref k, ref v)| (k, v))) .entries(self.map.iter().map(|(k, v)| (k, v)))
.finish() .finish()
} }
} }

@ -99,7 +99,7 @@ impl<'input> Lexer<'input> {
} }
} }
} }
impl<'input> Iterator for Lexer<'input> { impl Iterator for Lexer<'_> {
type Item = Spanned<Token, usize, ParseError>; type Item = Spanned<Token, usize, ParseError>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {

@ -29,7 +29,7 @@ pub enum TaggedType {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Type { pub enum Type {
TypeVariable(Ident), // a Variable(Ident), // a
Primitive(PrimitiveType), // Bool | Nat Primitive(PrimitiveType), // Bool | Nat
Arrow(Box<Type>, Box<Type>), // 0 -> 1 Arrow(Box<Type>, Box<Type>), // 0 -> 1
} }
@ -67,7 +67,7 @@ impl TaggedType {
} }
} }
pub fn to_concrete(self) -> Option<Type> { pub fn into_concrete(self) -> Option<Type> {
match self { match self {
TaggedType::Tagged(type_tag, _, tagged_type) => None, TaggedType::Tagged(type_tag, _, tagged_type) => None,
TaggedType::Concrete(t) => Some(t), TaggedType::Concrete(t) => Some(t),
@ -228,7 +228,7 @@ impl From<PrimitiveType> for Type {
impl From<&str> for Type { impl From<&str> for Type {
fn from(value: &str) -> Self { fn from(value: &str) -> Self {
Self::TypeVariable(value.to_string()) Self::Variable(value.to_string())
} }
} }
@ -246,7 +246,7 @@ impl Type {
pub fn is_concrete(&self) -> bool { pub fn is_concrete(&self) -> bool {
match self { match self {
Type::TypeVariable(_) => false, Type::Variable(_) => false,
Type::Primitive(primitive_type) => true, Type::Primitive(primitive_type) => true,
Type::Arrow(t1, t2) => t1.is_concrete() && t2.is_concrete(), Type::Arrow(t1, t2) => t1.is_concrete() && t2.is_concrete(),
} }
@ -254,19 +254,18 @@ impl Type {
pub fn has_tag(&self, tag: &TypeTag) -> bool { pub fn has_tag(&self, tag: &TypeTag) -> bool {
match self { match self {
Type::TypeVariable(_) => true, Type::Variable(_) => true,
Type::Primitive(primitive_type) => match (primitive_type, tag) { Type::Primitive(primitive_type) => matches!(
(_, TypeTag::Any) => true, (primitive_type, tag),
(PrimitiveType::Nat, TypeTag::Num) => true, (_, TypeTag::Any) | (PrimitiveType::Nat, TypeTag::Num)
_ => false, ),
},
Type::Arrow(_, _) => false, Type::Arrow(_, _) => false,
} }
} }
pub fn map_name<F: Fn(&mut String)>(&mut self, f: &F) { pub fn map_name<F: Fn(&mut String)>(&mut self, f: &F) {
match self { match self {
Type::TypeVariable(v) => f(v), Type::Variable(v) => f(v),
Type::Arrow(lhs, rhs) => { Type::Arrow(lhs, rhs) => {
lhs.map_name(f); lhs.map_name(f);
rhs.map_name(f); rhs.map_name(f);
@ -277,7 +276,7 @@ impl Type {
pub fn name_used(&self, ident: &str) -> bool { pub fn name_used(&self, ident: &str) -> bool {
match self { match self {
Type::TypeVariable(i) if *i == ident => true, Type::Variable(i) if *i == ident => true,
Type::Arrow(lhs, rhs) => lhs.name_used(ident) || rhs.name_used(ident), Type::Arrow(lhs, rhs) => lhs.name_used(ident) || rhs.name_used(ident),
_ => false, _ => false,
} }
@ -285,7 +284,7 @@ impl Type {
pub fn type_var(&self) -> Option<String> { pub fn type_var(&self) -> Option<String> {
match self { match self {
Type::TypeVariable(v) => Some(v.clone()), Type::Variable(v) => Some(v.clone()),
Type::Primitive(primitive_type) => None, Type::Primitive(primitive_type) => None,
Type::Arrow(_, _) => None, Type::Arrow(_, _) => None,
} }
@ -293,7 +292,7 @@ impl Type {
pub fn type_vars(&self) -> HashSet<String> { pub fn type_vars(&self) -> HashSet<String> {
match self { match self {
Type::TypeVariable(v) => { Type::Variable(v) => {
let mut set = HashSet::new(); let mut set = HashSet::new();
set.insert(v.to_string()); set.insert(v.to_string());
set set
@ -311,7 +310,7 @@ impl Type {
fn specialize(self, ident: &str, typ: &Type) -> Type { fn specialize(self, ident: &str, typ: &Type) -> Type {
match self { match self {
Type::TypeVariable(i) if i == ident => typ.clone(), Type::Variable(i) if i == ident => typ.clone(),
Type::Arrow(lhs, rhs) => Type::Arrow( Type::Arrow(lhs, rhs) => Type::Arrow(
Box::new(lhs.specialize(ident, typ)), Box::new(lhs.specialize(ident, typ)),
Box::new(rhs.specialize(ident, typ)), Box::new(rhs.specialize(ident, typ)),
@ -344,7 +343,7 @@ impl Display for TaggedType {
impl Display for Type { impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Type::TypeVariable(i) => write!(f, "{i}"), Type::Variable(i) => write!(f, "{i}"),
Type::Primitive(primitive_type) => write!(f, "{primitive_type}"), Type::Primitive(primitive_type) => write!(f, "{primitive_type}"),
Type::Arrow(t1, t2) => write!(f, "({t1} -> {t2})"), Type::Arrow(t1, t2) => write!(f, "({t1} -> {t2})"),
} }

Loading…
Cancel
Save