lisette_semantics/checker/registration/
builtins.rs1use syntax::EcoString;
2use syntax::types::Type;
3
4use crate::checker::Checker;
5
6impl Checker<'_, '_> {
7 fn builtin_qualified_name(&mut self, type_name: &str) -> EcoString {
8 self.lookup_qualified_name(type_name)
9 .map(EcoString::from)
10 .unwrap_or_else(|| panic!("Builtin type {type_name} not found in store"))
11 }
12
13 fn builtin_type(&mut self, type_name: &str) -> Type {
14 if let Some(ty) = self.builtins.get(type_name) {
15 return ty.clone();
16 }
17
18 let qualified_name = self.builtin_qualified_name(type_name);
19
20 let ty = self
21 .store
22 .get_type(&qualified_name)
23 .unwrap_or_else(|| panic!("Builtin type {type_name} not found in store"));
24
25 let body = match &ty {
26 Type::Forall { body, .. } => body.as_ref().clone(),
27 _ => ty.clone(),
28 };
29
30 self.builtins.insert(type_name.to_string(), body.clone());
31
32 body
33 }
34
35 pub fn type_unit(&self) -> Type {
36 Type::unit()
37 }
38
39 pub fn type_never(&self) -> Type {
40 Type::Never
41 }
42
43 pub fn type_int(&mut self) -> Type {
44 self.builtin_type("int")
45 }
46
47 pub fn type_float(&mut self) -> Type {
48 self.builtin_type("float64")
49 }
50
51 pub fn type_string(&mut self) -> Type {
52 self.builtin_type("string")
53 }
54
55 pub fn type_char(&mut self) -> Type {
56 self.builtin_type("rune")
57 }
58
59 pub fn type_bool(&mut self) -> Type {
60 self.builtin_type("bool")
61 }
62
63 pub fn type_complex128(&mut self) -> Type {
64 self.builtin_type("complex128")
65 }
66
67 pub fn type_unknown(&mut self) -> Type {
68 self.builtin_type("Unknown")
69 }
70
71 pub fn type_slice(&mut self, element_type: Type) -> Type {
72 Type::Constructor {
73 id: self.builtin_qualified_name("Slice"),
74 params: vec![element_type],
75 underlying_ty: None,
76 }
77 }
78
79 pub fn type_reference(&mut self, inner_type: Type) -> Type {
80 Type::Constructor {
81 id: self.builtin_qualified_name("Ref"),
82 params: vec![inner_type],
83 underlying_ty: None,
84 }
85 }
86
87 pub fn type_map(&mut self, key_type: Type, value_type: Type) -> Type {
88 Type::Constructor {
89 id: self.builtin_qualified_name("Map"),
90 params: vec![key_type, value_type],
91 underlying_ty: None,
92 }
93 }
94
95 pub fn type_result(&mut self, ok_type: Type, error_type: Type) -> Type {
96 Type::Constructor {
97 id: self.builtin_qualified_name("Result"),
98 params: vec![ok_type, error_type],
99 underlying_ty: None,
100 }
101 }
102
103 pub fn type_option(&mut self, some_type: Type) -> Type {
104 Type::Constructor {
105 id: self.builtin_qualified_name("Option"),
106 params: vec![some_type],
107 underlying_ty: None,
108 }
109 }
110
111 pub fn type_panic_value(&mut self) -> Type {
112 Type::Constructor {
113 id: self.builtin_qualified_name("PanicValue"),
114 params: vec![],
115 underlying_ty: None,
116 }
117 }
118
119 pub fn type_range(&mut self, element_type: Type) -> Type {
120 Type::Constructor {
121 id: self.builtin_qualified_name("Range"),
122 params: vec![element_type],
123 underlying_ty: None,
124 }
125 }
126
127 pub fn type_range_inclusive(&mut self, element_type: Type) -> Type {
128 Type::Constructor {
129 id: self.builtin_qualified_name("RangeInclusive"),
130 params: vec![element_type],
131 underlying_ty: None,
132 }
133 }
134
135 pub fn type_range_from(&mut self, element_type: Type) -> Type {
136 Type::Constructor {
137 id: self.builtin_qualified_name("RangeFrom"),
138 params: vec![element_type],
139 underlying_ty: None,
140 }
141 }
142
143 pub fn type_range_to(&mut self, element_type: Type) -> Type {
144 Type::Constructor {
145 id: self.builtin_qualified_name("RangeTo"),
146 params: vec![element_type],
147 underlying_ty: None,
148 }
149 }
150
151 pub fn type_range_to_inclusive(&mut self, element_type: Type) -> Type {
152 Type::Constructor {
153 id: self.builtin_qualified_name("RangeToInclusive"),
154 params: vec![element_type],
155 underlying_ty: None,
156 }
157 }
158
159 pub fn is_generic_container_with_interface(&self, ty: &Type) -> bool {
162 let Type::Constructor { id, params, .. } = ty.resolve() else {
163 return false;
164 };
165
166 if id != "prelude.Option" && id != "prelude.Result" {
167 return false;
168 }
169
170 params.iter().any(|p| {
171 if let Type::Constructor { id, .. } = p.resolve() {
172 self.store.get_interface(&id).is_some()
173 } else {
174 false
175 }
176 })
177 }
178
179 pub fn has_interface_type_param(&self, ty: &Type) -> bool {
180 let Type::Constructor { params, .. } = ty.resolve() else {
181 return false;
182 };
183
184 params.iter().any(|p| {
185 if let Type::Constructor { id, .. } = p.resolve() {
186 self.store.get_interface(&id).is_some()
187 } else {
188 false
189 }
190 })
191 }
192}