1#![allow(dead_code)]
2
3use super::constant;
4use super::obj::*;
5use super::objects::{ObjKey, PackageKey, ScopeKey, TCObjects, TypeKey, Types};
6use super::package::*;
7use super::scope::*;
8use super::typ::*;
9use std::collections::HashMap;
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq)]
14pub enum ExprKind {
15 Conversion,
16 Expression,
17 Statement,
18}
19
20#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
22pub enum Builtin {
23 Append,
24 Cap,
25 Close,
26 Complex,
27 Copy,
28 Delete,
29 Imag,
30 Len,
31 Make,
32 New,
33 Panic,
34 Print,
35 Println,
36 Real,
37 Recover,
38 Alignof,
40 Offsetof,
41 Sizeof,
42 Assert,
44 Trace,
45 Ffi,
47}
48
49#[derive(Copy, Clone)]
50pub struct BuiltinInfo {
51 pub name: &'static str,
52 pub arg_count: usize,
53 pub variadic: bool,
54 pub kind: ExprKind,
55}
56
57pub struct Universe {
60 scope: ScopeKey,
61 unsafe_: PackageKey,
62 iota: ObjKey,
63 byte: TypeKey,
64 rune: TypeKey,
65 slice_of_bytes: TypeKey, no_value_tuple: TypeKey, indir: ObjKey,
73 guard_sig: TypeKey,
75 types: HashMap<BasicType, TypeKey>,
76 builtins: HashMap<Builtin, BuiltinInfo>,
77}
78
79impl Universe {
80 pub fn new(objs: &mut TCObjects) -> Universe {
81 let (uskey, unsafe_) = Universe::def_universe_unsafe(objs);
83 let types = Universe::basic_types(&mut objs.types);
85 Universe::def_basic_types(&types, &uskey, &unsafe_, objs);
86 Universe::def_basic_types(
87 &Universe::alias_types(&mut objs.types),
88 &uskey,
89 &unsafe_,
90 objs,
91 );
92 Universe::def_error_type(&types, &uskey, &unsafe_, objs);
93 Universe::def_consts(&types, &uskey, &unsafe_, objs);
95 Universe::def_nil(&types, &uskey, &unsafe_, objs);
96 let builtins = Universe::builtin_funcs();
98 let ftype = types[&BasicType::Invalid];
99 Universe::def_builtins(&builtins, ftype, &uskey, &unsafe_, objs);
100 let (iota, byte, rune) = Universe::iota_byte_rune(&uskey, objs);
102 let slice_of_bytes = objs.new_t_slice(byte);
103 let no_value_tuple = objs.new_t_tuple(vec![]);
104 let indir = objs.new_type_name(0, None, "*".to_string(), None);
105 let guard_sig = objs.new_t_signature(None, None, no_value_tuple, no_value_tuple, false);
106 Universe {
107 scope: uskey,
108 unsafe_: unsafe_,
109 iota: iota,
110 byte: byte,
111 rune: rune,
112 slice_of_bytes: slice_of_bytes,
113 no_value_tuple: no_value_tuple,
114 indir: indir,
115 guard_sig: guard_sig,
116 types: types,
117 builtins: builtins,
118 }
119 }
120
121 pub fn scope(&self) -> &ScopeKey {
122 &self.scope
123 }
124
125 pub fn unsafe_pkg(&self) -> &PackageKey {
126 &self.unsafe_
127 }
128
129 pub fn types(&self) -> &HashMap<BasicType, TypeKey> {
130 &self.types
131 }
132
133 pub fn builtins(&self) -> &HashMap<Builtin, BuiltinInfo> {
134 &self.builtins
135 }
136
137 pub fn iota(&self) -> &ObjKey {
138 &self.iota
139 }
140
141 pub fn byte(&self) -> &TypeKey {
142 &self.byte
143 }
144
145 pub fn rune(&self) -> &TypeKey {
146 &self.rune
147 }
148
149 pub fn slice_of_bytes(&self) -> &TypeKey {
150 &self.slice_of_bytes
151 }
152
153 pub fn no_value_tuple(&self) -> &TypeKey {
154 &self.no_value_tuple
155 }
156
157 pub fn indir(&self) -> &ObjKey {
158 &self.indir
159 }
160
161 pub fn guard_sig(&self) -> &TypeKey {
162 &self.guard_sig
163 }
164
165 fn def_universe_unsafe(objs: &mut TCObjects) -> (ScopeKey, PackageKey) {
166 let uskey = objs
167 .scopes
168 .insert(Scope::new(None, 0, 0, "universe".to_owned(), false));
169 let pkg_skey = objs.scopes.insert(Scope::new(
170 Some(uskey),
171 0,
172 0,
173 "package unsafe".to_owned(),
174 false,
175 ));
176 let mut pkg = Package::new("unsafe".to_owned(), Some("unsafe".to_owned()), pkg_skey);
177 pkg.mark_complete();
178 (uskey, objs.pkgs.insert(pkg))
179 }
180
181 fn def_error_type(
186 types: &HashMap<BasicType, TypeKey>,
187 universe: &ScopeKey,
188 unsafe_: &PackageKey,
189 objs: &mut TCObjects,
190 ) {
191 let res = objs.lobjs.insert(LangObj::new_var(
192 0,
193 None,
194 "".to_owned(),
195 Some(types[&BasicType::Str]),
196 ));
197 let params = objs.new_t_tuple(vec![]);
198 let results = objs.new_t_tuple(vec![res]);
199 let sig = objs.new_t_signature(None, None, params, results, false);
200 let err = objs
201 .lobjs
202 .insert(LangObj::new_func(0, None, "Error".to_owned(), Some(sig)));
203 let inter_detail = InterfaceDetail::new(vec![err], vec![], objs);
204 inter_detail.complete(objs);
205 let underlying = objs.types.insert(Type::Interface(inter_detail));
206 let typ = objs.new_t_named(None, Some(underlying), vec![]);
207 let recv = objs
208 .lobjs
209 .insert(LangObj::new_var(0, None, "".to_owned(), Some(typ)));
210 objs.types[sig]
211 .try_as_signature_mut()
212 .unwrap()
213 .set_recv(Some(recv));
214 let type_name = objs.lobjs.insert(LangObj::new_type_name(
215 0,
216 None,
217 "error".to_owned(),
218 Some(typ),
219 ));
220 Universe::def(type_name, universe, unsafe_, objs);
221 }
222
223 fn def_basic_types(
224 types: &HashMap<BasicType, TypeKey>,
225 universe: &ScopeKey,
226 unsafe_: &PackageKey,
227 objs: &mut TCObjects,
228 ) {
229 for (_, v) in types {
230 let name = objs.types[*v].try_as_basic().unwrap().name();
231 let t = objs
232 .lobjs
233 .insert(LangObj::new_type_name(0, None, name.to_owned(), Some(*v)));
234 Universe::def(t, universe, unsafe_, objs);
235 }
236 }
237
238 fn basic_types(tobjs: &mut Types) -> HashMap<BasicType, TypeKey> {
239 vec![
240 (BasicType::Invalid, BasicInfo::IsInvalid, "invalid type"),
243 (BasicType::Bool, BasicInfo::IsBoolean, "bool"),
244 (BasicType::Int, BasicInfo::IsInteger, "int"),
245 (BasicType::Int8, BasicInfo::IsInteger, "int8"),
246 (BasicType::Int16, BasicInfo::IsInteger, "int16"),
247 (BasicType::Int32, BasicInfo::IsInteger, "int32"),
248 (BasicType::Int64, BasicInfo::IsInteger, "int64"),
249 (BasicType::Uint, BasicInfo::IsInteger, "uint"),
250 (BasicType::Uint8, BasicInfo::IsInteger, "uint8"),
251 (BasicType::Uint16, BasicInfo::IsInteger, "uint16"),
252 (BasicType::Uint32, BasicInfo::IsInteger, "uint32"),
253 (BasicType::Uint64, BasicInfo::IsInteger, "uint64"),
254 (BasicType::Uintptr, BasicInfo::IsInteger, "uintptr"),
255 (BasicType::Float32, BasicInfo::IsFloat, "float32"),
256 (BasicType::Float64, BasicInfo::IsFloat, "float64"),
257 (BasicType::Complex64, BasicInfo::IsComplex, "complex64"),
258 (BasicType::Complex128, BasicInfo::IsComplex, "complex128"),
259 (BasicType::Str, BasicInfo::IsString, "string"),
260 (BasicType::UnsafePointer, BasicInfo::IsInvalid, "Pointer"),
261 (BasicType::UntypedBool, BasicInfo::IsBoolean, "untyped bool"),
262 (BasicType::UntypedInt, BasicInfo::IsInteger, "untyped int"),
263 (BasicType::UntypedRune, BasicInfo::IsInteger, "untyped rune"),
264 (BasicType::UntypedFloat, BasicInfo::IsFloat, "untyped float"),
265 (
266 BasicType::UntypedComplex,
267 BasicInfo::IsComplex,
268 "untyped complex",
269 ),
270 (
271 BasicType::UntypedString,
272 BasicInfo::IsString,
273 "untyped string",
274 ),
275 (BasicType::UntypedNil, BasicInfo::IsInvalid, "untyped nil"),
276 ]
277 .into_iter()
278 .map(|(t, i, n)| (t, tobjs.insert(Type::Basic(BasicDetail::new(t, i, n)))))
279 .collect::<HashMap<_, _>>()
280 }
281
282 fn alias_types(tobjs: &mut Types) -> HashMap<BasicType, TypeKey> {
283 [
284 (BasicType::Byte, BasicInfo::IsInteger, "byte"),
285 (BasicType::Rune, BasicInfo::IsInteger, "rune"),
286 ]
287 .iter()
288 .map(|(t, i, n)| (*t, tobjs.insert(Type::Basic(BasicDetail::new(*t, *i, n)))))
289 .collect::<HashMap<_, _>>()
290 }
291
292 fn def_consts(
293 types: &HashMap<BasicType, TypeKey>,
294 universe: &ScopeKey,
295 unsafe_: &PackageKey,
296 objs: &mut TCObjects,
297 ) {
298 for (n, t, v) in vec![
299 (
301 "true",
302 BasicType::UntypedBool,
303 constant::Value::with_bool(true),
304 ),
305 (
306 "false",
307 BasicType::UntypedBool,
308 constant::Value::with_bool(false),
309 ),
310 ("iota", BasicType::UntypedInt, constant::Value::with_i64(0)),
311 ]
312 .into_iter()
313 {
314 let cst = LangObj::new_const(0, None, n.to_owned(), Some(types[&t]), v);
315 Universe::def(objs.lobjs.insert(cst), universe, unsafe_, objs);
316 }
317 }
318
319 fn def_nil(
320 types: &HashMap<BasicType, TypeKey>,
321 universe: &ScopeKey,
322 unsafe_: &PackageKey,
323 objs: &mut TCObjects,
324 ) {
325 let nil = LangObj::new_nil(types[&BasicType::UntypedNil]);
326 Universe::def(objs.lobjs.insert(nil), universe, unsafe_, objs);
327 }
328
329 fn builtin_funcs() -> HashMap<Builtin, BuiltinInfo> {
330 vec![
331 (Builtin::Append, "append", 1, true, ExprKind::Expression),
333 (Builtin::Cap, "cap", 1, false, ExprKind::Expression),
334 (Builtin::Close, "close", 1, false, ExprKind::Statement),
335 (Builtin::Complex, "complex", 2, false, ExprKind::Expression),
336 (Builtin::Copy, "copy", 2, false, ExprKind::Statement),
337 (Builtin::Delete, "delete", 2, false, ExprKind::Statement),
338 (Builtin::Imag, "imag", 1, false, ExprKind::Expression),
339 (Builtin::Len, "len", 1, false, ExprKind::Expression),
340 (Builtin::Make, "make", 1, true, ExprKind::Expression),
341 (Builtin::New, "new", 1, false, ExprKind::Expression),
342 (Builtin::Panic, "panic", 1, false, ExprKind::Statement),
343 (Builtin::Print, "print", 0, true, ExprKind::Statement),
344 (Builtin::Println, "println", 0, true, ExprKind::Statement),
345 (Builtin::Real, "real", 1, false, ExprKind::Expression),
346 (Builtin::Recover, "recover", 0, false, ExprKind::Statement),
347 (Builtin::Alignof, "Alignof", 1, false, ExprKind::Expression),
348 (
349 Builtin::Offsetof,
350 "Offsetof",
351 1,
352 false,
353 ExprKind::Expression,
354 ),
355 (Builtin::Sizeof, "Sizeof", 1, false, ExprKind::Expression),
356 (Builtin::Assert, "assert", 1, false, ExprKind::Statement),
357 (Builtin::Trace, "trace", 0, true, ExprKind::Statement),
358 (Builtin::Ffi, "ffi", 2, false, ExprKind::Expression),
359 ]
360 .into_iter()
361 .map(|(f, name, no, v, k)| {
362 (
363 f,
364 BuiltinInfo {
365 name: name,
366 arg_count: no,
367 variadic: v,
368 kind: k,
369 },
370 )
371 })
372 .collect::<HashMap<_, _>>()
373 }
374
375 fn def_builtins(
376 builtins: &HashMap<Builtin, BuiltinInfo>,
377 typ: TypeKey,
378 universe: &ScopeKey,
379 unsafe_: &PackageKey,
380 objs: &mut TCObjects,
381 ) {
382 for (f, info) in builtins.iter() {
383 let fobj = objs
384 .lobjs
385 .insert(LangObj::new_builtin(*f, info.name.to_owned(), typ));
386 Universe::def(fobj, universe, unsafe_, objs);
387 }
388 }
389
390 fn iota_byte_rune(universe: &ScopeKey, objs: &mut TCObjects) -> (ObjKey, TypeKey, TypeKey) {
391 let scope = &objs.scopes[*universe];
392 let iota = *scope.lookup("iota").unwrap();
393 let byte = objs.lobjs[*scope.lookup("byte").unwrap()].typ().unwrap();
394 let rune = objs.lobjs[*scope.lookup("rune").unwrap()].typ().unwrap();
395 (iota, byte, rune)
396 }
397
398 fn def(okey: ObjKey, universe: &ScopeKey, unsafe_: &PackageKey, objs: &mut TCObjects) {
402 let obj = &objs.lobjs[okey];
403 assert!(obj.color() == ObjColor::Black);
404 if obj.name().contains(' ') {
405 return;
406 }
407 let typ_val = &mut objs.types[obj.typ().unwrap()];
409 if let Some(n) = typ_val.try_as_named_mut() {
410 n.set_obj(okey);
411 }
412
413 let skey = if obj.exported() {
414 match obj.entity_type() {
415 EntityType::TypeName | EntityType::Builtin(_) => {
416 objs.lobjs[okey].set_pkg(Some(*unsafe_))
417 }
418 _ => unreachable!(),
419 }
420 objs.pkgs[*unsafe_].scope()
421 } else {
422 universe
423 };
424 let re = Scope::insert(*skey, okey, objs);
425 assert!(re.is_none());
426 }
427}