#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PrimitiveType {
I32,
I64,
F64,
Bool,
String,
Unit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeVarId(pub u32);
#[derive(Debug, Clone, PartialEq)]
pub enum Type {
Primitive(PrimitiveType),
Named {
name: String,
args: Vec<Type>,
},
Function { params: Vec<Type>, ret: Box<Type> },
Var(TypeVarId),
Array(Box<Type>),
Tuple(Vec<Type>),
}
impl Type {
pub fn i32() -> Self {
Type::Primitive(PrimitiveType::I32)
}
pub fn i64() -> Self {
Type::Primitive(PrimitiveType::I64)
}
pub fn f64() -> Self {
Type::Primitive(PrimitiveType::F64)
}
pub fn bool() -> Self {
Type::Primitive(PrimitiveType::Bool)
}
pub fn string() -> Self {
Type::Primitive(PrimitiveType::String)
}
pub fn unit() -> Self {
Type::Primitive(PrimitiveType::Unit)
}
pub fn named(name: impl Into<String>, args: Vec<Type>) -> Self {
Type::Named {
name: name.into(),
args,
}
}
pub fn function(params: Vec<Type>, ret: Type) -> Self {
Type::Function {
params,
ret: Box::new(ret),
}
}
pub fn tuple(elements: Vec<Type>) -> Self {
Type::Tuple(elements)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn primitives_constructors_work() {
assert_eq!(Type::i32(), Type::Primitive(PrimitiveType::I32));
assert_eq!(Type::i64(), Type::Primitive(PrimitiveType::I64));
assert_eq!(Type::bool(), Type::Primitive(PrimitiveType::Bool));
assert_eq!(Type::string(), Type::Primitive(PrimitiveType::String));
assert_eq!(Type::unit(), Type::Primitive(PrimitiveType::Unit));
}
#[test]
fn named_type_with_args() {
let t = Type::named("Option", vec![Type::string()]);
match t {
Type::Named { name, args } => {
assert_eq!(name, "Option");
assert_eq!(args.len(), 1);
assert_eq!(args[0], Type::string());
}
_ => panic!("expected named type"),
}
}
#[test]
fn function_type() {
let t = Type::function(vec![Type::i32(), Type::bool()], Type::string());
match t {
Type::Function { params, ret } => {
assert_eq!(params.len(), 2);
assert_eq!(params[0], Type::i32());
assert_eq!(params[1], Type::bool());
assert_eq!(*ret, Type::string());
}
_ => panic!("expected function type"),
}
}
#[test]
fn tuple_type() {
let t = Type::tuple(vec![Type::i32(), Type::string(), Type::bool()]);
match t {
Type::Tuple(elements) => {
assert_eq!(elements.len(), 3);
assert_eq!(elements[0], Type::i32());
assert_eq!(elements[1], Type::string());
assert_eq!(elements[2], Type::bool());
}
_ => panic!("expected tuple type"),
}
}
}