|
|
@ -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})"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|