1 // Copyright 2014 Wouter van Oortmerssen. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef LOBSTER_IDENTS
16 #define LOBSTER_IDENTS
17
18 #include "lobster/natreg.h"
19
20 #define FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
21 #include "lobster/bytecode_generated.h"
22
23 namespace lobster {
24
25 struct NativeFun;
26 struct SymbolTable;
27
28 struct Node;
29 struct List;
30
31 struct Function;
32 struct SubFunction;
33
34 struct SpecIdent;
35
36 struct Ident : Named {
37 size_t scopelevel;
38
39 bool single_assignment = true; // not declared const but def only, exp may or may not be const
40 bool constant = false; // declared const
41 bool static_constant = false; // not declared const but def only, exp is const.
42 bool anonymous_arg = false;
43 bool logvar = false;
44
45 SpecIdent *cursid = nullptr;
46
IdentIdent47 Ident(string_view _name, int _idx, size_t _sl)
48 : Named(_name, _idx), scopelevel(_sl) {}
49
AssignIdent50 void Assign(Lex &lex) {
51 single_assignment = false;
52 if (constant)
53 lex.Error("variable " + name + " is constant");
54 }
55
SerializeIdent56 flatbuffers::Offset<bytecode::Ident> Serialize(flatbuffers::FlatBufferBuilder &fbb,
57 bool is_top_level) {
58 return bytecode::CreateIdent(fbb, fbb.CreateString(name), constant, is_top_level);
59 }
60 };
61
62 struct SpecIdent {
63 Ident *id;
64 TypeRef type;
65 Lifetime lt = LT_UNDEF;
66 bool consume_on_last_use = false;
67 int logvaridx = -1;
68 int idx, sidx = -1; // Into specidents, and into vm ordering.
69 SubFunction *sf_def = nullptr; // Where it is defined, including anonymous functions.
70
SpecIdentSpecIdent71 SpecIdent(Ident *_id, TypeRef _type, int idx)
72 : id(_id), type(_type), idx(idx){}
IdxSpecIdent73 int Idx() { assert(sidx >= 0); return sidx; }
CurrentSpecIdent74 SpecIdent *&Current() { return id->cursid; }
75 };
76
77 struct Enum;
78
79 struct EnumVal : Named {
80 int64_t val = 0;
81 Enum *e = nullptr;
82
EnumValEnumVal83 EnumVal(string_view _name, int _idx) : Named(_name, _idx) {}
84 };
85
86 struct Enum : Named {
87 vector<unique_ptr<EnumVal>> vals;
88 Type thistype;
89
EnumEnum90 Enum(string_view _name, int _idx) : Named(_name, _idx) {
91 thistype = Type { this };
92 }
93
SerializeEnum94 flatbuffers::Offset<bytecode::Enum> Serialize(flatbuffers::FlatBufferBuilder &fbb) {
95 vector<flatbuffers::Offset<bytecode::EnumVal>> valoffsets;
96 for (auto &v : vals)
97 valoffsets.push_back(
98 bytecode::CreateEnumVal(fbb, fbb.CreateString(v->name), v->val));
99 return bytecode::CreateEnum(fbb, fbb.CreateString(name), fbb.CreateVector(valoffsets));
100 }
101 };
102
103 // Only still needed because we have no idea which struct it refers to at parsing time.
104 struct SharedField : Named {
SharedFieldSharedField105 SharedField(string_view _name, int _idx) : Named(_name, _idx) {}
SharedFieldSharedField106 SharedField() : SharedField("", 0) {}
107 };
108
109 struct Field {
110 TypeRef type;
111 SharedField *id = nullptr;
112 int genericref = -1;
113 Node *defaultval = nullptr;
114 int slot = -1;
115
116 Field() = default;
FieldField117 Field(SharedField *_id, TypeRef _type, int _genericref, Node *_defaultval)
118 : type(_type), id(_id),
119 genericref(_genericref), defaultval(_defaultval) {}
120 Field(const Field &o);
121 ~Field();
122 };
123
124 struct FieldVector : GenericArgs {
125 vector<Field> v;
126
FieldVectorFieldVector127 FieldVector(size_t nargs) : v(nargs) {}
128
sizeFieldVector129 size_t size() const { return v.size(); }
GetTypeFieldVector130 TypeRef GetType(size_t i) const { return v[i].type; }
GetFlagsFieldVector131 ArgFlags GetFlags(size_t) const { return AF_NONE; }
GetNameFieldVector132 string_view GetName(size_t i) const { return v[i].id->name; }
133 };
134
135 struct GenericParameter {
136 string_view name;
137 };
138
139 struct DispatchEntry {
140 SubFunction *sf = nullptr;
141 bool is_dispatch_root = false;
142 // Shared return type if root of dispatch.
143 TypeRef returntype = nullptr;
144 };
145
146 struct UDT : Named {
147 FieldVector fields { 0 };
148 vector<GenericParameter> generics;
149 UDT *next = nullptr, *first = this; // Specializations
150 UDT *superclass = nullptr;
151 bool is_struct = false, hasref = false;
152 bool predeclaration = false;
153 bool constructed = false; // Is this instantiated anywhere in the code?
154 Type thistype; // convenient place to store the type corresponding to this.
155 TypeRef sametype = type_undefined; // If all fields are int/float, this allows vector ops.
156 type_elem_t typeinfo = (type_elem_t)-1; // Runtime type.
157 int numslots = -1;
158 int vtable_start = -1;
159 vector<UDT *> subudts; // Including self.
160 // Subset of methods that participate in dynamic dispatch. Order in this table determines
161 // vtable layout and is compatible with sub/super classes.
162 // Multiple specializations of a method may be in here.
163 // Methods whose dispatch can be determined statically for the current program do not end up
164 // in here.
165 vector<DispatchEntry> dispatch;
166
UDTUDT167 UDT(string_view _name, int _idx, bool is_struct) : Named(_name, _idx), is_struct(is_struct) {
168 thistype = is_struct ? Type { V_STRUCT_R, this } : Type { V_CLASS, this };
169 }
170
HasUDT171 int Has(SharedField *fld) {
172 for (auto &uf : fields.v) if (uf.id == fld) return int(&uf - &fields.v[0]);
173 return -1;
174 }
175
CloneIntoUDT176 UDT *CloneInto(UDT *st) {
177 *st = *this;
178 st->thistype.udt = st;
179 st->next = next;
180 st->first = first;
181 next = st;
182 return st;
183 }
184
IsSpecializationUDT185 bool IsSpecialization(UDT *other) {
186 if (!generics.empty()) {
187 for (auto udt = first->next; udt; udt = udt->next)
188 if (udt == other)
189 return true;
190 return false;
191 } else {
192 return this == other;
193 }
194 }
195
NumSuperTypesUDT196 int NumSuperTypes() {
197 int n = 0;
198 for (auto t = superclass; t; t = t->superclass) n++;
199 return n;
200 }
201
202 bool ComputeSizes(int depth = 0) {
203 if (numslots >= 0) return true;
204 if (depth > 16) return false; // Simple protection against recursive references.
205 int size = 0;
206 for (auto &uf : fields.v) {
207 uf.slot = size;
208 if (IsStruct(uf.type->t)) {
209 if (!uf.type->udt->ComputeSizes(depth + 1)) return false;
210 size += uf.type->udt->numslots;
211 } else {
212 size++;
213 }
214 }
215 numslots = size;
216 return true;
217 }
218
SerializeUDT219 flatbuffers::Offset<bytecode::UDT> Serialize(flatbuffers::FlatBufferBuilder &fbb) {
220 vector<flatbuffers::Offset<bytecode::Field>> fieldoffsets;
221 for (auto f : fields.v)
222 fieldoffsets.push_back(
223 bytecode::CreateField(fbb, fbb.CreateString(f.id->name), f.slot));
224 return bytecode::CreateUDT(fbb, fbb.CreateString(name), idx,
225 fbb.CreateVector(fieldoffsets), numslots);
226 }
227 };
228
ValWidth(TypeRef type)229 inline int ValWidth(TypeRef type) { return IsStruct(type->t) ? type->udt->numslots : 1; }
230
FindSlot(const UDT & udt,int i)231 inline const Field *FindSlot(const UDT &udt, int i) {
232 for (auto &f : udt.fields.v) if (i >= f.slot && i < f.slot + ValWidth(f.type)) {
233 return IsStruct(f.type->t) ? FindSlot(*f.type->udt, i - f.slot) : &f;
234 }
235 assert(false);
236 return nullptr;
237 }
238
239 struct Arg : Typed {
240 SpecIdent *sid = nullptr;
241
242 Arg() = default;
ArgArg243 Arg(const Arg &o) : Typed(o), sid(o.sid) {}
ArgArg244 Arg(SpecIdent *_sid, TypeRef _type, ArgFlags _flags) : Typed(_type, _flags), sid(_sid) {}
245 };
246
247 struct ArgVector : GenericArgs {
248 vector<Arg> v;
249
ArgVectorArgVector250 ArgVector(size_t nargs) : v(nargs) {}
251
sizeArgVector252 size_t size() const { return v.size(); }
GetTypeArgVector253 TypeRef GetType(size_t i) const { return v[i].type; }
GetFlagsArgVector254 ArgFlags GetFlags(size_t i) const { return v[i].flags; }
GetNameArgVector255 string_view GetName(size_t i) const { return v[i].sid->id->name; }
256
AddArgVector257 bool Add(const Arg &in) {
258 for (auto &arg : v)
259 if (arg.sid->id == in.sid->id)
260 return false;
261 v.push_back(in);
262 return true;
263 }
264 };
265
266 struct Function;
267
268 struct SubFunction {
269 int idx;
270 ArgVector args { 0 };
271 ArgVector locals { 0 };
272 ArgVector freevars { 0 }; // any used from outside this scope
273 TypeRef fixedreturntype = nullptr;
274 TypeRef returntype = type_undefined;
275 size_t num_returns = 0;
276 size_t reqret = 0; // Do the caller(s) want values to be returned?
277 const Lifetime ltret = LT_KEEP;
278 vector<pair<const SubFunction *, TypeRef>> reuse_return_events;
279 bool isrecursivelycalled = false;
280 bool iscoroutine = false;
281 ArgVector coyieldsave { 0 };
282 TypeRef coresumetype;
283 type_elem_t cotypeinfo = (type_elem_t)-1;
284 List *body = nullptr;
285 SubFunction *next = nullptr;
286 Function *parent = nullptr;
287 int subbytecodestart = 0;
288 bool typechecked = false;
289 bool freevarchecked = false;
290 bool mustspecialize = false;
291 bool logvarcallgraph = false;
292 bool isdynamicfunctionvalue = false;
293 UDT *method_of = nullptr;
294 int numcallers = 0;
295 Type thistype { V_FUNCTION, this }; // convenient place to store the type corresponding to this
296
SubFunctionSubFunction297 SubFunction(int _idx) : idx(_idx) {}
298
SetParentSubFunction299 void SetParent(Function &f, SubFunction *&link) {
300 parent = &f;
301 next = link;
302 link = this;
303 }
304
305 ~SubFunction();
306 };
307
308 struct Function : Named {
309 // Start of all SubFunctions sequentially.
310 int bytecodestart = 0;
311 // functions with the same name and args, but different types (dynamic dispatch |
312 // specialization)
313 vector<SubFunction *> overloads;
314 // functions with the same name but different number of args (overloaded)
315 Function *sibf = nullptr;
316 // does not have a programmer specified name
317 bool anonymous = false;
318 // its merely a function type, has no body, but does have a set return type.
319 bool istype = false;
320 // Store the original types the function was declared with, before specialization.
321 ArgVector orig_args { 0 };
322 size_t scopelevel;
323
FunctionFunction324 Function(string_view _name, int _idx, size_t _sl)
325 : Named(_name, _idx), scopelevel(_sl) {}
~FunctionFunction326 ~Function() {}
327
nargsFunction328 size_t nargs() const { return overloads[0]->args.v.size(); }
329
NumSubfFunction330 int NumSubf() {
331 int sum = 0;
332 for (auto sf : overloads) for (; sf; sf = sf->next) sum++;
333 return sum;
334 }
335
RemoveSubFunctionFunction336 bool RemoveSubFunction(SubFunction *sf) {
337 for (auto &sfh : overloads) {
338 for (auto sfp = &sfh; *sfp; sfp = &(*sfp)->next) {
339 if (*sfp == sf) {
340 *sfp = sf->next;
341 sf->next = nullptr;
342 return true;
343 }
344 }
345 }
346 return false;
347 }
348
SerializeFunction349 flatbuffers::Offset<bytecode::Function> Serialize(flatbuffers::FlatBufferBuilder &fbb) {
350 return bytecode::CreateFunction(fbb, fbb.CreateString(name), bytecodestart);
351 }
352 };
353
354 struct SymbolTable {
355 unordered_map<string_view, Ident *> idents; // Key points to value!
356 vector<Ident *> identtable;
357 vector<Ident *> identstack;
358 vector<SpecIdent *> specidents;
359
360 unordered_map<string_view, UDT *> udts; // Key points to value!
361 vector<UDT *> udttable;
362
363 unordered_map<string_view, SharedField *> fields; // Key points to value!
364 vector<SharedField *> fieldtable;
365
366 unordered_map<string_view, Function *> functions; // Key points to value!
367 vector<Function *> functiontable;
368 vector<SubFunction *> subfunctiontable;
369 SubFunction *toplevel = nullptr;
370
371 unordered_map<string_view, Enum *> enums; // Key points to value!
372 unordered_map<string_view, EnumVal *> enumvals; // Key points to value!
373 vector<Enum *> enumtable;
374
375 vector<string> filenames;
376
377 vector<size_t> scopelevels;
378
379 struct WithStackElem { TypeRef type; Ident *id = nullptr; SubFunction *sf = nullptr; };
380 vector<WithStackElem> withstack;
381 vector<size_t> withstacklevels;
382
383 enum { NUM_VECTOR_TYPE_WRAPPINGS = 3 };
384 vector<TypeRef> default_int_vector_types[NUM_VECTOR_TYPE_WRAPPINGS],
385 default_float_vector_types[NUM_VECTOR_TYPE_WRAPPINGS];
386 Enum *default_bool_type = nullptr;
387
388 // Used during parsing.
389 vector<SubFunction *> defsubfunctionstack;
390
391 vector<Type *> typelist; // Used for constructing new vector types, variables, etc.
392 vector<vector<Type::TupleElem> *> tuplelist;
393
394 string current_namespace;
395 // FIXME: because we cleverly use string_view's into source code everywhere, we now have
396 // no way to refer to constructed strings, and need to store them seperately :(
397 // TODO: instead use larger buffers and constuct directly into those, so no temp string?
398 vector<const char *> stored_names;
399
~SymbolTableSymbolTable400 ~SymbolTable() {
401 for (auto id : identtable) delete id;
402 for (auto sid : specidents) delete sid;
403 for (auto u : udttable) delete u;
404 for (auto f : functiontable) delete f;
405 for (auto e : enumtable) delete e;
406 for (auto sf : subfunctiontable) delete sf;
407 for (auto f : fieldtable) delete f;
408 for (auto t : typelist) delete t;
409 for (auto t : tuplelist) delete t;
410 for (auto n : stored_names) delete[] n;
411 }
412
NameSpacedSymbolTable413 string NameSpaced(string_view name) {
414 assert(!current_namespace.empty());
415 return cat(current_namespace, "_", name);
416 }
417
StoreNameSymbolTable418 string_view StoreName(const string &s) {
419 auto buf = new char[s.size()];
420 memcpy(buf, s.data(), s.size()); // Look ma, no terminator :)
421 stored_names.push_back(buf);
422 return string_view(buf, s.size());
423 }
424
MaybeNameSpaceSymbolTable425 string_view MaybeNameSpace(string_view name, bool other_conditions) {
426 return other_conditions && !current_namespace.empty() && scopelevels.size() == 1
427 ? StoreName(NameSpaced(name))
428 : name;
429 }
430
LookupSymbolTable431 Ident *Lookup(string_view name) {
432 auto it = idents.find(name);
433 if (it != idents.end()) return it->second;
434 if (!current_namespace.empty()) {
435 auto it = idents.find(NameSpaced(name));
436 if (it != idents.end()) return it->second;
437 }
438 return nullptr;
439 }
440
LookupAnySymbolTable441 Ident *LookupAny(string_view name) {
442 for (auto id : identtable) if (id->name == name) return id;
443 return nullptr;
444 }
445
NewIdSymbolTable446 Ident *NewId(string_view name, SubFunction *sf) {
447 auto ident = new Ident(name, (int)identtable.size(), scopelevels.size());
448 ident->cursid = NewSid(ident, sf);
449 identtable.push_back(ident);
450 return ident;
451 }
452
LookupDefSymbolTable453 Ident *LookupDef(string_view name, Lex &lex, bool anonymous_arg, bool islocal,
454 bool withtype) {
455 auto sf = defsubfunctionstack.back();
456 auto existing_ident = Lookup(name);
457 if (anonymous_arg && existing_ident && existing_ident->cursid->sf_def == sf)
458 return existing_ident;
459 Ident *ident = nullptr;
460 if (LookupWithStruct(name, lex, ident))
461 lex.Error("cannot define variable with same name as field in this scope: " + name);
462 ident = NewId(name, sf);
463 ident->anonymous_arg = anonymous_arg;
464 (islocal ? sf->locals : sf->args).v.push_back(
465 Arg(ident->cursid, type_any, AF_GENERIC | (withtype ? AF_WITHTYPE : AF_NONE)));
466 if (existing_ident) {
467 lex.Error("identifier redefinition / shadowing: " + ident->name);
468 }
469 idents[ident->name /* must be in value */] = ident;
470 identstack.push_back(ident);
471 return ident;
472 }
473
LookupUseSymbolTable474 Ident *LookupUse(string_view name, Lex &lex) {
475 auto id = Lookup(name);
476 if (!id)
477 lex.Error("unknown identifier: " + name);
478 return id;
479 }
480
AddWithStructSymbolTable481 void AddWithStruct(TypeRef t, Ident *id, Lex &lex, SubFunction *sf) {
482 if (!IsUDT(t->t)) lex.Error(":: can only be used with struct/value types");
483 for (auto &wp : withstack)
484 if (wp.type->udt == t->udt)
485 lex.Error("type used twice in the same scope with ::");
486 // FIXME: should also check if variables have already been defined in this scope that clash
487 // with the struct, or do so in LookupUse
488 assert(t->udt);
489 withstack.push_back({ t, id, sf });
490 }
491
LookupWithStructSymbolTable492 SharedField *LookupWithStruct(string_view name, Lex &lex, Ident *&id) {
493 auto fld = FieldUse(name);
494 if (!fld) return nullptr;
495 assert(!id);
496 for (auto &wse : withstack) {
497 if (wse.type->udt->Has(fld) >= 0) {
498 if (id) lex.Error("access to ambiguous field: " + fld->name);
499 id = wse.id;
500 }
501 }
502 return id ? fld : nullptr;
503 }
504
GetWithStackBackSymbolTable505 WithStackElem GetWithStackBack() {
506 return withstack.size()
507 ? withstack.back()
508 : WithStackElem();
509 }
510
MakeLogVarSymbolTable511 void MakeLogVar(Ident *id) {
512 id->logvar = true;
513 defsubfunctionstack.back()->logvarcallgraph = true;
514 }
515
ScopeStartSymbolTable516 SubFunction *ScopeStart() {
517 scopelevels.push_back(identstack.size());
518 withstacklevels.push_back(withstack.size());
519 auto sf = CreateSubFunction();
520 defsubfunctionstack.push_back(sf);
521 return sf;
522 }
523
ScopeCleanupSymbolTable524 void ScopeCleanup() {
525 defsubfunctionstack.pop_back();
526 while (identstack.size() > scopelevels.back()) {
527 auto ident = identstack.back();
528 auto it = idents.find(ident->name);
529 if (it != idents.end()) { // can already have been removed by private var cleanup
530 idents.erase(it);
531 }
532 identstack.pop_back();
533 }
534 scopelevels.pop_back();
535 while (withstack.size() > withstacklevels.back()) withstack.pop_back();
536 withstacklevels.pop_back();
537 }
538
UnregisterStructSymbolTable539 void UnregisterStruct(const UDT *st, Lex &lex) {
540 if (st->predeclaration) lex.Error("pre-declared struct never defined: " + st->name);
541 auto it = udts.find(st->name);
542 if (it != udts.end()) udts.erase(it);
543 }
544
UnregisterFunSymbolTable545 void UnregisterFun(Function *f) {
546 auto it = functions.find(f->name);
547 if (it != functions.end()) // it can already have been removed by another variation
548 functions.erase(it);
549 }
550
UnregisterEnumSymbolTable551 void UnregisterEnum(Enum *e) {
552 for (auto &ev : e->vals) {
553 auto it = enumvals.find(ev->name);
554 assert(it != enumvals.end());
555 enumvals.erase(it);
556 }
557 auto it = enums.find(e->name);
558 assert(it != enums.end());
559 enums.erase(it);
560 }
561
EndOfIncludeSymbolTable562 void EndOfInclude() {
563 current_namespace.clear();
564 auto it = idents.begin();
565 while (it != idents.end()) {
566 if (it->second->isprivate) {
567 idents.erase(it++);
568 } else
569 it++;
570 }
571 }
572
EnumLookupSymbolTable573 Enum *EnumLookup(string_view name, Lex &lex, bool decl) {
574 auto eit = enums.find(name);
575 if (eit != enums.end()) {
576 if (decl) lex.Error("double declaration of enum: " + name);
577 return eit->second;
578 }
579 if (!decl) {
580 if (!current_namespace.empty()) {
581 eit = enums.find(NameSpaced(name));
582 if (eit != enums.end()) return eit->second;
583 }
584 return nullptr;
585 }
586 auto e = new Enum(name, (int)enumtable.size());
587 enumtable.push_back(e);
588 enums[e->name /* must be in value */] = e;
589 return e;
590 }
591
EnumValLookupSymbolTable592 EnumVal *EnumValLookup(string_view name, Lex &lex, bool decl) {
593 auto evit = enumvals.find(name);
594 if (evit != enumvals.end()) {
595 if (decl) lex.Error("double declaration of enum value: " + name);
596 return evit->second;
597 }
598 if (!decl) {
599 if (!current_namespace.empty()) {
600 evit = enumvals.find(NameSpaced(name));
601 if (evit != enumvals.end()) return evit->second;
602 }
603 return nullptr;
604 }
605 auto ev = new EnumVal(name, 0);
606 enumvals[ev->name /* must be in value */] = ev;
607 return ev;
608 }
609
StructDeclSymbolTable610 UDT &StructDecl(string_view name, Lex &lex, bool is_struct) {
611 auto uit = udts.find(name);
612 if (uit != udts.end()) {
613 if (!uit->second->predeclaration)
614 lex.Error("double declaration of type: " + name);
615 if (uit->second->is_struct != is_struct)
616 lex.Error("class/struct previously declared as different kind");
617 uit->second->predeclaration = false;
618 return *uit->second;
619 }
620 auto st = new UDT(name, (int)udttable.size(), is_struct);
621 udts[st->name /* must be in value */] = st;
622 udttable.push_back(st);
623 return *st;
624 }
625
StructUseSymbolTable626 UDT &StructUse(string_view name, Lex &lex) {
627 auto uit = udts.find(name);
628 if (uit != udts.end()) return *uit->second;
629 if (!current_namespace.empty()) {
630 uit = udts.find(NameSpaced(name));
631 if (uit != udts.end()) return *uit->second;
632 }
633 lex.Error("unknown type: " + name);
634 return *uit->second;
635 }
636
SuperDistanceSymbolTable637 int SuperDistance(const UDT *sup, const UDT *sub) {
638 int dist = 0;
639 for (auto t = sub; t; t = t->superclass) {
640 if (t == sup) return dist;
641 dist++;
642 }
643 return -1;
644 }
645
CommonSuperTypeSymbolTable646 const UDT *CommonSuperType(const UDT *a, const UDT *b) {
647 if (a != b) for (;;) {
648 a = a->superclass;
649 if (!a) return nullptr;
650 if (SuperDistance(a, b) >= 0) break;
651 }
652 return a;
653 }
654
FieldDeclSymbolTable655 SharedField &FieldDecl(string_view name) {
656 auto fld = FieldUse(name);
657 if (fld) return *fld;
658 fld = new SharedField(name, (int)fieldtable.size());
659 fields[fld->name /* must be in value */] = fld;
660 fieldtable.push_back(fld);
661 return *fld;
662 }
663
FieldUseSymbolTable664 SharedField *FieldUse(string_view name) {
665 auto it = fields.find(name);
666 return it != fields.end() ? it->second : nullptr;
667 }
668
CreateSubFunctionSymbolTable669 SubFunction *CreateSubFunction() {
670 auto sf = new SubFunction((int)subfunctiontable.size());
671 subfunctiontable.push_back(sf);
672 return sf;
673 }
674
CreateFunctionSymbolTable675 Function &CreateFunction(string_view name, string_view context) {
676 auto fname = name.length() ? string(name) : cat("function", functiontable.size(), context);
677 auto f = new Function(fname, (int)functiontable.size(), scopelevels.size());
678 functiontable.push_back(f);
679 return *f;
680 }
681
FunctionDeclSymbolTable682 Function &FunctionDecl(string_view name, size_t nargs, Lex &lex) {
683 auto fit = functions.find(name);
684 if (fit != functions.end()) {
685 if (fit->second->scopelevel != scopelevels.size())
686 lex.Error("cannot define a variation of function " + name +
687 " at a different scope level");
688 for (auto f = fit->second; f; f = f->sibf)
689 if (f->nargs() == nargs)
690 return *f;
691 }
692 auto &f = CreateFunction(name, "");
693 if (fit != functions.end()) {
694 f.sibf = fit->second->sibf;
695 fit->second->sibf = &f;
696 } else {
697 functions[f.name /* must be in value */] = &f;
698 }
699 return f;
700 }
701
FindFunctionSymbolTable702 Function *FindFunction(string_view name) {
703 auto it = functions.find(name);
704 if (it != functions.end()) return it->second;
705 if (!current_namespace.empty()) {
706 auto it = functions.find(NameSpaced(name));
707 if (it != functions.end()) return it->second;
708 }
709 return nullptr;
710 }
711
712 SpecIdent *NewSid(Ident *id, SubFunction *sf, TypeRef type = nullptr) {
713 auto sid = new SpecIdent(id, type, (int)specidents.size());
714 sid->sf_def = sf;
715 specidents.push_back(sid);
716 return sid;
717 }
718
CloneSidsSymbolTable719 void CloneSids(ArgVector &av, SubFunction *sf) {
720 for (auto &a : av.v) {
721 a.sid = NewSid(a.sid->id, sf);
722 }
723 }
724
CloneIdsSymbolTable725 void CloneIds(SubFunction &sf, const SubFunction &o) {
726 sf.args = o.args; CloneSids(sf.args, &sf);
727 sf.locals = o.locals; CloneSids(sf.locals, &sf);
728 // Don't clone freevars, these will be accumulated in the new copy anew.
729 }
730
NewTypeSymbolTable731 Type *NewType() {
732 // These get allocated for very few nodes, given that most types are shared or stored in
733 // their own struct.
734 auto t = new Type();
735 typelist.push_back(t);
736 return t;
737 }
738
WrapSymbolTable739 TypeRef Wrap(TypeRef elem, ValueType with) {
740 auto wt = WrapKnown(elem, with);
741 return !wt.Null() ? wt : elem->Wrap(NewType(), with);
742 }
743
RegisterTypeVectorSymbolTable744 bool RegisterTypeVector(vector<TypeRef> *sv, const char **names) {
745 if (sv[0].size()) return true; // Already initialized.
746 for (size_t i = 0; i < NUM_VECTOR_TYPE_WRAPPINGS; i++) {
747 sv[i].push_back(nullptr);
748 sv[i].push_back(nullptr);
749 }
750 for (auto name = names; *name; name++) {
751 // Can't use stucts.find, since all are out of scope.
752 for (auto udt : udttable) if (udt->name == *name) {
753 for (size_t i = 0; i < NUM_VECTOR_TYPE_WRAPPINGS; i++) {
754 auto vt = TypeRef(&udt->thistype);
755 for (size_t j = 0; j < i; j++) vt = Wrap(vt, V_VECTOR);
756 sv[i].push_back(vt);
757 }
758 goto found;
759 }
760 return false;
761 found:;
762 }
763 return true;
764 }
765
RegisterDefaultTypesSymbolTable766 bool RegisterDefaultTypes() {
767 // TODO: This isn't great hardcoded in the compiler, would be better if it was declared in
768 // lobster code.
769 for (auto e : enumtable) {
770 if (e->name == "bool") {
771 default_bool_type = e;
772 break;
773 }
774 }
775 static const char *default_int_vector_type_names[] =
776 { "xy_i", "xyz_i", "xyzw_i", nullptr };
777 static const char *default_float_vector_type_names[] =
778 { "xy_f", "xyz_f", "xyzw_f", nullptr };
779 return RegisterTypeVector(default_int_vector_types, default_int_vector_type_names) &&
780 RegisterTypeVector(default_float_vector_types, default_float_vector_type_names) &&
781 default_bool_type;
782 }
783
VectorTypeSymbolTable784 TypeRef VectorType(TypeRef vt, size_t level, int arity) const {
785 return vt->sub->t == V_INT
786 ? default_int_vector_types[level][arity]
787 : default_float_vector_types[level][arity];
788 }
789
IsGenericSymbolTable790 bool IsGeneric(TypeRef type) {
791 if (type->t == V_ANY) return true;
792 auto u = type->UnWrapped();
793 return IsUDT(u->t) && !u->udt->generics.empty();
794 }
795
796 // This one is used to sort types for multi-dispatch.
IsLessGeneralThanSymbolTable797 bool IsLessGeneralThan(const Type &a, const Type &b) const {
798 if (a.t != b.t) return a.t > b.t;
799 switch (a.t) {
800 case V_VECTOR:
801 case V_NIL:
802 return IsLessGeneralThan(*a.sub, *b.sub);
803 case V_FUNCTION:
804 return a.sf->idx < b.sf->idx;
805 case V_STRUCT_R:
806 case V_STRUCT_S:
807 case V_CLASS: {
808 if (a.udt == b.udt) return false;
809 auto ans = a.udt->NumSuperTypes();
810 auto bns = b.udt->NumSuperTypes();
811 return ans != bns
812 ? ans > bns
813 : a.udt->idx < b.udt->idx;
814 }
815 default:
816 return false;
817 }
818 }
819
SerializeSymbolTable820 void Serialize(vector<int> &code,
821 vector<uchar> &code_attr,
822 vector<type_elem_t> &typetable,
823 vector<type_elem_t> &vint_typeoffsets,
824 vector<type_elem_t> &vfloat_typeoffsets,
825 vector<bytecode::LineInfo> &linenumbers,
826 vector<bytecode::SpecIdent> &sids,
827 vector<string_view> &stringtable,
828 vector<int> &speclogvars,
829 string &bytecode,
830 vector<int> &vtables) {
831 flatbuffers::FlatBufferBuilder fbb;
832 vector<flatbuffers::Offset<flatbuffers::String>> fns;
833 for (auto &f : filenames) fns.push_back(fbb.CreateString(f));
834 vector<flatbuffers::Offset<bytecode::Function>> functionoffsets;
835 for (auto f : functiontable) functionoffsets.push_back(f->Serialize(fbb));
836 vector<flatbuffers::Offset<bytecode::UDT>> udtoffsets;
837 for (auto u : udttable) udtoffsets.push_back(u->Serialize(fbb));
838 vector<flatbuffers::Offset<bytecode::Ident>> identoffsets;
839 for (auto i : identtable) identoffsets.push_back(i->Serialize(fbb, i->cursid->sf_def == toplevel));
840 vector<flatbuffers::Offset<bytecode::Enum>> enumoffsets;
841 for (auto e : enumtable) enumoffsets.push_back(e->Serialize(fbb));
842 auto bcf = bytecode::CreateBytecodeFile(fbb,
843 LOBSTER_BYTECODE_FORMAT_VERSION,
844 fbb.CreateVector(code),
845 fbb.CreateVector(code_attr),
846 fbb.CreateVector((vector<int> &)typetable),
847 fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(stringtable.size(),
848 [&](size_t i) {
849 return fbb.CreateString(stringtable[i].data(), stringtable[i].size());
850 }
851 ),
852 fbb.CreateVectorOfStructs(linenumbers),
853 fbb.CreateVector(fns),
854 fbb.CreateVector(functionoffsets),
855 fbb.CreateVector(udtoffsets),
856 fbb.CreateVector(identoffsets),
857 fbb.CreateVectorOfStructs(sids),
858 fbb.CreateVector((vector<int> &)vint_typeoffsets),
859 fbb.CreateVector((vector<int> &)vfloat_typeoffsets),
860 fbb.CreateVector(speclogvars),
861 fbb.CreateVector(enumoffsets),
862 fbb.CreateVector(vtables));
863 bytecode::FinishBytecodeFileBuffer(fbb, bcf);
864 bytecode.assign(fbb.GetBufferPointer(), fbb.GetBufferPointer() + fbb.GetSize());
865 }
866 };
867
868 inline string TypeName(TypeRef type, int flen = 0, const SymbolTable *st = nullptr) {
869 switch (type->t) {
870 case V_STRUCT_R:
871 case V_STRUCT_S:
872 case V_CLASS:
873 return type->udt->name;
874 case V_VECTOR:
875 return flen && type->Element()->Numeric()
876 ? (flen < 0
877 ? (type->Element()->t == V_INT ? "vec_i" : "vec_f") // FIXME: better names?
878 : TypeName(st->VectorType(type, 0, flen)))
879 : (type->Element()->t == V_VAR
880 ? "[]"
881 : "[" + TypeName(type->Element(), flen, st) + "]");
882 case V_FUNCTION:
883 return type->sf // || type->sf->anonymous
884 ? type->sf->parent->name
885 : "function";
886 case V_NIL:
887 return type->Element()->t == V_VAR
888 ? "nil"
889 : TypeName(type->Element(), flen, st) + "?";
890 case V_COROUTINE:
891 return type->sf
892 ? "coroutine(" + type->sf->parent->name + ")"
893 : "coroutine";
894 case V_TUPLE: {
895 string s = "(";
896 for (auto [i, te] : enumerate(*type->tup)) {
897 if (i) s += ", ";
898 s += TypeName(te.type);
899 }
900 s += ")";
901 return s;
902 }
903 case V_INT:
904 return type->e ? type->e->name : "int";
905 default:
906 return string(BaseTypeName(type->t));
907 }
908 }
909
910 } // namespace lobster
911
912 #endif // LOBSTER_IDENTS
913