1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum PrimitiveType {
8 I32,
9 I64,
10 F64,
11 Bool,
12 String,
13 Unit,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct TypeVarId(pub u32);
19
20#[derive(Debug, Clone, PartialEq)]
22pub enum Type {
23 Primitive(PrimitiveType),
25 Named {
27 name: String,
29 args: Vec<Type>,
31 },
32 Function { params: Vec<Type>, ret: Box<Type> },
34 Var(TypeVarId),
36 Array(Box<Type>),
38 Tuple(Vec<Type>),
40}
41
42impl Type {
43 pub fn i32() -> Self {
44 Type::Primitive(PrimitiveType::I32)
45 }
46
47 pub fn i64() -> Self {
48 Type::Primitive(PrimitiveType::I64)
49 }
50
51 pub fn f64() -> Self {
52 Type::Primitive(PrimitiveType::F64)
53 }
54
55 pub fn bool() -> Self {
56 Type::Primitive(PrimitiveType::Bool)
57 }
58
59 pub fn string() -> Self {
60 Type::Primitive(PrimitiveType::String)
61 }
62
63 pub fn unit() -> Self {
64 Type::Primitive(PrimitiveType::Unit)
65 }
66
67 pub fn named(name: impl Into<String>, args: Vec<Type>) -> Self {
68 Type::Named {
69 name: name.into(),
70 args,
71 }
72 }
73
74 pub fn function(params: Vec<Type>, ret: Type) -> Self {
75 Type::Function {
76 params,
77 ret: Box::new(ret),
78 }
79 }
80
81 pub fn tuple(elements: Vec<Type>) -> Self {
82 Type::Tuple(elements)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn primitives_constructors_work() {
92 assert_eq!(Type::i32(), Type::Primitive(PrimitiveType::I32));
93 assert_eq!(Type::i64(), Type::Primitive(PrimitiveType::I64));
94 assert_eq!(Type::bool(), Type::Primitive(PrimitiveType::Bool));
95 assert_eq!(Type::string(), Type::Primitive(PrimitiveType::String));
96 assert_eq!(Type::unit(), Type::Primitive(PrimitiveType::Unit));
97 }
98
99 #[test]
100 fn named_type_with_args() {
101 let t = Type::named("Option", vec![Type::string()]);
102 match t {
103 Type::Named { name, args } => {
104 assert_eq!(name, "Option");
105 assert_eq!(args.len(), 1);
106 assert_eq!(args[0], Type::string());
107 }
108 _ => panic!("expected named type"),
109 }
110 }
111
112 #[test]
113 fn function_type() {
114 let t = Type::function(vec![Type::i32(), Type::bool()], Type::string());
115 match t {
116 Type::Function { params, ret } => {
117 assert_eq!(params.len(), 2);
118 assert_eq!(params[0], Type::i32());
119 assert_eq!(params[1], Type::bool());
120 assert_eq!(*ret, Type::string());
121 }
122 _ => panic!("expected function type"),
123 }
124 }
125
126 #[test]
127 fn tuple_type() {
128 let t = Type::tuple(vec![Type::i32(), Type::string(), Type::bool()]);
129 match t {
130 Type::Tuple(elements) => {
131 assert_eq!(elements.len(), 3);
132 assert_eq!(elements[0], Type::i32());
133 assert_eq!(elements[1], Type::string());
134 assert_eq!(elements[2], Type::bool());
135 }
136 _ => panic!("expected tuple type"),
137 }
138 }
139}