Skip to content

Commit

Permalink
Add basic Hindley-Milner impl
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Aug 30, 2024
1 parent ca540e5 commit 7407165
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ members = [
# chumsky = "0.9.2"
ariadne = "0.4.1" # for nice errors
num = "0.4"
itertools = "0.13.0"
clap = "3.2"

# Tree sitter
Expand All @@ -45,6 +46,7 @@ lsp-types = {version = "0.94.0", optional = true}
serde_json = {version = "1.0.97", optional = true}
serde = {version = "1.0.156", optional = true}


[features]
default = ["lsp"]

Expand Down
2 changes: 2 additions & 0 deletions src/typing/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod abstract_type;
pub mod concrete_type;
pub mod template;
pub mod type_inference;

59 changes: 59 additions & 0 deletions src/typing/type_inference.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Implementes the Hindley-Milner algorithm for Type Inference.

use itertools::Itertools;

use crate::prelude::*;

use crate::alloc::{UUIDMarker, UUID};

struct TypeVariableIDMarker;
impl UUIDMarker for TypeVariableIDMarker {
const DISPLAY_NAME: &'static str = "type_variable_";
}
type TypeVariableID = UUID<TypeVariableIDMarker>;

#[derive(Debug, Clone)]
enum MyType {
TypeFunc(TypeUUID, FlatAlloc<MyType, TemplateIDMarker>),
TypeVar(TypeVariableID),
}

/// Returns false if the types couldn't be unified
fn unify<'t>(substitution_map: &mut FlatAlloc<Option<&'t MyType>, TypeVariableIDMarker>, a: &'t MyType, b: &'t MyType) -> Result<(), ()> {
match a {
MyType::TypeFunc(tf_a, args_a) => {
match b {
MyType::TypeFunc(tf_b, args_b) => {
if tf_a != tf_b {
return Err(());
}
for ((_, arg_a), (_, arg_b)) in args_a.iter().zip_eq(args_b.iter()) {
unify(substitution_map, arg_a, arg_b)?;
}
Ok(())
}
MyType::TypeVar(_) => unify(substitution_map, b, a)
}
}
MyType::TypeVar(var) => {
let typ_cell = &mut substitution_map[*var];
if let Some(found) = typ_cell {
let ff : &'t MyType = *found;
unify(substitution_map, ff, b)
} else {
*typ_cell = Some(b);
Ok(())
}
}
}
}

fn fully_substitute(substitution_map: &mut FlatAlloc<Option<&MyType>, TypeVariableIDMarker>, a: &MyType) -> MyType {
match a {
MyType::TypeFunc(tf, tf_args) => MyType::TypeFunc(*tf, tf_args.map(|(_, arg)| fully_substitute(substitution_map, arg))),
MyType::TypeVar(v) => {
let substituted = substitution_map[*v].expect("This variable wasn't properly substituted");
fully_substitute(substitution_map, substituted)
}
}
}

0 comments on commit 7407165

Please sign in to comment.