Skip to content

Commit

Permalink
Merge pull request #118 from ditto-lang/fix-type-alias-checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Jordan Mackie authored Jan 3, 2023
2 parents e41bdbd + 45b4c25 commit 7c8cdbd
Show file tree
Hide file tree
Showing 13 changed files with 1,753 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fn read_module_dir<P: AsRef<std::path::Path>>(
modules
}

fn main() {
fn run() {
let mut everything = ditto_checker::Everything::default();

let mut package_paths = Vec::new();
Expand Down Expand Up @@ -106,3 +106,17 @@ fn main() {

serde_json::to_writer_pretty(std::io::stdout(), &module).unwrap();
}

fn main() {
let builder = std::thread::Builder::new();

let handler = builder
.stack_size(
// 32 MB
32 * 1024 * 1024,
)
.spawn(run)
.unwrap();

handler.join().unwrap();
}
8 changes: 4 additions & 4 deletions crates/ditto-checker/src/kindchecker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ pub use substitution::*;
use crate::result::{Result, TypeError};
use ditto_ast::{Kind, Name, QualifiedProperName, Row, Span, Type};
use ditto_cst as cst;
use indexmap::IndexSet;
use non_empty_vec::NonEmpty;
use std::collections::HashSet;

#[cfg(test)]
pub fn kindcheck(
Expand Down Expand Up @@ -377,13 +377,13 @@ fn occurs_check(span: Span, var: usize, kind: &Kind) -> Result<()> {
Ok(())
}

pub fn kind_variables(kind: &Kind) -> HashSet<usize> {
let mut accum = HashSet::new();
pub fn kind_variables(kind: &Kind) -> IndexSet<usize> {
let mut accum = IndexSet::new();
kind_variables_rec(kind, &mut accum);
accum
}

fn kind_variables_rec(kind: &Kind, accum: &mut HashSet<usize>) {
fn kind_variables_rec(kind: &Kind, accum: &mut IndexSet<usize>) {
match kind {
Kind::Variable(var) => {
accum.insert(*var);
Expand Down
24 changes: 10 additions & 14 deletions crates/ditto-checker/src/typechecker/common.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use ditto_ast::{Name, Type};
use ditto_cst as cst;
use std::collections::HashSet;
use indexmap::IndexSet;

pub fn type_variables(ast_type: &Type) -> HashSet<usize> {
let mut accum = HashSet::new();
pub fn type_variables(ast_type: &Type) -> IndexSet<usize> {
let mut accum = IndexSet::new();
type_variables_rec(ast_type, &mut accum);
accum
}

fn type_variables_rec(ast_type: &Type, accum: &mut HashSet<usize>) {
fn type_variables_rec(ast_type: &Type, accum: &mut IndexSet<usize>) {
use Type::*;
match ast_type {
Call {
Expand Down Expand Up @@ -43,22 +43,18 @@ fn type_variables_rec(ast_type: &Type, accum: &mut HashSet<usize>) {
type_variables_rec(t, accum);
}
}
ConstructorAlias {
alias_variables, ..
} => {
accum.extend(alias_variables);
}
ConstructorAlias { aliased_type, .. } => type_variables_rec(aliased_type, accum),
Constructor { .. } | PrimConstructor { .. } => {}
}
}

pub fn cst_type_variables(t: &cst::Type) -> HashSet<Name> {
let mut accum = HashSet::new();
pub fn cst_type_variables(t: &cst::Type) -> IndexSet<Name> {
let mut accum = IndexSet::new();
cst_type_variables_rec(t, &mut accum);
accum
}

fn cst_type_variables_rec(t: &cst::Type, accum: &mut HashSet<Name>) {
fn cst_type_variables_rec(t: &cst::Type, accum: &mut IndexSet<Name>) {
use cst::Type::*;
match t {
Parens(parens) => cst_type_variables_rec(&parens.value, accum),
Expand Down Expand Up @@ -151,13 +147,13 @@ mod test_macros {
macro_rules! identity_scheme {
($name:expr) => {
Scheme {
forall: std::collections::HashSet::from_iter(vec![0]),
forall: indexmap::IndexSet::from_iter(vec![0]),
signature: $crate::typechecker::common::identity_type!($name),
}
};
() => {
Scheme {
forall: std::collections::HashSet::from_iter(vec![0]),
forall: indexmap::IndexSet::from_iter(vec![0]),
signature: $crate::typechecker::common::identity_type!(),
}
};
Expand Down
8 changes: 3 additions & 5 deletions crates/ditto-checker/src/typechecker/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ use ditto_ast::{
Expression, FullyQualifiedName, FullyQualifiedProperName, Name, Pattern, ProperName,
QualifiedName, QualifiedProperName, Span, Type,
};
use std::{
collections::{HashMap, HashSet},
default::Default,
};
use indexmap::IndexSet;
use std::{collections::HashMap, default::Default};

#[derive(Default, Clone)]
pub struct Env {
Expand All @@ -32,7 +30,7 @@ impl Env {
signature: ast_type,
}
}
fn free_type_variables(&self) -> HashSet<usize> {
fn free_type_variables(&self) -> IndexSet<usize> {
self.constructors
.values()
.map(|env_constructor| env_constructor.get_scheme().free_type_variables())
Expand Down
6 changes: 3 additions & 3 deletions crates/ditto-checker/src/typechecker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use ditto_ast::{
QualifiedName, Row, Span, Type,
};
use ditto_cst as cst;
use indexmap::IndexMap;
use std::collections::{HashMap, HashSet};
use indexmap::{IndexMap, IndexSet};
use std::collections::HashMap;

#[cfg(test)]
pub fn typecheck(
Expand Down Expand Up @@ -1137,7 +1137,7 @@ fn with_extended_env<T>(
EnvValue::ModuleValue {
span,
variable_scheme: Scheme {
forall: HashSet::new(),
forall: IndexSet::new(),
signature: value_type,
},
variable: unqualified_name.value,
Expand Down
3 changes: 2 additions & 1 deletion crates/ditto-checker/src/typechecker/scheme.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::{common::type_variables, Substitution};
use crate::supply::Supply;
use ditto_ast::Type;
use indexmap::IndexSet;
use std::collections::HashSet;

/// A polymorphic type.
Expand All @@ -9,7 +10,7 @@ use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct Scheme {
/// The "quantifier".
pub forall: HashSet<usize>,
pub forall: IndexSet<usize>,
/// The enclosed type.
pub signature: Type,
}
Expand Down
17 changes: 16 additions & 1 deletion crates/ditto-checker/src/typechecker/substitution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ impl Substitution {
for t in tail {
arguments.push(self.apply_rec(t.clone(), depth));
}
let alias_variables = alias_variables
.into_iter()
.map(|var| self.apply_var(var))
.collect::<Vec<_>>();

let mut subst = self.0.clone();
subst.extend(
alias_variables
Expand Down Expand Up @@ -185,7 +190,10 @@ impl Substitution {
constructor_kind,
canonical_value,
source_value,
alias_variables,
alias_variables: alias_variables
.into_iter()
.map(|var| self.apply_var(var))
.collect(),
aliased_type: Box::new(self.apply_rec(aliased_type, depth)),
},
Type::Constructor {
Expand Down Expand Up @@ -474,4 +482,11 @@ impl Substitution {
},
}
}

fn apply_var(&self, var: usize) -> usize {
match self.0.get(&var) {
Some(Type::Variable { var, .. }) => self.apply_var(*var),
_ => var,
}
}
}
Empty file.
17 changes: 17 additions & 0 deletions crates/ditto-checker/tests/cmd/basic_task_module/test.stdin
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Task exports (
Task,
succeed,
);


type alias VoidEffect = Effect(Unit);

type Result(a, e) =
| Ok(a)
| Err(e);

type alias Callback(a, e) = (Result(a, e)) -> VoidEffect;

type Task(a, e) = Task((Callback(a, e)) -> VoidEffect);

succeed = fn (a): Task(a, e) -> Task(fn (callback) -> callback(Ok(a)));
Loading

0 comments on commit 7c8cdbd

Please sign in to comment.