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