diff --git a/src/exec/builtins.rs b/src/exec/builtins.rs index 3547702..ccd9b3c 100644 --- a/src/exec/builtins.rs +++ b/src/exec/builtins.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, rc::Rc, usize}; +use std::{collections::HashMap, rc::Rc}; use crate::{ parse::Constant, @@ -83,9 +83,9 @@ impl DeBrujinBuiltInAst { } } -impl Into for DeBrujinBuiltInAst { - fn into(self) -> DeBrujinAst { - match self { +impl From for DeBrujinAst { + fn from(val: DeBrujinBuiltInAst) -> Self { + match val { DeBrujinBuiltInAst::Abstraction(i, t, ast) => { DeBrujinAst::Abstraction(i, t, Box::new((*ast).into())) } diff --git a/src/exec/mod.rs b/src/exec/mod.rs index ef400ed..696e7e4 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -14,25 +14,25 @@ use crate::{ vec_map::VecMap, }; -impl Into for Ast { - fn into(self) -> DeBrujinAst { - self.to_de_brujin_inter(Rc::new(HashMap::new())) +impl From for DeBrujinAst { + fn from(val: Ast) -> Self { + val.into_de_brujin_inter(Rc::new(HashMap::new())) } } impl Ast { - fn to_de_brujin_inter(self, mut gamma: Rc>) -> DeBrujinAst { + fn into_de_brujin_inter(self, mut gamma: Rc>) -> DeBrujinAst { match self { Ast::Abstraction(var, t, ast) => { let gamma_ref = Rc::make_mut(&mut gamma); gamma_ref.values_mut().for_each(|v| *v += 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( - Box::new(lhs.to_de_brujin_inter(gamma.clone())), - Box::new(rhs.to_de_brujin_inter(gamma)), + Box::new(lhs.into_de_brujin_inter(gamma.clone())), + Box::new(rhs.into_de_brujin_inter(gamma)), ), Ast::Variable(v) => { if let Some(c) = gamma.get(&v) { @@ -55,9 +55,9 @@ pub enum DeBrujinAst { Constant(Constant), // true | false | n } -impl Into for DeBrujinAst { - fn into(self) -> Ast { - self.to_ast(Rc::new(VecMap::new())) +impl From for Ast { + fn from(val: DeBrujinAst) -> Self { + 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 // all the keys every time recuse into an Abstraction, which would be suuper // expensive if not impossible with a HashMap - fn to_ast(self, mut gamma: Rc>) -> Ast { + fn into_ast(self, mut gamma: Rc>) -> Ast { match self { DeBrujinAst::Abstraction(i, t, de_brujin_ast) => { let gamma_ref = Rc::make_mut(&mut gamma); gamma_ref.map_keys(|i| *i += 1); 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( - Box::new(lhs.to_ast(gamma.clone())), - Box::new(rhs.to_ast(gamma)), + Box::new(lhs.into_ast(gamma.clone())), + Box::new(rhs.into_ast(gamma)), ), DeBrujinAst::FreeVariable(i) => Ast::Variable(i), DeBrujinAst::BoundVariable(n) => Ast::Variable( diff --git a/src/inference/recursive.rs b/src/inference/recursive.rs index c6101ea..a70be18 100644 --- a/src/inference/recursive.rs +++ b/src/inference/recursive.rs @@ -25,7 +25,7 @@ fn infer_type_debrujin_int( DeBrujinAst::Abstraction(_, arg_type, ast) => { let gamma_ref = Rc::make_mut(&mut gamma_bound); 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)?; // TODO: Fix this hack @@ -38,7 +38,7 @@ fn infer_type_debrujin_int( return Err(InferError::NotAFunction); }; 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 { return Err(InferError::ExpectedConreteType); }; diff --git a/src/inference/test.rs b/src/inference/test.rs index f2a76a4..30eacd7 100644 --- a/src/inference/test.rs +++ b/src/inference/test.rs @@ -32,10 +32,10 @@ fn infer_add_nat_rec() { TypeTag::Num, "a".to_string(), 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::TypeVariable("a".to_string())), - Box::new(Type::TypeVariable("a".to_string())), + Box::new(Type::Variable("a".to_string())), + Box::new(Type::Variable("a".to_string())), )), ))), ), @@ -63,10 +63,10 @@ fn infer_add_nat_partial_rec() { TypeTag::Num, "a".to_string(), 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::TypeVariable("a".to_string())), - Box::new(Type::TypeVariable("a".to_string())), + Box::new(Type::Variable("a".to_string())), + Box::new(Type::Variable("a".to_string())), )), ))), ), @@ -95,7 +95,7 @@ fn subtype_constraints() { assert_eq!( st_constraints .borrow() - .get(&Type::TypeVariable("?typ_0".to_string())), + .get(&Type::Variable("?typ_0".to_string())), vec![&TypeTag::Num] ); @@ -231,11 +231,9 @@ fn subst_type_var() { TaggedType::Tagged(TypeTag::Any, b, tagged_type) => match *tagged_type { TaggedType::Concrete(typ) => match typ { 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) { - (Type::TypeVariable(b1), Type::TypeVariable(b2)) => { - (b1 == b) && (b2 == b) - } + (Type::Variable(b1), Type::Variable(b2)) => (b1 == b) && (b2 == b), _ => false, } } diff --git a/src/inference/unification.rs b/src/inference/unification.rs index d79c1e4..9362dce 100644 --- a/src/inference/unification.rs +++ b/src/inference/unification.rs @@ -22,6 +22,12 @@ pub struct TypeVarCtx { counter: RefCell, } +impl Default for TypeVarCtx { + fn default() -> Self { + Self::new() + } +} + impl TypeVarCtx { pub fn new() -> Self { Self { @@ -33,7 +39,7 @@ impl TypeVarCtx { let mut num = self.counter.borrow_mut(); let res = format!("?typ_{num}"); *num += 1; - Type::TypeVariable(res) + Type::Variable(res) } } @@ -164,8 +170,7 @@ pub(super) fn step_1( Constant::Nat(_) => Type::Primitive(PrimitiveType::Nat), Constant::Float(_) => Type::Primitive(PrimitiveType::Float), Constant::Bool(_) => Type::Primitive(PrimitiveType::Bool), - } - .into(); + }; RefCell::borrow_mut(&eq_constraints).insert(var.clone(), typ); @@ -230,14 +235,13 @@ impl Subst for TypeVarAst { Box::new(rhs.subst(var, subst)?), )), 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( - typ.subst_typevar(var, &subst)?, + typ.subst_typevar(var, subst)?, constant, )), } @@ -248,7 +252,7 @@ impl Subst for Constraints { fn subst(mut self, var: &str, subst: &Type) -> Result, InferError> { self.into_iter() .map::, _>(|(k, v)| { - Ok((k.subst_typevar(var, &subst)?, v)) + Ok((k.subst_typevar(var, subst)?, v)) }) .collect() } @@ -342,15 +346,13 @@ pub fn infer_type( let mut typ: TaggedType = typ.into(); 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() { typ = TaggedType::Tagged(TypeTag::Any, free_var, Box::new(typ)); } else { let tag = tags .into_iter() - .fold(Some(TypeTag::Any), |acc, t| { - acc.map(|acc| acc.tightens(t.clone())).flatten() - }) + .try_fold(TypeTag::Any, |acc, t| acc.tightens(t.clone())) .ok_or(InferError::ConfilictingTags)?; typ = TaggedType::Tagged(tag, free_var, Box::new(typ)); } @@ -438,7 +440,7 @@ impl TaggedType { impl Type { pub fn subst_typevar(self, var: &str, subst: &Type) -> Result { 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( Box::new(lhs.subst_typevar(var, subst)?), Box::new(rhs.subst_typevar(var, subst)?), diff --git a/src/main.rs b/src/main.rs index 929cfd5..19b50a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, hash_map}, io::{Write, stdin, stdout}, rc::Rc, }; @@ -48,14 +48,14 @@ fn main() { if !is_ident(&ident) { 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, 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"); - gamma.insert(ident, typ.into()); + e.insert(typ); } else { println!("Cannot override existing ctx"); } diff --git a/src/multi_map.rs b/src/multi_map.rs index ba69769..40d1508 100644 --- a/src/multi_map.rs +++ b/src/multi_map.rs @@ -98,7 +98,7 @@ impl Clone for MultiMap { impl Debug for MultiMap { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_map() - .entries(self.map.iter().map(|&(ref k, ref v)| (k, v))) + .entries(self.map.iter().map(|(k, v)| (k, v))) .finish() } } diff --git a/src/parse/tokenize.rs b/src/parse/tokenize.rs index a79093f..c502f80 100644 --- a/src/parse/tokenize.rs +++ b/src/parse/tokenize.rs @@ -99,7 +99,7 @@ impl<'input> Lexer<'input> { } } } -impl<'input> Iterator for Lexer<'input> { +impl Iterator for Lexer<'_> { type Item = Spanned; fn next(&mut self) -> Option { diff --git a/src/types/mod.rs b/src/types/mod.rs index 505ebab..0e31d18 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -29,7 +29,7 @@ pub enum TaggedType { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Type { - TypeVariable(Ident), // a + Variable(Ident), // a Primitive(PrimitiveType), // Bool | Nat Arrow(Box, Box), // 0 -> 1 } @@ -67,7 +67,7 @@ impl TaggedType { } } - pub fn to_concrete(self) -> Option { + pub fn into_concrete(self) -> Option { match self { TaggedType::Tagged(type_tag, _, tagged_type) => None, TaggedType::Concrete(t) => Some(t), @@ -228,7 +228,7 @@ impl From for Type { impl From<&str> for Type { 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 { match self { - Type::TypeVariable(_) => false, + Type::Variable(_) => false, Type::Primitive(primitive_type) => true, Type::Arrow(t1, t2) => t1.is_concrete() && t2.is_concrete(), } @@ -254,19 +254,18 @@ impl Type { pub fn has_tag(&self, tag: &TypeTag) -> bool { match self { - Type::TypeVariable(_) => true, - Type::Primitive(primitive_type) => match (primitive_type, tag) { - (_, TypeTag::Any) => true, - (PrimitiveType::Nat, TypeTag::Num) => true, - _ => false, - }, + Type::Variable(_) => true, + Type::Primitive(primitive_type) => matches!( + (primitive_type, tag), + (_, TypeTag::Any) | (PrimitiveType::Nat, TypeTag::Num) + ), Type::Arrow(_, _) => false, } } pub fn map_name(&mut self, f: &F) { match self { - Type::TypeVariable(v) => f(v), + Type::Variable(v) => f(v), Type::Arrow(lhs, rhs) => { lhs.map_name(f); rhs.map_name(f); @@ -277,7 +276,7 @@ impl Type { pub fn name_used(&self, ident: &str) -> bool { 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), _ => false, } @@ -285,7 +284,7 @@ impl Type { pub fn type_var(&self) -> Option { match self { - Type::TypeVariable(v) => Some(v.clone()), + Type::Variable(v) => Some(v.clone()), Type::Primitive(primitive_type) => None, Type::Arrow(_, _) => None, } @@ -293,7 +292,7 @@ impl Type { pub fn type_vars(&self) -> HashSet { match self { - Type::TypeVariable(v) => { + Type::Variable(v) => { let mut set = HashSet::new(); set.insert(v.to_string()); set @@ -311,7 +310,7 @@ impl Type { fn specialize(self, ident: &str, typ: &Type) -> Type { match self { - Type::TypeVariable(i) if i == ident => typ.clone(), + Type::Variable(i) if i == ident => typ.clone(), Type::Arrow(lhs, rhs) => Type::Arrow( Box::new(lhs.specialize(ident, typ)), Box::new(rhs.specialize(ident, typ)), @@ -344,7 +343,7 @@ impl Display for TaggedType { impl Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Type::TypeVariable(i) => write!(f, "{i}"), + Type::Variable(i) => write!(f, "{i}"), Type::Primitive(primitive_type) => write!(f, "{primitive_type}"), Type::Arrow(t1, t2) => write!(f, "({t1} -> {t2})"), }