Squashed 'third_party/flatbuffers/' content from commit acc9990ab

Change-Id: I48550d40d78fea996ebe74e9723a5d1f910de491
git-subtree-dir: third_party/flatbuffers
git-subtree-split: acc9990abd2206491480291b0f85f925110102ea
diff --git a/src/idl_gen_lua.cpp b/src/idl_gen_lua.cpp
new file mode 100644
index 0000000..10df231
--- /dev/null
+++ b/src/idl_gen_lua.cpp
@@ -0,0 +1,731 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ // independent from idl_parser, since this code is not needed for most clients
+
+#include <string>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+#include <unordered_set>
+
+namespace flatbuffers {
+namespace lua {
+
+  // Hardcode spaces per indentation.
+  const CommentConfig def_comment = { nullptr, "--", nullptr };
+  const char * Indent = "    ";
+  const char * Comment = "-- ";
+  const char * End = "end\n";
+  const char * EndFunc = "end\n";
+  const char * SelfData = "self.view";
+  const char * SelfDataPos = "self.view.pos";
+  const char * SelfDataBytes = "self.view.bytes";
+
+  class LuaGenerator : public BaseGenerator {
+  public:
+    LuaGenerator(const Parser &parser, const std::string &path,
+      const std::string &file_name)
+      : BaseGenerator(parser, path, file_name, "" /* not used */,
+        "" /* not used */) {
+      static const char * const keywords[] = {
+        "and",
+        "break",
+        "do",
+        "else",
+        "elseif",
+        "end",
+        "false",
+        "for",
+        "function",
+        "goto",
+        "if",
+        "in",
+        "local",
+        "nil",
+        "not",
+        "or",
+        "repeat",
+        "return",
+        "then",
+        "true",
+        "until",
+        "while"
+      };
+      keywords_.insert(std::begin(keywords), std::end(keywords));
+    }
+
+    // Most field accessors need to retrieve and test the field offset first,
+    // this is the prefix code for that.
+    std::string OffsetPrefix(const FieldDef &field) {
+      return std::string(Indent) +
+        "local o = " + SelfData + ":Offset(" + NumToString(field.value.offset) + ")\n" +
+        Indent + "if o ~= 0 then\n";
+    }
+
+    // Begin a class declaration.
+    void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "local " + NormalizedName(struct_def) + " = {} -- the module\n";
+      code += "local " + NormalizedMetaName(struct_def) + " = {} -- the class metatable\n";
+      code += "\n";
+    }
+
+    // Begin enum code with a class declaration.
+    void BeginEnum(const std::string &class_name, std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "local " + class_name + " = {\n";
+    }
+
+    std::string EscapeKeyword(const std::string &name) const {
+      return keywords_.find(name) == keywords_.end() ? name : "_" + name;
+    }
+
+    std::string NormalizedName(const Definition &definition) const {
+      return EscapeKeyword(definition.name);
+    }
+
+    std::string NormalizedName(const EnumVal &ev) const {
+      return EscapeKeyword(ev.name);
+    }
+
+    std::string NormalizedMetaName(const Definition &definition) const {
+      return EscapeKeyword(definition.name) + "_mt";
+    }
+
+    // A single enum member.
+    void EnumMember(const EnumDef &enum_def, const EnumVal &ev, std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += std::string(Indent) + NormalizedName(ev) + " = " +
+              enum_def.ToString(ev) + ",\n";
+    }
+
+    // End enum code.
+    void EndEnum(std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "}\n";
+    }
+
+    void GenerateNewObjectPrototype(const StructDef &struct_def,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+
+      code += "function " + NormalizedName(struct_def) + ".New()\n";
+      code += std::string(Indent) + "local o = {}\n";
+      code += std::string(Indent) + "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) + "})\n";
+      code += std::string(Indent) + "return o\n";
+      code += EndFunc;
+    }
+
+    // Initialize a new struct or table from existing data.
+    void NewRootTypeFromBuffer(const StructDef &struct_def,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+
+      code += "function " + NormalizedName(struct_def) + ".GetRootAs" + NormalizedName(struct_def) + "(buf, offset)\n";
+      code += std::string(Indent) + "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
+      code += std::string(Indent) + "local o = " + NormalizedName(struct_def) + ".New()\n";
+      code += std::string(Indent) + "o:Init(buf, n + offset)\n";
+      code += std::string(Indent) + "return o\n";
+      code += EndFunc;
+    }
+
+    // Initialize an existing object with other data, to avoid an allocation.
+    void InitializeExisting(const StructDef &struct_def,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+
+      GenReceiver(struct_def, code_ptr);
+      code += "Init(buf, pos)\n";
+      code += std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n";
+      code += EndFunc;
+    }
+
+    // Get the length of a vector.
+    void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field)) + "Length()\n";
+      code += OffsetPrefix(field);
+      code += std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
+      code += std::string(Indent) + End;
+      code += std::string(Indent) + "return 0\n";
+      code += EndFunc;
+    }
+
+    // Get the value of a struct's scalar.
+    void GetScalarFieldOfStruct(const StructDef &struct_def,
+      const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      std::string getter = GenGetter(field.value.type);
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "()\n";
+      code += std::string(Indent) + "return " + getter;
+      code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) + ")\n";
+      code += EndFunc;
+    }
+
+    // Get the value of a table's scalar.
+    void GetScalarFieldOfTable(const StructDef &struct_def,
+      const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      std::string getter = GenGetter(field.value.type);
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "()\n";
+      code += OffsetPrefix(field);
+      getter += std::string("o + ") + SelfDataPos + ")";
+      auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
+      if (is_bool) {
+        getter = "(" + getter + " ~= 0)";
+      }
+      code += std::string(Indent) + Indent + "return " + getter + "\n";
+      code += std::string(Indent) + End;
+      std::string default_value;
+      if (is_bool) {
+        default_value = field.value.constant == "0" ? "false" : "true";
+      }
+      else {
+        default_value = field.value.constant;
+      }
+      code += std::string(Indent) + "return " + default_value + "\n";
+      code += EndFunc;
+    }
+
+    // Get a struct by initializing an existing struct.
+    // Specific to Struct.
+    void GetStructFieldOfStruct(const StructDef &struct_def,
+      const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "(obj)\n";
+      code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " + SelfDataPos + " + ";
+      code += NumToString(field.value.offset) + ")\n";
+      code += std::string(Indent) + "return obj\n";
+      code += EndFunc;
+    }
+
+    // Get a struct by initializing an existing struct.
+    // Specific to Table.
+    void GetStructFieldOfTable(const StructDef &struct_def,
+      const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "()\n";
+      code += OffsetPrefix(field);
+      if (field.value.type.struct_def->fixed) {
+        code += std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n";
+      }
+      else {
+        code += std::string(Indent) + Indent + "local x = " + SelfData + ":Indirect(o + " + SelfDataPos + ")\n";
+      }
+      code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n";
+      code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
+      code += std::string(Indent) + Indent + "return obj\n";
+      code += std::string(Indent) + End;
+      code += EndFunc;
+    }
+
+    // Get the value of a string.
+    void GetStringField(const StructDef &struct_def, const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "()\n";
+      code += OffsetPrefix(field);
+      code += std::string(Indent) + Indent + "return " + GenGetter(field.value.type);
+      code += std::string("o + ") + SelfDataPos + ")\n";
+      code += std::string(Indent) + End;
+      code += EndFunc;
+    }
+
+    // Get the value of a union from an object.
+    void GetUnionField(const StructDef &struct_def, const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field)) + "()\n";
+      code += OffsetPrefix(field);
+
+      // TODO(rw): this works and is not the good way to it:
+      //bool is_native_table = TypeName(field) == "*flatbuffers.Table";
+      //if (is_native_table) {
+      //  code += std::string(Indent) + Indent + "from flatbuffers.table import Table\n";
+      //} else {
+      //  code += std::string(Indent) + Indent +
+      //  code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n";
+      //}
+      code += std::string(Indent) + Indent + "local obj = flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n";
+      code += std::string(Indent) + Indent + GenGetter(field.value.type) + "obj, o)\n";
+      code += std::string(Indent) + Indent + "return obj\n";
+      code += std::string(Indent) + End;
+      code += EndFunc;
+    }
+
+    // Get the value of a vector's struct member.
+    void GetMemberOfVectorOfStruct(const StructDef &struct_def,
+      const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      auto vectortype = field.value.type.VectorType();
+
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "(j)\n";
+      code += OffsetPrefix(field);
+      code += std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n";
+      code += std::string(Indent) + Indent + "x = x + ((j-1) * ";
+      code += NumToString(InlineSize(vectortype)) + ")\n";
+      if (!(vectortype.struct_def->fixed)) {
+        code += std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n";
+      }
+      code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n";
+      code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
+      code += std::string(Indent) + Indent + "return obj\n";
+      code += std::string(Indent) + End;
+      code += EndFunc;
+    }
+
+    // Get the value of a vector's non-struct member. Uses a named return
+    // argument to conveniently set the zero value for the result.
+    void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
+      const FieldDef &field,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      auto vectortype = field.value.type.VectorType();
+
+      GenReceiver(struct_def, code_ptr);
+      code += MakeCamel(NormalizedName(field));
+      code += "(j)\n";
+      code += OffsetPrefix(field);
+      code += std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n";
+      code += std::string(Indent) + Indent;
+      code += "return " + GenGetter(field.value.type);
+      code += "a + ((j-1) * ";
+      code += NumToString(InlineSize(vectortype)) + "))\n";
+      code += std::string(Indent) + End;
+      if (vectortype.base_type == BASE_TYPE_STRING) {
+        code += std::string(Indent) + "return ''\n";
+      }
+      else {
+        code += std::string(Indent) + "return 0\n";
+      }
+      code += EndFunc;
+    }
+
+    // Begin the creator function signature.
+    void BeginBuilderArgs(const StructDef &struct_def,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+
+      code += "function " + NormalizedName(struct_def) + ".Create" + NormalizedName(struct_def);
+      code += "(builder";
+    }
+
+    // Recursively generate arguments for a constructor, to deal with nested
+    // structs.
+    void StructBuilderArgs(const StructDef &struct_def,
+      const char *nameprefix, std::string *code_ptr) {
+      for (auto it = struct_def.fields.vec.begin();
+        it != struct_def.fields.vec.end(); ++it) {
+        auto &field = **it;
+        if (IsStruct(field.value.type)) {
+          // Generate arguments for a struct inside a struct. To ensure names
+          // don't clash, and to make it obvious these arguments are constructing
+          // a nested struct, prefix the name with the field name.
+          StructBuilderArgs(*field.value.type.struct_def,
+            (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
+        }
+        else {
+          std::string &code = *code_ptr;
+          code += std::string(", ") + nameprefix;
+          code += MakeCamel(NormalizedName(field), false);
+        }
+      }
+    }
+
+    // End the creator function signature.
+    void EndBuilderArgs(std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += ")\n";
+    }
+
+    // Recursively generate struct construction statements and instert manual
+    // padding.
+    void StructBuilderBody(const StructDef &struct_def,
+      const char *nameprefix, std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += std::string(Indent) + "builder:Prep(" + NumToString(struct_def.minalign) + ", ";
+      code += NumToString(struct_def.bytesize) + ")\n";
+      for (auto it = struct_def.fields.vec.rbegin();
+        it != struct_def.fields.vec.rend(); ++it) {
+        auto &field = **it;
+        if (field.padding)
+          code += std::string(Indent) + "builder:Pad(" + NumToString(field.padding) + ")\n";
+        if (IsStruct(field.value.type)) {
+          StructBuilderBody(*field.value.type.struct_def,
+            (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
+        }
+        else {
+          code += std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
+          code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
+        }
+      }
+    }
+
+    void EndBuilderBody(std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += std::string(Indent) + "return builder:Offset()\n";
+      code += EndFunc;
+    }
+
+    // Get the value of a table's starting offset.
+    void GetStartOfTable(const StructDef &struct_def,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "function " + NormalizedName(struct_def) + ".Start";
+      code += "(builder) ";
+      code += "builder:StartObject(";
+      code += NumToString(struct_def.fields.vec.size());
+      code += ") end\n";
+    }
+
+    // Set the value of a table's field.
+    void BuildFieldOfTable(const StructDef &struct_def,
+      const FieldDef &field, const size_t offset,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "function " + NormalizedName(struct_def) + ".Add" + MakeCamel(NormalizedName(field));
+      code += "(builder, ";
+      code += MakeCamel(NormalizedName(field), false);
+      code += ") ";
+      code += "builder:Prepend";
+      code += GenMethod(field) + "Slot(";
+      code += NumToString(offset) + ", ";
+      // todo: i don't need to cast in Lua, but am I missing something?
+    //    if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
+    //      code += "flatbuffers.N.UOffsetTFlags.py_type";
+    //      code += "(";
+    //      code += MakeCamel(NormalizedName(field), false) + ")";
+    //    } else {
+      code += MakeCamel(NormalizedName(field), false);
+      //    }
+      code += ", " + field.value.constant;
+      code += ") end\n";
+    }
+
+    // Set the value of one of the members of a table's vector.
+    void BuildVectorOfTable(const StructDef &struct_def,
+      const FieldDef &field, std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "function " + NormalizedName(struct_def) + ".Start";
+      code += MakeCamel(NormalizedName(field));
+      code += "Vector(builder, numElems) return builder:StartVector(";
+      auto vector_type = field.value.type.VectorType();
+      auto alignment = InlineAlignment(vector_type);
+      auto elem_size = InlineSize(vector_type);
+      code += NumToString(elem_size);
+      code += ", numElems, " + NumToString(alignment);
+      code += ") end\n";
+    }
+
+    // Get the offset of the end of a table.
+    void GetEndOffsetOnTable(const StructDef &struct_def,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "function " + NormalizedName(struct_def) + ".End";
+      code += "(builder) ";
+      code += "return builder:EndObject() end\n";
+    }
+
+    // Generate the receiver for function signatures.
+    void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += "function " + NormalizedMetaName(struct_def) + ":";
+    }
+
+    // Generate a struct field, conditioned on its child type(s).
+    void GenStructAccessor(const StructDef &struct_def,
+      const FieldDef &field, std::string *code_ptr) {
+      GenComment(field.doc_comment, code_ptr, &def_comment);
+      if (IsScalar(field.value.type.base_type)) {
+        if (struct_def.fixed) {
+          GetScalarFieldOfStruct(struct_def, field, code_ptr);
+        }
+        else {
+          GetScalarFieldOfTable(struct_def, field, code_ptr);
+        }
+      }
+      else {
+        switch (field.value.type.base_type) {
+        case BASE_TYPE_STRUCT:
+          if (struct_def.fixed) {
+            GetStructFieldOfStruct(struct_def, field, code_ptr);
+          }
+          else {
+            GetStructFieldOfTable(struct_def, field, code_ptr);
+          }
+          break;
+        case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break;
+        case BASE_TYPE_VECTOR: {
+          auto vectortype = field.value.type.VectorType();
+          if (vectortype.base_type == BASE_TYPE_STRUCT) {
+            GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+          }
+          else {
+            GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
+          }
+          break;
+        }
+        case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
+        default: FLATBUFFERS_ASSERT(0);
+        }
+      }
+      if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+        GetVectorLen(struct_def, field, code_ptr);
+      }
+    }
+
+    // Generate table constructors, conditioned on its members' types.
+    void GenTableBuilders(const StructDef &struct_def,
+      std::string *code_ptr) {
+      GetStartOfTable(struct_def, code_ptr);
+
+      for (auto it = struct_def.fields.vec.begin();
+        it != struct_def.fields.vec.end(); ++it) {
+        auto &field = **it;
+        if (field.deprecated) continue;
+
+        auto offset = it - struct_def.fields.vec.begin();
+        BuildFieldOfTable(struct_def, field, offset, code_ptr);
+        if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+          BuildVectorOfTable(struct_def, field, code_ptr);
+        }
+      }
+
+      GetEndOffsetOnTable(struct_def, code_ptr);
+    }
+
+    // Generate struct or table methods.
+    void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+      if (struct_def.generated) return;
+
+      GenComment(struct_def.doc_comment, code_ptr, &def_comment);
+      BeginClass(struct_def, code_ptr);
+
+      GenerateNewObjectPrototype(struct_def, code_ptr);
+
+      if (!struct_def.fixed) {
+        // Generate a special accessor for the table that has been declared as
+        // the root type.
+        NewRootTypeFromBuffer(struct_def, code_ptr);
+      }
+
+      // Generate the Init method that sets the field in a pre-existing
+      // accessor object. This is to allow object reuse.
+      InitializeExisting(struct_def, code_ptr);
+      for (auto it = struct_def.fields.vec.begin();
+        it != struct_def.fields.vec.end(); ++it) {
+        auto &field = **it;
+        if (field.deprecated) continue;
+
+        GenStructAccessor(struct_def, field, code_ptr);
+      }
+
+      if (struct_def.fixed) {
+        // create a struct constructor function
+        GenStructBuilder(struct_def, code_ptr);
+      }
+      else {
+        // Create a set of functions that allow table construction.
+        GenTableBuilders(struct_def, code_ptr);
+      }
+    }
+
+    // Generate enum declarations.
+    void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+      if (enum_def.generated) return;
+
+      GenComment(enum_def.doc_comment, code_ptr, &def_comment);
+      BeginEnum(NormalizedName(enum_def), code_ptr);
+      for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+           ++it) {
+        auto &ev = **it;
+        GenComment(ev.doc_comment, code_ptr, &def_comment, Indent);
+        EnumMember(enum_def, ev, code_ptr);
+      }
+      EndEnum(code_ptr);
+    }
+
+    // Returns the function name that is able to read a value of the given type.
+    std::string GenGetter(const Type &type) {
+      switch (type.base_type) {
+      case BASE_TYPE_STRING: return std::string(SelfData) + ":String(";
+      case BASE_TYPE_UNION: return  std::string(SelfData) + ":Union(";
+      case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
+      default:
+        return std::string(SelfData) + ":Get(flatbuffers.N." +
+          MakeCamel(GenTypeGet(type)) + ", ";
+      }
+    }
+
+    // Returns the method name for use with add/put calls.
+    std::string GenMethod(const FieldDef &field) {
+      return IsScalar(field.value.type.base_type)
+        ? MakeCamel(GenTypeBasic(field.value.type))
+        : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
+    }
+
+    std::string GenTypeBasic(const Type &type) {
+      static const char *ctypename[] = {
+        // clang-format off
+          #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+            CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+            #PTYPE,
+            FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+          #undef FLATBUFFERS_TD
+            // clang-format on
+      };
+      return ctypename[type.base_type];
+    }
+
+    std::string GenTypePointer(const Type &type) {
+      switch (type.base_type) {
+      case BASE_TYPE_STRING: return "string";
+      case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+      case BASE_TYPE_STRUCT: return type.struct_def->name;
+      case BASE_TYPE_UNION:
+        // fall through
+      default: return "*flatbuffers.Table";
+      }
+    }
+
+    std::string GenTypeGet(const Type &type) {
+      return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
+    }
+
+    std::string GetNamespace(const Type &type) {
+      return type.struct_def->defined_namespace->GetFullyQualifiedName(type.struct_def->name);
+    }
+
+    std::string TypeName(const FieldDef &field) {
+      return GenTypeGet(field.value.type);
+    }
+
+    std::string TypeNameWithNamespace(const FieldDef &field) {
+      return GetNamespace(field.value.type);
+    }
+
+    // Create a struct with a builder and the struct's arguments.
+    void GenStructBuilder(const StructDef &struct_def,
+      std::string *code_ptr) {
+      BeginBuilderArgs(struct_def, code_ptr);
+      StructBuilderArgs(struct_def, "", code_ptr);
+      EndBuilderArgs(code_ptr);
+
+      StructBuilderBody(struct_def, "", code_ptr);
+      EndBuilderBody(code_ptr);
+    }
+
+    bool generate() {
+      if (!generateEnums()) return false;
+      if (!generateStructs()) return false;
+      return true;
+    }
+
+  private:
+    bool generateEnums() {
+      for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+        ++it) {
+        auto &enum_def = **it;
+        std::string enumcode;
+        GenEnum(enum_def, &enumcode);
+        if (!SaveType(enum_def, enumcode, false)) return false;
+      }
+      return true;
+    }
+
+    bool generateStructs() {
+      for (auto it = parser_.structs_.vec.begin();
+        it != parser_.structs_.vec.end(); ++it) {
+        auto &struct_def = **it;
+        std::string declcode;
+        GenStruct(struct_def, &declcode);
+        if (!SaveType(struct_def, declcode, true)) return false;
+      }
+      return true;
+    }
+
+    // Begin by declaring namespace and imports.
+    void BeginFile(const std::string &name_space_name, const bool needs_imports,
+      std::string *code_ptr) {
+      std::string &code = *code_ptr;
+      code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n";
+      code += std::string(Comment) + "namespace: " + name_space_name + "\n\n";
+      if (needs_imports) {
+        code += "local flatbuffers = require('flatbuffers')\n\n";
+      }
+    }
+
+    // Save out the generated code for a Lua Table type.
+    bool SaveType(const Definition &def, const std::string &classcode,
+      bool needs_imports) {
+      if (!classcode.length()) return true;
+
+      std::string namespace_dir = path_;
+      auto &namespaces = def.defined_namespace->components;
+      for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+        if (it != namespaces.begin()) namespace_dir += kPathSeparator;
+        namespace_dir += *it;
+        //std::string init_py_filename = namespace_dir + "/__init__.py";
+        //SaveFile(init_py_filename.c_str(), "", false);
+      }
+
+      std::string code = "";
+      BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
+      code += classcode;
+      code += "\n";
+      code += "return " + NormalizedName(def) + " " + Comment + "return the module";
+      std::string filename =
+        NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua";
+      return SaveFile(filename.c_str(), code, false);
+    }
+  private:
+    std::unordered_set<std::string> keywords_;
+  };
+
+}  // namespace lua
+
+bool GenerateLua(const Parser &parser, const std::string &path,
+  const std::string &file_name) {
+  lua::LuaGenerator generator(parser, path, file_name);
+  return generator.generate();
+}
+
+}  // namespace flatbuffers