10df231171d1da6ae38e19071f415ad2668a2ca5
[platform/upstream/flatbuffers.git] / src / idl_gen_lua.cpp
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17  // independent from idl_parser, since this code is not needed for most clients
18
19 #include <string>
20
21 #include "flatbuffers/code_generators.h"
22 #include "flatbuffers/flatbuffers.h"
23 #include "flatbuffers/idl.h"
24 #include "flatbuffers/util.h"
25
26 #include <unordered_set>
27
28 namespace flatbuffers {
29 namespace lua {
30
31   // Hardcode spaces per indentation.
32   const CommentConfig def_comment = { nullptr, "--", nullptr };
33   const char * Indent = "    ";
34   const char * Comment = "-- ";
35   const char * End = "end\n";
36   const char * EndFunc = "end\n";
37   const char * SelfData = "self.view";
38   const char * SelfDataPos = "self.view.pos";
39   const char * SelfDataBytes = "self.view.bytes";
40
41   class LuaGenerator : public BaseGenerator {
42   public:
43     LuaGenerator(const Parser &parser, const std::string &path,
44       const std::string &file_name)
45       : BaseGenerator(parser, path, file_name, "" /* not used */,
46         "" /* not used */) {
47       static const char * const keywords[] = {
48         "and",
49         "break",
50         "do",
51         "else",
52         "elseif",
53         "end",
54         "false",
55         "for",
56         "function",
57         "goto",
58         "if",
59         "in",
60         "local",
61         "nil",
62         "not",
63         "or",
64         "repeat",
65         "return",
66         "then",
67         "true",
68         "until",
69         "while"
70       };
71       keywords_.insert(std::begin(keywords), std::end(keywords));
72     }
73
74     // Most field accessors need to retrieve and test the field offset first,
75     // this is the prefix code for that.
76     std::string OffsetPrefix(const FieldDef &field) {
77       return std::string(Indent) +
78         "local o = " + SelfData + ":Offset(" + NumToString(field.value.offset) + ")\n" +
79         Indent + "if o ~= 0 then\n";
80     }
81
82     // Begin a class declaration.
83     void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
84       std::string &code = *code_ptr;
85       code += "local " + NormalizedName(struct_def) + " = {} -- the module\n";
86       code += "local " + NormalizedMetaName(struct_def) + " = {} -- the class metatable\n";
87       code += "\n";
88     }
89
90     // Begin enum code with a class declaration.
91     void BeginEnum(const std::string &class_name, std::string *code_ptr) {
92       std::string &code = *code_ptr;
93       code += "local " + class_name + " = {\n";
94     }
95
96     std::string EscapeKeyword(const std::string &name) const {
97       return keywords_.find(name) == keywords_.end() ? name : "_" + name;
98     }
99
100     std::string NormalizedName(const Definition &definition) const {
101       return EscapeKeyword(definition.name);
102     }
103
104     std::string NormalizedName(const EnumVal &ev) const {
105       return EscapeKeyword(ev.name);
106     }
107
108     std::string NormalizedMetaName(const Definition &definition) const {
109       return EscapeKeyword(definition.name) + "_mt";
110     }
111
112     // A single enum member.
113     void EnumMember(const EnumDef &enum_def, const EnumVal &ev, std::string *code_ptr) {
114       std::string &code = *code_ptr;
115       code += std::string(Indent) + NormalizedName(ev) + " = " +
116               enum_def.ToString(ev) + ",\n";
117     }
118
119     // End enum code.
120     void EndEnum(std::string *code_ptr) {
121       std::string &code = *code_ptr;
122       code += "}\n";
123     }
124
125     void GenerateNewObjectPrototype(const StructDef &struct_def,
126       std::string *code_ptr) {
127       std::string &code = *code_ptr;
128
129       code += "function " + NormalizedName(struct_def) + ".New()\n";
130       code += std::string(Indent) + "local o = {}\n";
131       code += std::string(Indent) + "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) + "})\n";
132       code += std::string(Indent) + "return o\n";
133       code += EndFunc;
134     }
135
136     // Initialize a new struct or table from existing data.
137     void NewRootTypeFromBuffer(const StructDef &struct_def,
138       std::string *code_ptr) {
139       std::string &code = *code_ptr;
140
141       code += "function " + NormalizedName(struct_def) + ".GetRootAs" + NormalizedName(struct_def) + "(buf, offset)\n";
142       code += std::string(Indent) + "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
143       code += std::string(Indent) + "local o = " + NormalizedName(struct_def) + ".New()\n";
144       code += std::string(Indent) + "o:Init(buf, n + offset)\n";
145       code += std::string(Indent) + "return o\n";
146       code += EndFunc;
147     }
148
149     // Initialize an existing object with other data, to avoid an allocation.
150     void InitializeExisting(const StructDef &struct_def,
151       std::string *code_ptr) {
152       std::string &code = *code_ptr;
153
154       GenReceiver(struct_def, code_ptr);
155       code += "Init(buf, pos)\n";
156       code += std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n";
157       code += EndFunc;
158     }
159
160     // Get the length of a vector.
161     void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
162       std::string *code_ptr) {
163       std::string &code = *code_ptr;
164
165       GenReceiver(struct_def, code_ptr);
166       code += MakeCamel(NormalizedName(field)) + "Length()\n";
167       code += OffsetPrefix(field);
168       code += std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
169       code += std::string(Indent) + End;
170       code += std::string(Indent) + "return 0\n";
171       code += EndFunc;
172     }
173
174     // Get the value of a struct's scalar.
175     void GetScalarFieldOfStruct(const StructDef &struct_def,
176       const FieldDef &field,
177       std::string *code_ptr) {
178       std::string &code = *code_ptr;
179       std::string getter = GenGetter(field.value.type);
180       GenReceiver(struct_def, code_ptr);
181       code += MakeCamel(NormalizedName(field));
182       code += "()\n";
183       code += std::string(Indent) + "return " + getter;
184       code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) + ")\n";
185       code += EndFunc;
186     }
187
188     // Get the value of a table's scalar.
189     void GetScalarFieldOfTable(const StructDef &struct_def,
190       const FieldDef &field,
191       std::string *code_ptr) {
192       std::string &code = *code_ptr;
193       std::string getter = GenGetter(field.value.type);
194       GenReceiver(struct_def, code_ptr);
195       code += MakeCamel(NormalizedName(field));
196       code += "()\n";
197       code += OffsetPrefix(field);
198       getter += std::string("o + ") + SelfDataPos + ")";
199       auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
200       if (is_bool) {
201         getter = "(" + getter + " ~= 0)";
202       }
203       code += std::string(Indent) + Indent + "return " + getter + "\n";
204       code += std::string(Indent) + End;
205       std::string default_value;
206       if (is_bool) {
207         default_value = field.value.constant == "0" ? "false" : "true";
208       }
209       else {
210         default_value = field.value.constant;
211       }
212       code += std::string(Indent) + "return " + default_value + "\n";
213       code += EndFunc;
214     }
215
216     // Get a struct by initializing an existing struct.
217     // Specific to Struct.
218     void GetStructFieldOfStruct(const StructDef &struct_def,
219       const FieldDef &field,
220       std::string *code_ptr) {
221       std::string &code = *code_ptr;
222       GenReceiver(struct_def, code_ptr);
223       code += MakeCamel(NormalizedName(field));
224       code += "(obj)\n";
225       code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " + SelfDataPos + " + ";
226       code += NumToString(field.value.offset) + ")\n";
227       code += std::string(Indent) + "return obj\n";
228       code += EndFunc;
229     }
230
231     // Get a struct by initializing an existing struct.
232     // Specific to Table.
233     void GetStructFieldOfTable(const StructDef &struct_def,
234       const FieldDef &field,
235       std::string *code_ptr) {
236       std::string &code = *code_ptr;
237       GenReceiver(struct_def, code_ptr);
238       code += MakeCamel(NormalizedName(field));
239       code += "()\n";
240       code += OffsetPrefix(field);
241       if (field.value.type.struct_def->fixed) {
242         code += std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n";
243       }
244       else {
245         code += std::string(Indent) + Indent + "local x = " + SelfData + ":Indirect(o + " + SelfDataPos + ")\n";
246       }
247       code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n";
248       code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
249       code += std::string(Indent) + Indent + "return obj\n";
250       code += std::string(Indent) + End;
251       code += EndFunc;
252     }
253
254     // Get the value of a string.
255     void GetStringField(const StructDef &struct_def, const FieldDef &field,
256       std::string *code_ptr) {
257       std::string &code = *code_ptr;
258       GenReceiver(struct_def, code_ptr);
259       code += MakeCamel(NormalizedName(field));
260       code += "()\n";
261       code += OffsetPrefix(field);
262       code += std::string(Indent) + Indent + "return " + GenGetter(field.value.type);
263       code += std::string("o + ") + SelfDataPos + ")\n";
264       code += std::string(Indent) + End;
265       code += EndFunc;
266     }
267
268     // Get the value of a union from an object.
269     void GetUnionField(const StructDef &struct_def, const FieldDef &field,
270       std::string *code_ptr) {
271       std::string &code = *code_ptr;
272       GenReceiver(struct_def, code_ptr);
273       code += MakeCamel(NormalizedName(field)) + "()\n";
274       code += OffsetPrefix(field);
275
276       // TODO(rw): this works and is not the good way to it:
277       //bool is_native_table = TypeName(field) == "*flatbuffers.Table";
278       //if (is_native_table) {
279       //  code += std::string(Indent) + Indent + "from flatbuffers.table import Table\n";
280       //} else {
281       //  code += std::string(Indent) + Indent +
282       //  code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n";
283       //}
284       code += std::string(Indent) + Indent + "local obj = flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n";
285       code += std::string(Indent) + Indent + GenGetter(field.value.type) + "obj, o)\n";
286       code += std::string(Indent) + Indent + "return obj\n";
287       code += std::string(Indent) + End;
288       code += EndFunc;
289     }
290
291     // Get the value of a vector's struct member.
292     void GetMemberOfVectorOfStruct(const StructDef &struct_def,
293       const FieldDef &field,
294       std::string *code_ptr) {
295       std::string &code = *code_ptr;
296       auto vectortype = field.value.type.VectorType();
297
298       GenReceiver(struct_def, code_ptr);
299       code += MakeCamel(NormalizedName(field));
300       code += "(j)\n";
301       code += OffsetPrefix(field);
302       code += std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n";
303       code += std::string(Indent) + Indent + "x = x + ((j-1) * ";
304       code += NumToString(InlineSize(vectortype)) + ")\n";
305       if (!(vectortype.struct_def->fixed)) {
306         code += std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n";
307       }
308       code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n";
309       code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
310       code += std::string(Indent) + Indent + "return obj\n";
311       code += std::string(Indent) + End;
312       code += EndFunc;
313     }
314
315     // Get the value of a vector's non-struct member. Uses a named return
316     // argument to conveniently set the zero value for the result.
317     void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
318       const FieldDef &field,
319       std::string *code_ptr) {
320       std::string &code = *code_ptr;
321       auto vectortype = field.value.type.VectorType();
322
323       GenReceiver(struct_def, code_ptr);
324       code += MakeCamel(NormalizedName(field));
325       code += "(j)\n";
326       code += OffsetPrefix(field);
327       code += std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n";
328       code += std::string(Indent) + Indent;
329       code += "return " + GenGetter(field.value.type);
330       code += "a + ((j-1) * ";
331       code += NumToString(InlineSize(vectortype)) + "))\n";
332       code += std::string(Indent) + End;
333       if (vectortype.base_type == BASE_TYPE_STRING) {
334         code += std::string(Indent) + "return ''\n";
335       }
336       else {
337         code += std::string(Indent) + "return 0\n";
338       }
339       code += EndFunc;
340     }
341
342     // Begin the creator function signature.
343     void BeginBuilderArgs(const StructDef &struct_def,
344       std::string *code_ptr) {
345       std::string &code = *code_ptr;
346
347       code += "function " + NormalizedName(struct_def) + ".Create" + NormalizedName(struct_def);
348       code += "(builder";
349     }
350
351     // Recursively generate arguments for a constructor, to deal with nested
352     // structs.
353     void StructBuilderArgs(const StructDef &struct_def,
354       const char *nameprefix, std::string *code_ptr) {
355       for (auto it = struct_def.fields.vec.begin();
356         it != struct_def.fields.vec.end(); ++it) {
357         auto &field = **it;
358         if (IsStruct(field.value.type)) {
359           // Generate arguments for a struct inside a struct. To ensure names
360           // don't clash, and to make it obvious these arguments are constructing
361           // a nested struct, prefix the name with the field name.
362           StructBuilderArgs(*field.value.type.struct_def,
363             (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
364         }
365         else {
366           std::string &code = *code_ptr;
367           code += std::string(", ") + nameprefix;
368           code += MakeCamel(NormalizedName(field), false);
369         }
370       }
371     }
372
373     // End the creator function signature.
374     void EndBuilderArgs(std::string *code_ptr) {
375       std::string &code = *code_ptr;
376       code += ")\n";
377     }
378
379     // Recursively generate struct construction statements and instert manual
380     // padding.
381     void StructBuilderBody(const StructDef &struct_def,
382       const char *nameprefix, std::string *code_ptr) {
383       std::string &code = *code_ptr;
384       code += std::string(Indent) + "builder:Prep(" + NumToString(struct_def.minalign) + ", ";
385       code += NumToString(struct_def.bytesize) + ")\n";
386       for (auto it = struct_def.fields.vec.rbegin();
387         it != struct_def.fields.vec.rend(); ++it) {
388         auto &field = **it;
389         if (field.padding)
390           code += std::string(Indent) + "builder:Pad(" + NumToString(field.padding) + ")\n";
391         if (IsStruct(field.value.type)) {
392           StructBuilderBody(*field.value.type.struct_def,
393             (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
394         }
395         else {
396           code += std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
397           code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
398         }
399       }
400     }
401
402     void EndBuilderBody(std::string *code_ptr) {
403       std::string &code = *code_ptr;
404       code += std::string(Indent) + "return builder:Offset()\n";
405       code += EndFunc;
406     }
407
408     // Get the value of a table's starting offset.
409     void GetStartOfTable(const StructDef &struct_def,
410       std::string *code_ptr) {
411       std::string &code = *code_ptr;
412       code += "function " + NormalizedName(struct_def) + ".Start";
413       code += "(builder) ";
414       code += "builder:StartObject(";
415       code += NumToString(struct_def.fields.vec.size());
416       code += ") end\n";
417     }
418
419     // Set the value of a table's field.
420     void BuildFieldOfTable(const StructDef &struct_def,
421       const FieldDef &field, const size_t offset,
422       std::string *code_ptr) {
423       std::string &code = *code_ptr;
424       code += "function " + NormalizedName(struct_def) + ".Add" + MakeCamel(NormalizedName(field));
425       code += "(builder, ";
426       code += MakeCamel(NormalizedName(field), false);
427       code += ") ";
428       code += "builder:Prepend";
429       code += GenMethod(field) + "Slot(";
430       code += NumToString(offset) + ", ";
431       // todo: i don't need to cast in Lua, but am I missing something?
432     //    if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
433     //      code += "flatbuffers.N.UOffsetTFlags.py_type";
434     //      code += "(";
435     //      code += MakeCamel(NormalizedName(field), false) + ")";
436     //    } else {
437       code += MakeCamel(NormalizedName(field), false);
438       //    }
439       code += ", " + field.value.constant;
440       code += ") end\n";
441     }
442
443     // Set the value of one of the members of a table's vector.
444     void BuildVectorOfTable(const StructDef &struct_def,
445       const FieldDef &field, std::string *code_ptr) {
446       std::string &code = *code_ptr;
447       code += "function " + NormalizedName(struct_def) + ".Start";
448       code += MakeCamel(NormalizedName(field));
449       code += "Vector(builder, numElems) return builder:StartVector(";
450       auto vector_type = field.value.type.VectorType();
451       auto alignment = InlineAlignment(vector_type);
452       auto elem_size = InlineSize(vector_type);
453       code += NumToString(elem_size);
454       code += ", numElems, " + NumToString(alignment);
455       code += ") end\n";
456     }
457
458     // Get the offset of the end of a table.
459     void GetEndOffsetOnTable(const StructDef &struct_def,
460       std::string *code_ptr) {
461       std::string &code = *code_ptr;
462       code += "function " + NormalizedName(struct_def) + ".End";
463       code += "(builder) ";
464       code += "return builder:EndObject() end\n";
465     }
466
467     // Generate the receiver for function signatures.
468     void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
469       std::string &code = *code_ptr;
470       code += "function " + NormalizedMetaName(struct_def) + ":";
471     }
472
473     // Generate a struct field, conditioned on its child type(s).
474     void GenStructAccessor(const StructDef &struct_def,
475       const FieldDef &field, std::string *code_ptr) {
476       GenComment(field.doc_comment, code_ptr, &def_comment);
477       if (IsScalar(field.value.type.base_type)) {
478         if (struct_def.fixed) {
479           GetScalarFieldOfStruct(struct_def, field, code_ptr);
480         }
481         else {
482           GetScalarFieldOfTable(struct_def, field, code_ptr);
483         }
484       }
485       else {
486         switch (field.value.type.base_type) {
487         case BASE_TYPE_STRUCT:
488           if (struct_def.fixed) {
489             GetStructFieldOfStruct(struct_def, field, code_ptr);
490           }
491           else {
492             GetStructFieldOfTable(struct_def, field, code_ptr);
493           }
494           break;
495         case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break;
496         case BASE_TYPE_VECTOR: {
497           auto vectortype = field.value.type.VectorType();
498           if (vectortype.base_type == BASE_TYPE_STRUCT) {
499             GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
500           }
501           else {
502             GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
503           }
504           break;
505         }
506         case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
507         default: FLATBUFFERS_ASSERT(0);
508         }
509       }
510       if (field.value.type.base_type == BASE_TYPE_VECTOR) {
511         GetVectorLen(struct_def, field, code_ptr);
512       }
513     }
514
515     // Generate table constructors, conditioned on its members' types.
516     void GenTableBuilders(const StructDef &struct_def,
517       std::string *code_ptr) {
518       GetStartOfTable(struct_def, code_ptr);
519
520       for (auto it = struct_def.fields.vec.begin();
521         it != struct_def.fields.vec.end(); ++it) {
522         auto &field = **it;
523         if (field.deprecated) continue;
524
525         auto offset = it - struct_def.fields.vec.begin();
526         BuildFieldOfTable(struct_def, field, offset, code_ptr);
527         if (field.value.type.base_type == BASE_TYPE_VECTOR) {
528           BuildVectorOfTable(struct_def, field, code_ptr);
529         }
530       }
531
532       GetEndOffsetOnTable(struct_def, code_ptr);
533     }
534
535     // Generate struct or table methods.
536     void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
537       if (struct_def.generated) return;
538
539       GenComment(struct_def.doc_comment, code_ptr, &def_comment);
540       BeginClass(struct_def, code_ptr);
541
542       GenerateNewObjectPrototype(struct_def, code_ptr);
543
544       if (!struct_def.fixed) {
545         // Generate a special accessor for the table that has been declared as
546         // the root type.
547         NewRootTypeFromBuffer(struct_def, code_ptr);
548       }
549
550       // Generate the Init method that sets the field in a pre-existing
551       // accessor object. This is to allow object reuse.
552       InitializeExisting(struct_def, code_ptr);
553       for (auto it = struct_def.fields.vec.begin();
554         it != struct_def.fields.vec.end(); ++it) {
555         auto &field = **it;
556         if (field.deprecated) continue;
557
558         GenStructAccessor(struct_def, field, code_ptr);
559       }
560
561       if (struct_def.fixed) {
562         // create a struct constructor function
563         GenStructBuilder(struct_def, code_ptr);
564       }
565       else {
566         // Create a set of functions that allow table construction.
567         GenTableBuilders(struct_def, code_ptr);
568       }
569     }
570
571     // Generate enum declarations.
572     void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
573       if (enum_def.generated) return;
574
575       GenComment(enum_def.doc_comment, code_ptr, &def_comment);
576       BeginEnum(NormalizedName(enum_def), code_ptr);
577       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
578            ++it) {
579         auto &ev = **it;
580         GenComment(ev.doc_comment, code_ptr, &def_comment, Indent);
581         EnumMember(enum_def, ev, code_ptr);
582       }
583       EndEnum(code_ptr);
584     }
585
586     // Returns the function name that is able to read a value of the given type.
587     std::string GenGetter(const Type &type) {
588       switch (type.base_type) {
589       case BASE_TYPE_STRING: return std::string(SelfData) + ":String(";
590       case BASE_TYPE_UNION: return  std::string(SelfData) + ":Union(";
591       case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
592       default:
593         return std::string(SelfData) + ":Get(flatbuffers.N." +
594           MakeCamel(GenTypeGet(type)) + ", ";
595       }
596     }
597
598     // Returns the method name for use with add/put calls.
599     std::string GenMethod(const FieldDef &field) {
600       return IsScalar(field.value.type.base_type)
601         ? MakeCamel(GenTypeBasic(field.value.type))
602         : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
603     }
604
605     std::string GenTypeBasic(const Type &type) {
606       static const char *ctypename[] = {
607         // clang-format off
608           #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
609             CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
610             #PTYPE,
611             FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
612           #undef FLATBUFFERS_TD
613             // clang-format on
614       };
615       return ctypename[type.base_type];
616     }
617
618     std::string GenTypePointer(const Type &type) {
619       switch (type.base_type) {
620       case BASE_TYPE_STRING: return "string";
621       case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
622       case BASE_TYPE_STRUCT: return type.struct_def->name;
623       case BASE_TYPE_UNION:
624         // fall through
625       default: return "*flatbuffers.Table";
626       }
627     }
628
629     std::string GenTypeGet(const Type &type) {
630       return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
631     }
632
633     std::string GetNamespace(const Type &type) {
634       return type.struct_def->defined_namespace->GetFullyQualifiedName(type.struct_def->name);
635     }
636
637     std::string TypeName(const FieldDef &field) {
638       return GenTypeGet(field.value.type);
639     }
640
641     std::string TypeNameWithNamespace(const FieldDef &field) {
642       return GetNamespace(field.value.type);
643     }
644
645     // Create a struct with a builder and the struct's arguments.
646     void GenStructBuilder(const StructDef &struct_def,
647       std::string *code_ptr) {
648       BeginBuilderArgs(struct_def, code_ptr);
649       StructBuilderArgs(struct_def, "", code_ptr);
650       EndBuilderArgs(code_ptr);
651
652       StructBuilderBody(struct_def, "", code_ptr);
653       EndBuilderBody(code_ptr);
654     }
655
656     bool generate() {
657       if (!generateEnums()) return false;
658       if (!generateStructs()) return false;
659       return true;
660     }
661
662   private:
663     bool generateEnums() {
664       for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
665         ++it) {
666         auto &enum_def = **it;
667         std::string enumcode;
668         GenEnum(enum_def, &enumcode);
669         if (!SaveType(enum_def, enumcode, false)) return false;
670       }
671       return true;
672     }
673
674     bool generateStructs() {
675       for (auto it = parser_.structs_.vec.begin();
676         it != parser_.structs_.vec.end(); ++it) {
677         auto &struct_def = **it;
678         std::string declcode;
679         GenStruct(struct_def, &declcode);
680         if (!SaveType(struct_def, declcode, true)) return false;
681       }
682       return true;
683     }
684
685     // Begin by declaring namespace and imports.
686     void BeginFile(const std::string &name_space_name, const bool needs_imports,
687       std::string *code_ptr) {
688       std::string &code = *code_ptr;
689       code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n";
690       code += std::string(Comment) + "namespace: " + name_space_name + "\n\n";
691       if (needs_imports) {
692         code += "local flatbuffers = require('flatbuffers')\n\n";
693       }
694     }
695
696     // Save out the generated code for a Lua Table type.
697     bool SaveType(const Definition &def, const std::string &classcode,
698       bool needs_imports) {
699       if (!classcode.length()) return true;
700
701       std::string namespace_dir = path_;
702       auto &namespaces = def.defined_namespace->components;
703       for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
704         if (it != namespaces.begin()) namespace_dir += kPathSeparator;
705         namespace_dir += *it;
706         //std::string init_py_filename = namespace_dir + "/__init__.py";
707         //SaveFile(init_py_filename.c_str(), "", false);
708       }
709
710       std::string code = "";
711       BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
712       code += classcode;
713       code += "\n";
714       code += "return " + NormalizedName(def) + " " + Comment + "return the module";
715       std::string filename =
716         NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua";
717       return SaveFile(filename.c_str(), code, false);
718     }
719   private:
720     std::unordered_set<std::string> keywords_;
721   };
722
723 }  // namespace lua
724
725 bool GenerateLua(const Parser &parser, const std::string &path,
726   const std::string &file_name) {
727   lua::LuaGenerator generator(parser, path, file_name);
728   return generator.generate();
729 }
730
731 }  // namespace flatbuffers