goscript_types/
objects.rs

1#![allow(unused_macros)]
2#![allow(dead_code)]
3use super::check::DeclInfo;
4use super::constant;
5use super::obj::LangObj;
6use super::package::Package;
7use super::scope::Scope;
8use super::typ::*;
9use super::universe::Universe;
10use goscript_parser::position;
11use std::borrow::Cow;
12
13use slotmap::{new_key_type, DenseSlotMap};
14
15const DEFAULT_CAPACITY: usize = 16;
16
17macro_rules! null_key {
18    () => {
19        slotmap::Key::null()
20    };
21}
22
23macro_rules! new_objects {
24    () => {
25        DenseSlotMap::with_capacity_and_key(DEFAULT_CAPACITY)
26    };
27}
28
29new_key_type! { pub struct ObjKey; }
30new_key_type! { pub struct TypeKey; }
31new_key_type! { pub struct PackageKey; }
32new_key_type! { pub struct DeclInfoKey; }
33new_key_type! { pub struct ScopeKey; }
34
35pub type LangObjs = DenseSlotMap<ObjKey, LangObj>;
36pub type Types = DenseSlotMap<TypeKey, Type>;
37pub type Packages = DenseSlotMap<PackageKey, Package>;
38pub type Decls = DenseSlotMap<DeclInfoKey, DeclInfo>;
39pub type Scopes = DenseSlotMap<ScopeKey, Scope>;
40
41/// The container of all "managed" objects
42/// also works as a "global" variable holder
43pub struct TCObjects {
44    pub lobjs: LangObjs,
45    pub types: Types,
46    pub pkgs: Packages,
47    pub decls: Decls,
48    pub scopes: Scopes,
49    pub universe: Option<Universe>,
50    // "global" variable
51    pub fmt_qualifier: Box<dyn Fn(&Package) -> Cow<str>>,
52}
53
54fn default_fmt_qualifier(p: &Package) -> Cow<str> {
55    p.path().into()
56}
57
58impl TCObjects {
59    pub fn new() -> TCObjects {
60        let fmtq = Box::new(default_fmt_qualifier);
61        let mut objs = TCObjects {
62            lobjs: new_objects!(),
63            types: new_objects!(),
64            pkgs: new_objects!(),
65            decls: new_objects!(),
66            scopes: new_objects!(),
67            universe: None,
68            fmt_qualifier: fmtq,
69        };
70        objs.universe = Some(Universe::new(&mut objs));
71        objs
72    }
73
74    pub fn universe(&self) -> &Universe {
75        self.universe.as_ref().unwrap()
76    }
77
78    pub fn new_scope(
79        &mut self,
80        parent: Option<ScopeKey>,
81        pos: position::Pos,
82        end: position::Pos,
83        comment: String,
84        is_func: bool,
85    ) -> ScopeKey {
86        let scope = Scope::new(parent, pos, end, comment, is_func);
87        let skey = self.scopes.insert(scope);
88        if let Some(s) = parent {
89            // don't add children to Universe scope
90            if s != *self.universe().scope() {
91                self.scopes[s].add_child(skey);
92            }
93        }
94        skey
95    }
96
97    pub fn new_package(&mut self, path: String) -> PackageKey {
98        let skey = self.new_scope(
99            Some(*self.universe().scope()),
100            0,
101            0,
102            format!("package {}", path),
103            false,
104        );
105        let pkg = Package::new(path, None, skey);
106        self.pkgs.insert(pkg)
107    }
108
109    pub fn new_pkg_name(
110        &mut self,
111        pos: position::Pos,
112        pkg: Option<PackageKey>,
113        name: String,
114        imported: PackageKey,
115    ) -> ObjKey {
116        let lobj = LangObj::new_pkg_name(pos, pkg, name, imported, self.universe());
117        self.lobjs.insert(lobj)
118    }
119
120    pub fn new_const(
121        &mut self,
122        pos: position::Pos,
123        pkg: Option<PackageKey>,
124        name: String,
125        typ: Option<TypeKey>,
126        val: constant::Value,
127    ) -> ObjKey {
128        let lobj = LangObj::new_const(pos, pkg, name, typ, val);
129        self.lobjs.insert(lobj)
130    }
131
132    pub fn new_type_name(
133        &mut self,
134        pos: position::Pos,
135        pkg: Option<PackageKey>,
136        name: String,
137        typ: Option<TypeKey>,
138    ) -> ObjKey {
139        let lobj = LangObj::new_type_name(pos, pkg, name, typ);
140        self.lobjs.insert(lobj)
141    }
142
143    pub fn new_var(
144        &mut self,
145        pos: position::Pos,
146        pkg: Option<PackageKey>,
147        name: String,
148        typ: Option<TypeKey>,
149    ) -> ObjKey {
150        let lobj = LangObj::new_var(pos, pkg, name, typ);
151        self.lobjs.insert(lobj)
152    }
153
154    pub fn new_param_var(
155        &mut self,
156        pos: position::Pos,
157        pkg: Option<PackageKey>,
158        name: String,
159        typ: Option<TypeKey>,
160    ) -> ObjKey {
161        let lobj = LangObj::new_param_var(pos, pkg, name, typ);
162        self.lobjs.insert(lobj)
163    }
164
165    pub fn new_field(
166        &mut self,
167        pos: position::Pos,
168        pkg: Option<PackageKey>,
169        name: String,
170        typ: Option<TypeKey>,
171        embedded: bool,
172    ) -> ObjKey {
173        let lobj = LangObj::new_field(pos, pkg, name, typ, embedded);
174        self.lobjs.insert(lobj)
175    }
176
177    pub fn new_func(
178        &mut self,
179        pos: position::Pos,
180        pkg: Option<PackageKey>,
181        name: String,
182        typ: Option<TypeKey>,
183    ) -> ObjKey {
184        let lobj = LangObj::new_func(pos, pkg, name, typ);
185        self.lobjs.insert(lobj)
186    }
187
188    pub fn new_label(
189        &mut self,
190        pos: position::Pos,
191        pkg: Option<PackageKey>,
192        name: String,
193    ) -> ObjKey {
194        let lobj = LangObj::new_label(pos, pkg, name, self.universe());
195        self.lobjs.insert(lobj)
196    }
197
198    pub fn new_t_basic(&mut self, typ: BasicType, info: BasicInfo, name: &'static str) -> TypeKey {
199        self.types
200            .insert(Type::Basic(BasicDetail::new(typ, info, name)))
201    }
202
203    pub fn new_t_array(&mut self, elem: TypeKey, len: Option<u64>) -> TypeKey {
204        self.types.insert(Type::Array(ArrayDetail::new(elem, len)))
205    }
206
207    pub fn new_t_slice(&mut self, elem: TypeKey) -> TypeKey {
208        self.types.insert(Type::Slice(SliceDetail::new(elem)))
209    }
210
211    pub fn new_t_struct(
212        &mut self,
213        fields: Vec<ObjKey>,
214        tags: Option<Vec<Option<String>>>,
215    ) -> TypeKey {
216        self.types
217            .insert(Type::Struct(StructDetail::new(fields, tags, self)))
218    }
219    pub fn new_t_pointer(&mut self, base: TypeKey) -> TypeKey {
220        self.types.insert(Type::Pointer(PointerDetail::new(base)))
221    }
222
223    pub fn new_t_tuple(&mut self, vars: Vec<ObjKey>) -> TypeKey {
224        self.types.insert(Type::Tuple(TupleDetail::new(vars)))
225    }
226
227    pub fn new_t_signature(
228        &mut self,
229        scope: Option<ScopeKey>,
230        recv: Option<ObjKey>,
231        params: TypeKey,
232        results: TypeKey,
233        variadic: bool,
234    ) -> TypeKey {
235        self.types.insert(Type::Signature(SignatureDetail::new(
236            scope, recv, params, results, variadic, self,
237        )))
238    }
239
240    pub fn new_t_interface(&mut self, methods: Vec<ObjKey>, embeddeds: Vec<TypeKey>) -> TypeKey {
241        let iface = Type::Interface(InterfaceDetail::new(methods, embeddeds, self));
242        self.types.insert(iface)
243    }
244
245    pub fn new_t_empty_interface(&mut self) -> TypeKey {
246        self.types
247            .insert(Type::Interface(InterfaceDetail::new_empty()))
248    }
249
250    pub fn new_t_map(&mut self, key: TypeKey, elem: TypeKey) -> TypeKey {
251        self.types.insert(Type::Map(MapDetail::new(key, elem)))
252    }
253    pub fn new_t_chan(&mut self, dir: ChanDir, elem: TypeKey) -> TypeKey {
254        self.types.insert(Type::Chan(ChanDetail::new(dir, elem)))
255    }
256    pub fn new_t_named(
257        &mut self,
258        obj: Option<ObjKey>,
259        underlying: Option<TypeKey>,
260        methods: Vec<ObjKey>,
261    ) -> TypeKey {
262        self.types.insert(Type::Named(NamedDetail::new(
263            obj, underlying, methods, self,
264        )))
265    }
266}