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
41pub 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 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 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}