lisette_semantics/checker/registration/
builtins.rs1use crate::checker::EnvResolve;
2use syntax::types::{CompoundKind, SimpleKind, Symbol, Type};
3
4use crate::checker::TaskState;
5use crate::store::Store;
6
7impl TaskState<'_> {
8 fn builtin_qualified_name(&mut self, store: &Store, type_name: &str) -> Symbol {
9 self.lookup_qualified_name(store, type_name)
10 .map(Symbol::from)
11 .unwrap_or_else(|| panic!("Builtin type {type_name} not found in store"))
12 }
13
14 fn builtin_type(&mut self, store: &Store, type_name: &str) -> Type {
15 if let Some(ty) = self.builtins.get(type_name) {
16 return ty.clone();
17 }
18
19 let qualified_name = self.builtin_qualified_name(store, type_name);
20
21 let ty = 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 Type::Simple(SimpleKind::Int)
45 }
46
47 pub fn type_float(&mut self) -> Type {
48 Type::Simple(SimpleKind::Float64)
49 }
50
51 pub fn type_string(&mut self) -> Type {
52 Type::Simple(SimpleKind::String)
53 }
54
55 pub fn type_char(&mut self) -> Type {
56 Type::Simple(SimpleKind::Rune)
57 }
58
59 pub fn type_bool(&mut self) -> Type {
60 Type::Simple(SimpleKind::Bool)
61 }
62
63 pub fn type_complex128(&mut self) -> Type {
64 Type::Simple(SimpleKind::Complex128)
65 }
66
67 pub fn type_unknown(&mut self, store: &Store) -> Type {
68 self.builtin_type(store, "Unknown")
69 }
70
71 pub fn type_slice(&mut self, element_type: Type) -> Type {
72 Type::Compound {
73 kind: CompoundKind::Slice,
74 args: vec![element_type],
75 }
76 }
77
78 pub fn type_reference(&mut self, inner_type: Type) -> Type {
79 Type::Compound {
80 kind: CompoundKind::Ref,
81 args: vec![inner_type],
82 }
83 }
84
85 pub fn type_map(&mut self, key_type: Type, value_type: Type) -> Type {
86 Type::Compound {
87 kind: CompoundKind::Map,
88 args: vec![key_type, value_type],
89 }
90 }
91
92 pub fn type_result(&mut self, store: &Store, ok_type: Type, error_type: Type) -> Type {
93 Type::Nominal {
94 id: self.builtin_qualified_name(store, "Result"),
95 params: vec![ok_type, error_type],
96 underlying_ty: None,
97 }
98 }
99
100 pub fn type_option(&mut self, store: &Store, some_type: Type) -> Type {
101 Type::Nominal {
102 id: self.builtin_qualified_name(store, "Option"),
103 params: vec![some_type],
104 underlying_ty: None,
105 }
106 }
107
108 pub fn type_panic_value(&mut self, store: &Store) -> Type {
109 Type::Nominal {
110 id: self.builtin_qualified_name(store, "PanicValue"),
111 params: vec![],
112 underlying_ty: None,
113 }
114 }
115
116 pub fn type_range(&mut self, store: &Store, element_type: Type) -> Type {
117 Type::Nominal {
118 id: self.builtin_qualified_name(store, "Range"),
119 params: vec![element_type],
120 underlying_ty: None,
121 }
122 }
123
124 pub fn type_range_inclusive(&mut self, store: &Store, element_type: Type) -> Type {
125 Type::Nominal {
126 id: self.builtin_qualified_name(store, "RangeInclusive"),
127 params: vec![element_type],
128 underlying_ty: None,
129 }
130 }
131
132 pub fn type_range_from(&mut self, store: &Store, element_type: Type) -> Type {
133 Type::Nominal {
134 id: self.builtin_qualified_name(store, "RangeFrom"),
135 params: vec![element_type],
136 underlying_ty: None,
137 }
138 }
139
140 pub fn type_range_to(&mut self, store: &Store, element_type: Type) -> Type {
141 Type::Nominal {
142 id: self.builtin_qualified_name(store, "RangeTo"),
143 params: vec![element_type],
144 underlying_ty: None,
145 }
146 }
147
148 pub fn type_range_to_inclusive(&mut self, store: &Store, element_type: Type) -> Type {
149 Type::Nominal {
150 id: self.builtin_qualified_name(store, "RangeToInclusive"),
151 params: vec![element_type],
152 underlying_ty: None,
153 }
154 }
155
156 pub fn is_generic_container_with_interface(&self, store: &Store, ty: &Type) -> bool {
163 let resolved = ty.resolve_in(&self.env);
164 let Type::Nominal { id, params, .. } = &resolved else {
165 return false;
166 };
167
168 if id != "prelude.Option" && id != "prelude.Result" {
169 return false;
170 }
171
172 params.iter().any(|p| {
173 if let Type::Nominal { id, .. } = p.resolve_in(&self.env) {
174 store.get_interface(&id).is_some() || id.starts_with("go:")
175 } else {
176 false
177 }
178 })
179 }
180}