go_types/
universe.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4//
5//
6// This code is adapted from the offical Go code written in Go
7// with license as follows:
8// Copyright 2013 The Go Authors. All rights reserved.
9// Use of this source code is governed by a BSD-style
10// license that can be found in the LICENSE file.
11
12#![allow(dead_code)]
13
14use super::constant;
15use super::obj::*;
16use super::objects::{ObjKey, PackageKey, ScopeKey, TCObjects, TypeKey, Types};
17use super::package::*;
18use super::scope::*;
19use super::typ::*;
20use go_parser::Map;
21
22/// ExprKind describes the kind of an expression; the kind
23/// determines if an expression is valid in 'statement context'.
24#[derive(Copy, Clone, Debug, PartialEq, Eq)]
25pub enum ExprKind {
26    Conversion,
27    Expression,
28    Statement,
29}
30
31/// A Builtin is the id of a builtin function.
32#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub enum Builtin {
34    Append,
35    Cap,
36    Close,
37    Complex,
38    Copy,
39    Delete,
40    Imag,
41    Len,
42    Make,
43    New,
44    Panic,
45    Print,
46    Println,
47    Real,
48    Recover,
49    // package unsafe
50    Alignof,
51    Offsetof,
52    Sizeof,
53    // testing support
54    Assert,
55    Trace,
56    // goscript native extension
57    Ffi,
58}
59
60#[derive(Copy, Clone)]
61pub struct BuiltinInfo {
62    pub name: &'static str,
63    pub arg_count: usize,
64    pub variadic: bool,
65    pub kind: ExprKind,
66}
67
68/// Universe sets up the universe scope, the unsafe package
69/// and all the builtin types and functions
70pub struct Universe {
71    scope: ScopeKey,
72    unsafe_: PackageKey,
73    iota: ObjKey,
74    byte: TypeKey,
75    rune: TypeKey,
76    slice_of_bytes: TypeKey, // for builtin append
77    no_value_tuple: TypeKey, // for OperandMode::NoValue
78    // indir is a sentinel type name that is pushed onto the object path
79    // to indicate an "indirection" in the dependency from one type name
80    // to the next. For instance, for "type p *p" the object path contains
81    // p followed by indir, indicating that there's an indirection *p.
82    // Indirections are used to break type cycles.
83    indir: ObjKey,
84    // guard_sig is a empty signature type used to guard against func cycles
85    guard_sig: TypeKey,
86    types: Map<BasicType, TypeKey>,
87    builtins: Map<Builtin, BuiltinInfo>,
88}
89
90impl Universe {
91    pub fn new(objs: &mut TCObjects) -> Universe {
92        // universe scope and unsafe package
93        let (uskey, unsafe_) = Universe::def_universe_unsafe(objs);
94        // types
95        let types = Universe::basic_types(&mut objs.types);
96        Universe::def_basic_types(&types, &uskey, &unsafe_, objs);
97        Universe::def_basic_types(
98            &Universe::alias_types(&mut objs.types),
99            &uskey,
100            &unsafe_,
101            objs,
102        );
103        Universe::def_error_type(&types, &uskey, &unsafe_, objs);
104        // consts
105        Universe::def_consts(&types, &uskey, &unsafe_, objs);
106        Universe::def_nil(&types, &uskey, &unsafe_, objs);
107        // builtins
108        let builtins = Universe::builtin_funcs();
109        let ftype = types[&BasicType::Invalid];
110        Universe::def_builtins(&builtins, ftype, &uskey, &unsafe_, objs);
111        // iota byte rune
112        let (iota, byte, rune) = Universe::iota_byte_rune(&uskey, objs);
113        let slice_of_bytes = objs.new_t_slice(byte);
114        let no_value_tuple = objs.new_t_tuple(vec![]);
115        let indir = objs.new_type_name(0, None, "*".to_owned(), None);
116        let guard_sig = objs.new_t_signature(None, None, no_value_tuple, no_value_tuple, false);
117        Universe {
118            scope: uskey,
119            unsafe_: unsafe_,
120            iota: iota,
121            byte: byte,
122            rune: rune,
123            slice_of_bytes: slice_of_bytes,
124            no_value_tuple: no_value_tuple,
125            indir: indir,
126            guard_sig: guard_sig,
127            types: types,
128            builtins: builtins,
129        }
130    }
131
132    pub fn scope(&self) -> &ScopeKey {
133        &self.scope
134    }
135
136    pub fn unsafe_pkg(&self) -> &PackageKey {
137        &self.unsafe_
138    }
139
140    pub fn types(&self) -> &Map<BasicType, TypeKey> {
141        &self.types
142    }
143
144    pub fn builtins(&self) -> &Map<Builtin, BuiltinInfo> {
145        &self.builtins
146    }
147
148    pub fn iota(&self) -> &ObjKey {
149        &self.iota
150    }
151
152    pub fn byte(&self) -> &TypeKey {
153        &self.byte
154    }
155
156    pub fn rune(&self) -> &TypeKey {
157        &self.rune
158    }
159
160    pub fn slice_of_bytes(&self) -> &TypeKey {
161        &self.slice_of_bytes
162    }
163
164    pub fn no_value_tuple(&self) -> &TypeKey {
165        &self.no_value_tuple
166    }
167
168    pub fn indir(&self) -> &ObjKey {
169        &self.indir
170    }
171
172    pub fn guard_sig(&self) -> &TypeKey {
173        &self.guard_sig
174    }
175
176    fn def_universe_unsafe(objs: &mut TCObjects) -> (ScopeKey, PackageKey) {
177        let uskey = objs
178            .scopes
179            .insert(Scope::new(None, 0, 0, "universe".to_owned(), false));
180        let pkg_skey = objs.scopes.insert(Scope::new(
181            Some(uskey),
182            0,
183            0,
184            "package unsafe".to_owned(),
185            false,
186        ));
187        let mut pkg = Package::new("unsafe".to_owned(), Some("unsafe".to_owned()), pkg_skey);
188        pkg.mark_complete();
189        (uskey, objs.pkgs.insert(pkg))
190    }
191
192    ///define this:
193    ///type error interface {
194    ///    Error() string
195    ///}
196    fn def_error_type(
197        types: &Map<BasicType, TypeKey>,
198        universe: &ScopeKey,
199        unsafe_: &PackageKey,
200        objs: &mut TCObjects,
201    ) {
202        let res = objs.lobjs.insert(LangObj::new_var(
203            0,
204            None,
205            "".to_owned(),
206            Some(types[&BasicType::Str]),
207        ));
208        let params = objs.new_t_tuple(vec![]);
209        let results = objs.new_t_tuple(vec![res]);
210        let sig = objs.new_t_signature(None, None, params, results, false);
211        let err = objs
212            .lobjs
213            .insert(LangObj::new_func(0, None, "Error".to_owned(), Some(sig)));
214        let inter_detail = InterfaceDetail::new(vec![err], vec![], objs);
215        inter_detail.complete(objs);
216        let underlying = objs.types.insert(Type::Interface(inter_detail));
217        let typ = objs.new_t_named(None, Some(underlying), vec![]);
218        let recv = objs
219            .lobjs
220            .insert(LangObj::new_var(0, None, "".to_owned(), Some(typ)));
221        objs.types[sig]
222            .try_as_signature_mut()
223            .unwrap()
224            .set_recv(Some(recv));
225        let type_name = objs.lobjs.insert(LangObj::new_type_name(
226            0,
227            None,
228            "error".to_owned(),
229            Some(typ),
230        ));
231        Universe::def(type_name, universe, unsafe_, objs);
232    }
233
234    fn def_basic_types(
235        types: &Map<BasicType, TypeKey>,
236        universe: &ScopeKey,
237        unsafe_: &PackageKey,
238        objs: &mut TCObjects,
239    ) {
240        for (_, v) in types {
241            let name = objs.types[*v].try_as_basic().unwrap().name();
242            let t = objs
243                .lobjs
244                .insert(LangObj::new_type_name(0, None, name.to_owned(), Some(*v)));
245            Universe::def(t, universe, unsafe_, objs);
246        }
247    }
248
249    fn basic_types(tobjs: &mut Types) -> Map<BasicType, TypeKey> {
250        vec![
251            // use vec becasue array doesn't have into_iter()!
252            // may be more expensive, but looks better this way.
253            (BasicType::Invalid, BasicInfo::IsInvalid, "invalid type"),
254            (BasicType::Bool, BasicInfo::IsBoolean, "bool"),
255            (BasicType::Int, BasicInfo::IsInteger, "int"),
256            (BasicType::Int8, BasicInfo::IsInteger, "int8"),
257            (BasicType::Int16, BasicInfo::IsInteger, "int16"),
258            (BasicType::Int32, BasicInfo::IsInteger, "int32"),
259            (BasicType::Int64, BasicInfo::IsInteger, "int64"),
260            (BasicType::Uint, BasicInfo::IsInteger, "uint"),
261            (BasicType::Uint8, BasicInfo::IsInteger, "uint8"),
262            (BasicType::Uint16, BasicInfo::IsInteger, "uint16"),
263            (BasicType::Uint32, BasicInfo::IsInteger, "uint32"),
264            (BasicType::Uint64, BasicInfo::IsInteger, "uint64"),
265            (BasicType::Uintptr, BasicInfo::IsInteger, "uintptr"),
266            (BasicType::Float32, BasicInfo::IsFloat, "float32"),
267            (BasicType::Float64, BasicInfo::IsFloat, "float64"),
268            (BasicType::Complex64, BasicInfo::IsComplex, "complex64"),
269            (BasicType::Complex128, BasicInfo::IsComplex, "complex128"),
270            (BasicType::Str, BasicInfo::IsString, "string"),
271            (BasicType::UnsafePointer, BasicInfo::IsInvalid, "Pointer"),
272            (BasicType::UntypedBool, BasicInfo::IsBoolean, "untyped bool"),
273            (BasicType::UntypedInt, BasicInfo::IsInteger, "untyped int"),
274            (BasicType::UntypedRune, BasicInfo::IsInteger, "untyped rune"),
275            (BasicType::UntypedFloat, BasicInfo::IsFloat, "untyped float"),
276            (
277                BasicType::UntypedComplex,
278                BasicInfo::IsComplex,
279                "untyped complex",
280            ),
281            (
282                BasicType::UntypedString,
283                BasicInfo::IsString,
284                "untyped string",
285            ),
286            (BasicType::UntypedNil, BasicInfo::IsInvalid, "untyped nil"),
287        ]
288        .into_iter()
289        .map(|(t, i, n)| (t, tobjs.insert(Type::Basic(BasicDetail::new(t, i, n)))))
290        .collect::<Map<_, _>>()
291    }
292
293    fn alias_types(tobjs: &mut Types) -> Map<BasicType, TypeKey> {
294        [
295            (BasicType::Byte, BasicInfo::IsInteger, "byte"),
296            (BasicType::Rune, BasicInfo::IsInteger, "rune"),
297        ]
298        .iter()
299        .map(|(t, i, n)| (*t, tobjs.insert(Type::Basic(BasicDetail::new(*t, *i, n)))))
300        .collect::<Map<_, _>>()
301    }
302
303    fn def_consts(
304        types: &Map<BasicType, TypeKey>,
305        universe: &ScopeKey,
306        unsafe_: &PackageKey,
307        objs: &mut TCObjects,
308    ) {
309        for (n, t, v) in vec![
310            // use vec becasue array doesn't have into_iter()!
311            (
312                "true",
313                BasicType::UntypedBool,
314                constant::Value::with_bool(true),
315            ),
316            (
317                "false",
318                BasicType::UntypedBool,
319                constant::Value::with_bool(false),
320            ),
321            ("iota", BasicType::UntypedInt, constant::Value::with_i64(0)),
322        ]
323        .into_iter()
324        {
325            let cst = LangObj::new_const(0, None, n.to_owned(), Some(types[&t]), v);
326            Universe::def(objs.lobjs.insert(cst), universe, unsafe_, objs);
327        }
328    }
329
330    fn def_nil(
331        types: &Map<BasicType, TypeKey>,
332        universe: &ScopeKey,
333        unsafe_: &PackageKey,
334        objs: &mut TCObjects,
335    ) {
336        let nil = LangObj::new_nil(types[&BasicType::UntypedNil]);
337        Universe::def(objs.lobjs.insert(nil), universe, unsafe_, objs);
338    }
339
340    fn builtin_funcs() -> Map<Builtin, BuiltinInfo> {
341        vec![
342            // use vec becasue array doesn't have into_iter()!
343            (Builtin::Append, "append", 1, true, ExprKind::Expression),
344            (Builtin::Cap, "cap", 1, false, ExprKind::Expression),
345            (Builtin::Close, "close", 1, false, ExprKind::Statement),
346            (Builtin::Complex, "complex", 2, false, ExprKind::Expression),
347            (Builtin::Copy, "copy", 2, false, ExprKind::Statement),
348            (Builtin::Delete, "delete", 2, false, ExprKind::Statement),
349            (Builtin::Imag, "imag", 1, false, ExprKind::Expression),
350            (Builtin::Len, "len", 1, false, ExprKind::Expression),
351            (Builtin::Make, "make", 1, true, ExprKind::Expression),
352            (Builtin::New, "new", 1, false, ExprKind::Expression),
353            (Builtin::Panic, "panic", 1, false, ExprKind::Statement),
354            (Builtin::Print, "print", 0, true, ExprKind::Statement),
355            (Builtin::Println, "println", 0, true, ExprKind::Statement),
356            (Builtin::Real, "real", 1, false, ExprKind::Expression),
357            (Builtin::Recover, "recover", 0, false, ExprKind::Statement),
358            (Builtin::Alignof, "Alignof", 1, false, ExprKind::Expression),
359            (
360                Builtin::Offsetof,
361                "Offsetof",
362                1,
363                false,
364                ExprKind::Expression,
365            ),
366            (Builtin::Sizeof, "Sizeof", 1, false, ExprKind::Expression),
367            (Builtin::Assert, "assert", 1, false, ExprKind::Statement),
368            (Builtin::Trace, "trace", 0, true, ExprKind::Statement),
369            (Builtin::Ffi, "ffi", 2, false, ExprKind::Expression),
370        ]
371        .into_iter()
372        .map(|(f, name, no, v, k)| {
373            (
374                f,
375                BuiltinInfo {
376                    name: name,
377                    arg_count: no,
378                    variadic: v,
379                    kind: k,
380                },
381            )
382        })
383        .collect::<Map<_, _>>()
384    }
385
386    fn def_builtins(
387        builtins: &Map<Builtin, BuiltinInfo>,
388        typ: TypeKey,
389        universe: &ScopeKey,
390        unsafe_: &PackageKey,
391        objs: &mut TCObjects,
392    ) {
393        for (f, info) in builtins.iter() {
394            let fobj = objs
395                .lobjs
396                .insert(LangObj::new_builtin(*f, info.name.to_owned(), typ));
397            Universe::def(fobj, universe, unsafe_, objs);
398        }
399    }
400
401    fn iota_byte_rune(universe: &ScopeKey, objs: &mut TCObjects) -> (ObjKey, TypeKey, TypeKey) {
402        let scope = &objs.scopes[*universe];
403        let iota = *scope.lookup("iota").unwrap();
404        let byte = objs.lobjs[*scope.lookup("byte").unwrap()].typ().unwrap();
405        let rune = objs.lobjs[*scope.lookup("rune").unwrap()].typ().unwrap();
406        (iota, byte, rune)
407    }
408
409    // Objects with names containing blanks are internal and not entered into
410    // a scope. Objects with exported names are inserted in the unsafe package
411    // scope; other objects are inserted in the universe scope.
412    fn def(okey: ObjKey, universe: &ScopeKey, unsafe_: &PackageKey, objs: &mut TCObjects) {
413        let obj = &objs.lobjs[okey];
414        assert!(obj.color() == ObjColor::Black);
415        if obj.name().contains(' ') {
416            return;
417        }
418        // fix Obj link for named types
419        let typ_val = &mut objs.types[obj.typ().unwrap()];
420        if let Some(n) = typ_val.try_as_named_mut() {
421            n.set_obj(okey);
422        }
423
424        let skey = if obj.exported() {
425            match obj.entity_type() {
426                EntityType::TypeName | EntityType::Builtin(_) => {
427                    objs.lobjs[okey].set_pkg(Some(*unsafe_))
428                }
429                _ => unreachable!(),
430            }
431            objs.pkgs[*unsafe_].scope()
432        } else {
433            universe
434        };
435        let re = Scope::insert(*skey, okey, objs);
436        assert!(re.is_none());
437    }
438}