#![allow(missing_docs)]
use crate::diagnostics::Span;
use std::collections::HashSet;
use std::fmt;
pub mod substitution;
pub mod unification;
pub mod constraints;
pub mod inference;
pub mod type_classes;
pub mod gradual;
pub mod algebraic;
pub mod advanced_type_classes;
pub mod r7rs_integration;
pub mod integration_bridge;
pub mod type_var;
pub mod constraint;
pub mod row;
pub mod type_scheme;
pub mod type_env;
pub mod type_constructor;
pub mod type_checker;
pub use substitution::*;
pub use constraints::*;
pub use unification::*;
pub use inference::*;
pub use type_classes::*;
pub use gradual::*;
pub use algebraic::*;
pub use advanced_type_classes::*;
pub use r7rs_integration::*;
pub use integration_bridge::*;
pub use type_var::*;
pub use constraint::*;
pub use row::*;
pub use type_scheme::*;
pub use type_env::*;
pub use type_constructor::*;
pub use type_checker::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeLevel {
Dynamic,
Contracts,
Static,
Dependent,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Type {
Number,
String,
Symbol,
Boolean,
Char,
Bytevector,
Unit,
Pair(Box<Type>, Box<Type>),
List(Box<Type>),
Vector(Box<Type>),
Function {
params: Vec<Type>,
return_type: Box<Type>,
},
Variable(TypeVar),
Constructor {
name: String,
kind: Kind,
},
Application {
constructor: Box<Type>,
argument: Box<Type>,
},
Forall {
vars: Vec<TypeVar>,
body: Box<Type>,
},
Exists {
vars: Vec<TypeVar>,
body: Box<Type>,
},
Constrained {
constraints: Vec<Constraint>,
type_: Box<Type>,
},
Dynamic,
Unknown,
Effectful {
input: Box<Type>,
effects: Vec<Effect>,
output: Box<Type>,
},
Record(Row),
Variant(Row),
Recursive {
var: TypeVar,
body: Box<Type>,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Kind {
Type,
Arrow(Box<Kind>, Box<Kind>),
Row,
Effect,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Effect {
IO,
State(Type),
Exception(Type),
Custom(String),
Pure,
Error,
}
impl Type {
pub fn fresh_var() -> Self {
Type::Variable(TypeVar::new())
}
pub fn named_var(name: impl Into<String>) -> Self {
Type::Variable(TypeVar::with_name(name))
}
pub fn function(params: Vec<Type>, return_type: Type) -> Self {
Type::Function {
params,
return_type: Box::new(return_type),
}
}
pub fn pair(first: Type, second: Type) -> Self {
Type::Pair(Box::new(first), Box::new(second))
}
pub fn list(element_type: Type) -> Self {
Type::List(Box::new(element_type))
}
pub fn vector(element_type: Type) -> Self {
Type::Vector(Box::new(element_type))
}
pub fn forall(vars: Vec<TypeVar>, body: Type) -> Self {
if vars.is_empty() {
body
} else {
Type::Forall {
vars,
body: Box::new(body),
}
}
}
pub fn constrained(constraints: Vec<Constraint>, type_: Type) -> Self {
if constraints.is_empty() {
type_
} else {
Type::Constrained {
constraints,
type_: Box::new(type_),
}
}
}
pub fn is_variable(&self) -> bool {
matches!(self, Type::Variable(_))
}
pub fn is_function(&self) -> bool {
matches!(self, Type::Function { .. })
}
pub fn is_polymorphic(&self) -> bool {
matches!(self, Type::Forall { .. } | Type::Exists { .. })
}
pub fn contains_var(&self, var: &TypeVar) -> bool {
match self {
Type::Variable(v) => v == var,
Type::Pair(a, b) => a.contains_var(var) || b.contains_var(var),
Type::List(t) | Type::Vector(t) => t.contains_var(var),
Type::Function { params, return_type } => {
params.iter().any(|p| p.contains_var(var)) || return_type.contains_var(var)
}
Type::Application { constructor, argument } => {
constructor.contains_var(var) || argument.contains_var(var)
}
Type::Forall { vars, body } | Type::Exists { vars, body } => {
!vars.contains(var) && body.contains_var(var)
}
Type::Constrained { constraints, type_ } => {
constraints.iter().any(|c| c.type_.contains_var(var)) || type_.contains_var(var)
}
Type::Effectful { input, output, .. } => {
input.contains_var(var) || output.contains_var(var)
}
Type::Record(row) | Type::Variant(row) => {
row.fields.values().any(|t| t.contains_var(var)) ||
(row.rest.as_ref() == Some(var))
}
Type::Recursive { var: rv, body } => {
rv != var && body.contains_var(var)
}
_ => false,
}
}
pub fn free_vars(&self) -> HashSet<TypeVar> {
let mut vars = HashSet::new();
self.collect_free_vars(&mut vars, &HashSet::new());
vars
}
fn collect_free_vars(&self, vars: &mut HashSet<TypeVar>, bound: &HashSet<TypeVar>) {
match self {
Type::Variable(v) => {
if !bound.contains(v) {
vars.insert(v.clone());
}
}
Type::Pair(a, b) => {
a.collect_free_vars(vars, bound);
b.collect_free_vars(vars, bound);
}
Type::List(t) | Type::Vector(t) => {
t.collect_free_vars(vars, bound);
}
Type::Function { params, return_type } => {
for param in params {
param.collect_free_vars(vars, bound);
}
return_type.collect_free_vars(vars, bound);
}
Type::Application { constructor, argument } => {
constructor.collect_free_vars(vars, bound);
argument.collect_free_vars(vars, bound);
}
Type::Forall { vars: qvars, body } | Type::Exists { vars: qvars, body } => {
let mut new_bound = bound.clone();
new_bound.extend(qvars.iter().cloned());
body.collect_free_vars(vars, &new_bound);
}
Type::Constrained { constraints, type_ } => {
for constraint in constraints {
constraint.type_.collect_free_vars(vars, bound);
}
type_.collect_free_vars(vars, bound);
}
Type::Effectful { input, output, .. } => {
input.collect_free_vars(vars, bound);
output.collect_free_vars(vars, bound);
}
Type::Record(row) | Type::Variant(row) => {
for field_type in row.fields.values() {
field_type.collect_free_vars(vars, bound);
}
if let Some(rest_var) = &row.rest {
if !bound.contains(rest_var) {
vars.insert(rest_var.clone());
}
}
}
Type::Recursive { var, body } => {
let mut new_bound = bound.clone();
new_bound.insert(var.clone());
body.collect_free_vars(vars, &new_bound);
}
_ => {} }
}
}
impl Kind {
pub fn arrow(from: Kind, to: Kind) -> Self {
Kind::Arrow(Box::new(from), Box::new(to))
}
pub fn arity(&self) -> usize {
match self {
Kind::Type | Kind::Row | Kind::Effect => 0,
Kind::Arrow(_, to) => 1 + to.arity(),
}
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Type::Number => write!(f, "Number"),
Type::String => write!(f, "String"),
Type::Symbol => write!(f, "Symbol"),
Type::Boolean => write!(f, "Boolean"),
Type::Char => write!(f, "Char"),
Type::Unit => write!(f, "()"),
Type::Dynamic => write!(f, "Dynamic"),
Type::Unknown => write!(f, "?"),
Type::Variable(var) => {
if let Some(name) = &var.name {
write!(f, "{name}")
} else {
write!(f, "t{}", var.id)
}
}
Type::Pair(a, b) => write!(f, "(Pair {a} {b})"),
Type::List(t) => write!(f, "(List {t})"),
Type::Vector(t) => write!(f, "(Vector {t})"),
Type::Function { params, return_type } => {
write!(f, "(->")?;
for param in params {
write!(f, " {param}")?;
}
write!(f, " {return_type})")
}
Type::Constructor { name, .. } => write!(f, "{name}"),
Type::Application { constructor, argument } => {
write!(f, "({constructor} {argument})")
}
Type::Forall { vars, body } => {
write!(f, "(∀ (")?;
for (i, var) in vars.iter().enumerate() {
if i > 0 { write!(f, " ")?; }
if let Some(name) = &var.name {
write!(f, "{name}")?;
} else {
write!(f, "t{}", var.id)?;
}
}
write!(f, ") {body})")
}
Type::Constrained { constraints, type_ } => {
write!(f, "(")?;
for (i, constraint) in constraints.iter().enumerate() {
if i > 0 { write!(f, ", ")?; }
write!(f, "{} {}", constraint.class, constraint.type_)?;
}
write!(f, " => {type_})")
}
_ => write!(f, "<{self:?}"),
}
}
}
impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Kind::Type => write!(f, "*"),
Kind::Row => write!(f, "Row"),
Kind::Effect => write!(f, "Effect"),
Kind::Arrow(from, to) => write!(f, "({from} -> {to})"),
}
}
}