You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by ns...@apache.org on 2016/09/25 16:42:50 UTC

[01/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Repository: thrift
Updated Branches:
  refs/heads/master 5767901e7 -> 346e23149


http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_rb_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_rb_generator.cc b/compiler/cpp/src/thrift/generate/t_rb_generator.cc
new file mode 100644
index 0000000..924f6f6
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_rb_generator.cc
@@ -0,0 +1,1263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+
+#include "thrift/platform.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * A subclass of std::ofstream that includes indenting functionality.
+ */
+class t_rb_ofstream : public std::ofstream {
+private:
+  int indent_;
+
+public:
+  t_rb_ofstream() : std::ofstream(), indent_(0) {}
+  explicit t_rb_ofstream(const char* filename,
+                         ios_base::openmode mode = ios_base::out,
+                         int indent = 0)
+    : std::ofstream(filename, mode), indent_(indent) {}
+
+  t_rb_ofstream& indent() {
+    for (int i = 0; i < indent_; ++i) {
+      *this << "  ";
+    }
+    return *this;
+  }
+
+  void indent_up() { indent_++; }
+  void indent_down() { indent_--; }
+};
+
+/**
+ * Ruby code generator.
+ *
+ */
+class t_rb_generator : public t_oop_generator {
+public:
+  t_rb_generator(t_program* program,
+                 const std::map<std::string, std::string>& parsed_options,
+                 const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    require_rubygems_ = false;
+    namespaced_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("rubygems") == 0) {
+        require_rubygems_ = true;
+      } else if( iter->first.compare("namespaced") == 0) {
+        namespaced_ = true;
+      } else {
+        throw "unknown option ruby:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-rb";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_union(t_struct* tunion);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  t_rb_ofstream& render_const_value(t_rb_ofstream& out, t_type* type, t_const_value* value);
+
+  /**
+   * Struct generation code
+   */
+
+  void generate_rb_struct(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
+  void generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_rb_union(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
+  void generate_rb_union_validator(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_rb_function_helpers(t_function* tfunction);
+  void generate_rb_simple_constructor(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_rb_simple_exception_constructor(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_field_constants(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_field_constructors(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_field_defns(t_rb_ofstream& out, t_struct* tstruct);
+  void generate_field_data(t_rb_ofstream& out,
+                           t_type* field_type,
+                           const std::string& field_name,
+                           t_const_value* field_value,
+                           bool optional);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(t_rb_ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool inclass = false);
+
+  void generate_deserialize_struct(t_rb_ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(t_rb_ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(t_rb_ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(t_rb_ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(t_rb_ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(t_rb_ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(t_rb_ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(t_rb_ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(t_rb_ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(t_rb_ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(t_rb_ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_rdoc(t_rb_ofstream& out, t_doc* tdoc);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string rb_autogen_comment();
+  std::string render_require_thrift();
+  std::string render_includes();
+  std::string declare_field(t_field* tfield);
+  std::string type_name(const t_type* ttype);
+  std::string full_type_name(const t_type* ttype);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string rb_namespace_to_path_prefix(std::string rb_namespace);
+
+  std::vector<std::string> ruby_modules(const t_program* p) {
+    std::string ns = p->get_namespace("rb");
+    std::vector<std::string> modules;
+    if (ns.empty()) {
+      return modules;
+    }
+
+    std::string::iterator pos = ns.begin();
+    while (true) {
+      std::string::iterator delim = std::find(pos, ns.end(), '.');
+      modules.push_back(capitalize(std::string(pos, delim)));
+      pos = delim;
+      if (pos == ns.end()) {
+        break;
+      }
+      ++pos;
+    }
+
+    return modules;
+  }
+
+  void begin_namespace(t_rb_ofstream&, std::vector<std::string>);
+  void end_namespace(t_rb_ofstream&, std::vector<std::string>);
+
+private:
+  /**
+   * File streams
+   */
+
+  t_rb_ofstream f_types_;
+  t_rb_ofstream f_consts_;
+  t_rb_ofstream f_service_;
+
+  std::string namespace_dir_;
+  std::string require_prefix_;
+
+  /** If true, add a "require 'rubygems'" line to the top of each gen-rb file. */
+  bool require_rubygems_;
+
+  /** If true, generate files in idiomatic namespaced directories. */
+  bool namespaced_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_rb_generator::init_generator() {
+  string subdir = get_out_dir();
+
+  // Make output directory
+  MKDIR(subdir.c_str());
+
+  if (namespaced_) {
+    require_prefix_ = rb_namespace_to_path_prefix(program_->get_namespace("rb"));
+
+    string dir = require_prefix_;
+    string::size_type loc;
+
+    while ((loc = dir.find("/")) != string::npos) {
+      subdir = subdir + dir.substr(0, loc) + "/";
+      MKDIR(subdir.c_str());
+      dir = dir.substr(loc + 1);
+    }
+  }
+
+  namespace_dir_ = subdir;
+
+  // Make output file
+  string f_types_name = namespace_dir_ + underscore(program_name_) + "_types.rb";
+  f_types_.open(f_types_name.c_str());
+
+  string f_consts_name = namespace_dir_ + underscore(program_name_) + "_constants.rb";
+  f_consts_.open(f_consts_name.c_str());
+
+  // Print header
+  f_types_ << rb_autogen_comment() << endl << render_require_thrift() << render_includes() << endl;
+  begin_namespace(f_types_, ruby_modules(program_));
+
+  f_consts_ << rb_autogen_comment() << endl << render_require_thrift() << "require '"
+            << require_prefix_ << underscore(program_name_) << "_types'" << endl << endl;
+  begin_namespace(f_consts_, ruby_modules(program_));
+}
+
+/**
+ * Renders the require of thrift itself, and possibly of the rubygems dependency.
+ */
+string t_rb_generator::render_require_thrift() {
+  if (require_rubygems_) {
+    return "require 'rubygems'\nrequire 'thrift'\n";
+  } else {
+    return "require 'thrift'\n";
+  }
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_rb_generator::render_includes() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  for (size_t i = 0; i < includes.size(); ++i) {
+    if (namespaced_) {
+      t_program* included = includes[i];
+      std::string included_require_prefix
+          = rb_namespace_to_path_prefix(included->get_namespace("rb"));
+      std::string included_name = included->get_name();
+      result += "require '" + included_require_prefix + underscore(included_name) + "_types'\n";
+    } else {
+      result += "require '" + underscore(includes[i]->get_name()) + "_types'\n";
+    }
+  }
+  if (includes.size() > 0) {
+    result += "\n";
+  }
+  return result;
+}
+
+/**
+ * Autogen'd comment
+ */
+string t_rb_generator::rb_autogen_comment() {
+  return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+         + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n";
+}
+
+/**
+ * Closes the type files
+ */
+void t_rb_generator::close_generator() {
+  // Close types file
+  end_namespace(f_types_, ruby_modules(program_));
+  end_namespace(f_consts_, ruby_modules(program_));
+  f_types_.close();
+  f_consts_.close();
+}
+
+/**
+ * Generates a typedef. This is not done in Ruby, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_rb_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Generates code for an enumerated type. Done using a class to scope
+ * the values.
+ *
+ * @param tenum The enumeration
+ */
+void t_rb_generator::generate_enum(t_enum* tenum) {
+  f_types_.indent() << "module " << capitalize(tenum->get_name()) << endl;
+  f_types_.indent_up();
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+
+    // Ruby class constants have to be capitalized... omg i am so on the fence
+    // about languages strictly enforcing capitalization why can't we just all
+    // agree and play nice.
+    string name = capitalize((*c_iter)->get_name());
+
+    generate_rdoc(f_types_, *c_iter);
+    f_types_.indent() << name << " = " << value << endl;
+  }
+
+  // Create a hash mapping values back to their names (as strings) since ruby has no native enum
+  // type
+  f_types_.indent() << "VALUE_MAP = {";
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    // Populate the hash
+    int value = (*c_iter)->get_value();
+    if (c_iter != constants.begin())
+      f_types_ << ", ";
+    f_types_ << value << " => \"" << capitalize((*c_iter)->get_name()) << "\"";
+  }
+  f_types_ << "}" << endl;
+
+  // Create a set with valid values for this enum
+  f_types_.indent() << "VALID_VALUES = Set.new([";
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    // Populate the set
+    if (c_iter != constants.begin())
+      f_types_ << ", ";
+    f_types_ << capitalize((*c_iter)->get_name());
+  }
+  f_types_ << "]).freeze" << endl;
+
+  f_types_.indent_down();
+  f_types_.indent() << "end" << endl << endl;
+}
+
+/**
+ * Generate a constant value
+ */
+void t_rb_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  name[0] = toupper(name[0]);
+
+  f_consts_.indent() << name << " = ";
+  render_const_value(f_consts_, type, value) << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+t_rb_ofstream& t_rb_generator::render_const_value(t_rb_ofstream& out,
+                                                  t_type* type,
+                                                  t_const_value* value) {
+  type = get_true_type(type);
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << "%q\"" << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    out.indent() << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << full_type_name(type) << ".new({" << endl;
+    out.indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      out.indent();
+      render_const_value(out, g_type_string, v_iter->first) << " => ";
+      render_const_value(out, field_type, v_iter->second) << "," << endl;
+    }
+    out.indent_down();
+    out.indent() << "})";
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    out << "{" << endl;
+    out.indent_up();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out.indent();
+      render_const_value(out, ktype, v_iter->first) << " => ";
+      render_const_value(out, vtype, v_iter->second) << "," << endl;
+    }
+    out.indent_down();
+    out.indent() << "}";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    if (type->is_set()) {
+      out << "Set.new([" << endl;
+    } else {
+      out << "[" << endl;
+    }
+    out.indent_up();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out.indent();
+      render_const_value(out, etype, *v_iter) << "," << endl;
+    }
+    out.indent_down();
+    if (type->is_set()) {
+      out.indent() << "])";
+    } else {
+      out.indent() << "]";
+    }
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+  return out;
+}
+
+/**
+ * Generates a ruby struct
+ */
+void t_rb_generator::generate_struct(t_struct* tstruct) {
+  if (tstruct->is_union()) {
+    generate_rb_union(f_types_, tstruct, false);
+  } else {
+    generate_rb_struct(f_types_, tstruct, false);
+  }
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_rb_generator::generate_xception(t_struct* txception) {
+  generate_rb_struct(f_types_, txception, true);
+}
+
+/**
+ * Generates a ruby struct
+ */
+void t_rb_generator::generate_rb_struct(t_rb_ofstream& out,
+                                        t_struct* tstruct,
+                                        bool is_exception = false) {
+  generate_rdoc(out, tstruct);
+  out.indent() << "class " << type_name(tstruct);
+  if (is_exception) {
+    out << " < ::Thrift::Exception";
+  }
+  out << endl;
+
+  out.indent_up();
+  out.indent() << "include ::Thrift::Struct, ::Thrift::Struct_Union" << endl;
+
+  if (is_exception) {
+    generate_rb_simple_exception_constructor(out, tstruct);
+  }
+
+  generate_field_constants(out, tstruct);
+  generate_field_defns(out, tstruct);
+  generate_rb_struct_required_validator(out, tstruct);
+
+  out.indent() << "::Thrift::Struct.generate_accessors self" << endl;
+
+  out.indent_down();
+  out.indent() << "end" << endl << endl;
+}
+
+/**
+ * Generates a ruby union
+ */
+void t_rb_generator::generate_rb_union(t_rb_ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_exception = false) {
+  (void)is_exception;
+  generate_rdoc(out, tstruct);
+  out.indent() << "class " << type_name(tstruct) << " < ::Thrift::Union" << endl;
+
+  out.indent_up();
+  out.indent() << "include ::Thrift::Struct_Union" << endl;
+
+  generate_field_constructors(out, tstruct);
+
+  generate_field_constants(out, tstruct);
+  generate_field_defns(out, tstruct);
+  generate_rb_union_validator(out, tstruct);
+
+  out.indent() << "::Thrift::Union.generate_accessors self" << endl;
+
+  out.indent_down();
+  out.indent() << "end" << endl << endl;
+}
+
+void t_rb_generator::generate_field_constructors(t_rb_ofstream& out, t_struct* tstruct) {
+
+  out.indent() << "class << self" << endl;
+  out.indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (f_iter != fields.begin()) {
+      out << endl;
+    }
+    std::string field_name = (*f_iter)->get_name();
+
+    out.indent() << "def " << field_name << "(val)" << endl;
+    out.indent() << "  " << tstruct->get_name() << ".new(:" << field_name << ", val)" << endl;
+    out.indent() << "end" << endl;
+  }
+
+  out.indent_down();
+  out.indent() << "end" << endl;
+
+  out << endl;
+}
+
+void t_rb_generator::generate_rb_simple_exception_constructor(t_rb_ofstream& out,
+                                                              t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+
+  if (members.size() == 1) {
+    vector<t_field*>::const_iterator m_iter = members.begin();
+
+    if ((*m_iter)->get_type()->is_string()) {
+      string name = (*m_iter)->get_name();
+
+      out.indent() << "def initialize(message=nil)" << endl;
+      out.indent_up();
+      out.indent() << "super()" << endl;
+      out.indent() << "self." << name << " = message" << endl;
+      out.indent_down();
+      out.indent() << "end" << endl << endl;
+
+      if (name != "message") {
+        out.indent() << "def message; " << name << " end" << endl << endl;
+      }
+    }
+  }
+}
+
+void t_rb_generator::generate_field_constants(t_rb_ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    std::string field_name = (*f_iter)->get_name();
+    std::string cap_field_name = upcase_string(field_name);
+
+    out.indent() << cap_field_name << " = " << (*f_iter)->get_key() << endl;
+  }
+  out << endl;
+}
+
+void t_rb_generator::generate_field_defns(t_rb_ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out.indent() << "FIELDS = {" << endl;
+  out.indent_up();
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (f_iter != fields.begin()) {
+      out << "," << endl;
+    }
+
+    // generate the field docstrings within the FIELDS constant. no real better place...
+    generate_rdoc(out, *f_iter);
+
+    out.indent() << upcase_string((*f_iter)->get_name()) << " => ";
+
+    generate_field_data(out,
+                        (*f_iter)->get_type(),
+                        (*f_iter)->get_name(),
+                        (*f_iter)->get_value(),
+                        (*f_iter)->get_req() == t_field::T_OPTIONAL);
+  }
+  out.indent_down();
+  out << endl;
+  out.indent() << "}" << endl << endl;
+
+  out.indent() << "def struct_fields; FIELDS; end" << endl << endl;
+}
+
+void t_rb_generator::generate_field_data(t_rb_ofstream& out,
+                                         t_type* field_type,
+                                         const std::string& field_name = "",
+                                         t_const_value* field_value = NULL,
+                                         bool optional = false) {
+  field_type = get_true_type(field_type);
+
+  // Begin this field's defn
+  out << "{:type => " << type_to_enum(field_type);
+
+  if (!field_name.empty()) {
+    out << ", :name => '" << field_name << "'";
+  }
+
+  if (field_value != NULL) {
+    out << ", :default => ";
+    render_const_value(out, field_type, field_value);
+  }
+
+  if (!field_type->is_base_type()) {
+    if (field_type->is_struct() || field_type->is_xception()) {
+      out << ", :class => " << full_type_name((t_struct*)field_type);
+    } else if (field_type->is_list()) {
+      out << ", :element => ";
+      generate_field_data(out, ((t_list*)field_type)->get_elem_type());
+    } else if (field_type->is_map()) {
+      out << ", :key => ";
+      generate_field_data(out, ((t_map*)field_type)->get_key_type());
+      out << ", :value => ";
+      generate_field_data(out, ((t_map*)field_type)->get_val_type());
+    } else if (field_type->is_set()) {
+      out << ", :element => ";
+      generate_field_data(out, ((t_set*)field_type)->get_elem_type());
+    }
+  } else {
+    if (((t_base_type*)field_type)->is_binary()) {
+      out << ", :binary => true";
+    }
+  }
+
+  if (optional) {
+    out << ", :optional => true";
+  }
+
+  if (field_type->is_enum()) {
+    out << ", :enum_class => " << full_type_name(field_type);
+  }
+
+  // End of this field's defn
+  out << "}";
+}
+
+void t_rb_generator::begin_namespace(t_rb_ofstream& out, vector<std::string> modules) {
+  for (vector<std::string>::iterator m_iter = modules.begin(); m_iter != modules.end(); ++m_iter) {
+    out.indent() << "module " << *m_iter << endl;
+    out.indent_up();
+  }
+}
+
+void t_rb_generator::end_namespace(t_rb_ofstream& out, vector<std::string> modules) {
+  for (vector<std::string>::reverse_iterator m_iter = modules.rbegin(); m_iter != modules.rend();
+       ++m_iter) {
+    out.indent_down();
+    out.indent() << "end" << endl;
+  }
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_rb_generator::generate_service(t_service* tservice) {
+  string f_service_name = namespace_dir_ + underscore(service_name_) + ".rb";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << rb_autogen_comment() << endl << render_require_thrift();
+
+  if (tservice->get_extends() != NULL) {
+    if (namespaced_) {
+      f_service_ << "require '" << rb_namespace_to_path_prefix(
+                                       tservice->get_extends()->get_program()->get_namespace("rb"))
+                 << underscore(tservice->get_extends()->get_name()) << "'" << endl;
+    } else {
+      f_service_ << "require '" << require_prefix_
+                 << underscore(tservice->get_extends()->get_name()) << "'" << endl;
+    }
+  }
+
+  f_service_ << "require '" << require_prefix_ << underscore(program_name_) << "_types'" << endl
+             << endl;
+
+  begin_namespace(f_service_, ruby_modules(tservice->get_program()));
+
+  f_service_.indent() << "module " << capitalize(tservice->get_name()) << endl;
+  f_service_.indent_up();
+
+  // Generate the three main parts of the service (well, two for now in PHP)
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+
+  f_service_.indent_down();
+  f_service_.indent() << "end" << endl << endl;
+
+  end_namespace(f_service_, ruby_modules(tservice->get_program()));
+
+  // Close service file
+  f_service_.close();
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_rb_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  f_service_.indent() << "# HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_rb_struct(f_service_, ts);
+    generate_rb_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_rb_generator::generate_rb_function_helpers(t_function* tfunction) {
+  t_struct result(program_, tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+  generate_rb_struct(f_service_, &result);
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_rb_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = full_type_name(tservice->get_extends());
+    extends_client = " < " + extends + "::Client ";
+  }
+
+  f_service_.indent() << "class Client" << extends_client << endl;
+  f_service_.indent_up();
+
+  f_service_.indent() << "include ::Thrift::Client" << endl << endl;
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    f_service_.indent() << "def " << function_signature(*f_iter) << endl;
+    f_service_.indent_up();
+    f_service_.indent() << "send_" << funname << "(";
+
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << (*fld_iter)->get_name();
+    }
+    f_service_ << ")" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_.indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "recv_" << funname << "()" << endl;
+    }
+    f_service_.indent_down();
+    f_service_.indent() << "end" << endl;
+    f_service_ << endl;
+
+    f_service_.indent() << "def send_" << function_signature(*f_iter) << endl;
+    f_service_.indent_up();
+
+    std::string argsname = capitalize((*f_iter)->get_name() + "_args");
+    std::string messageSendProc = (*f_iter)->is_oneway() ? "send_oneway_message" : "send_message";
+
+    f_service_.indent() << messageSendProc << "('" << funname << "', " << argsname;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", :" << (*fld_iter)->get_name() << " => " << (*fld_iter)->get_name();
+    }
+
+    f_service_ << ")" << endl;
+
+    f_service_.indent_down();
+    f_service_.indent() << "end" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = capitalize((*f_iter)->get_name() + "_result");
+      t_struct noargs(program_);
+
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs);
+      // Open function
+      f_service_ << endl;
+      f_service_.indent() << "def " << function_signature(&recv_function) << endl;
+      f_service_.indent_up();
+
+      // TODO(mcslee): Validate message reply here, seq ids etc.
+
+      f_service_.indent() << "result = receive_message(" << resultname << ")" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_.indent() << "return result.success unless result.success.nil?" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_.indent() << "raise result." << (*x_iter)->get_name() << " unless result."
+                            << (*x_iter)->get_name() << ".nil?" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        f_service_.indent() << "return" << endl;
+      } else {
+        f_service_.indent() << "raise "
+                               "::Thrift::ApplicationException.new(::Thrift::ApplicationException::"
+                               "MISSING_RESULT, '" << (*f_iter)->get_name()
+                            << " failed: unknown result')" << endl;
+      }
+
+      // Close function
+      f_service_.indent_down();
+      f_service_.indent() << "end" << endl << endl;
+    }
+  }
+
+  f_service_.indent_down();
+  f_service_.indent() << "end" << endl << endl;
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_rb_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = full_type_name(tservice->get_extends());
+    extends_processor = " < " + extends + "::Processor ";
+  }
+
+  // Generate the header portion
+  f_service_.indent() << "class Processor" << extends_processor << endl;
+  f_service_.indent_up();
+
+  f_service_.indent() << "include ::Thrift::Processor" << endl << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  f_service_.indent_down();
+  f_service_.indent() << "end" << endl << endl;
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_rb_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open function
+  f_service_.indent() << "def process_" << tfunction->get_name() << "(seqid, iprot, oprot)" << endl;
+  f_service_.indent_up();
+
+  string argsname = capitalize(tfunction->get_name()) + "_args";
+  string resultname = capitalize(tfunction->get_name()) + "_result";
+
+  f_service_.indent() << "args = read_args(iprot, " << argsname << ")" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_.indent() << "result = " << resultname << ".new()" << endl;
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    f_service_.indent() << "begin" << endl;
+    f_service_.indent_up();
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_.indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result.success = ";
+  }
+  f_service_ << "@handler." << tfunction->get_name() << "(";
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << (*f_iter)->get_name();
+  }
+  f_service_ << ")" << endl;
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    f_service_.indent_down();
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_.indent() << "rescue " << full_type_name((*x_iter)->get_type()) << " => "
+                          << (*x_iter)->get_name() << endl;
+      if (!tfunction->is_oneway()) {
+        f_service_.indent_up();
+        f_service_.indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name()
+                            << endl;
+        f_service_.indent_down();
+      }
+    }
+    f_service_.indent() << "end" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_.indent() << "return" << endl;
+    f_service_.indent_down();
+    f_service_.indent() << "end" << endl << endl;
+    return;
+  }
+
+  f_service_.indent() << "write_result(result, oprot, '" << tfunction->get_name() << "', seqid)"
+                      << endl;
+
+  // Close function
+  f_service_.indent_down();
+  f_service_.indent() << "end" << endl << endl;
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_rb_generator::function_signature(t_function* tfunction, string prefix) {
+  // TODO(mcslee): Nitpicky, no ',' if argument_list is empty
+  return prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")";
+}
+
+/**
+ * Renders a field list
+ */
+string t_rb_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += (*f_iter)->get_name();
+  }
+  return result;
+}
+
+string t_rb_generator::type_name(const t_type* ttype) {
+  string prefix = "";
+
+  string name = ttype->get_name();
+  if (ttype->is_struct() || ttype->is_xception() || ttype->is_enum()) {
+    name = capitalize(ttype->get_name());
+  }
+
+  return prefix + name;
+}
+
+string t_rb_generator::full_type_name(const t_type* ttype) {
+  string prefix = "::";
+  vector<std::string> modules = ruby_modules(ttype->get_program());
+  for (vector<std::string>::iterator m_iter = modules.begin(); m_iter != modules.end(); ++m_iter) {
+    prefix += *m_iter + "::";
+  }
+  return prefix + type_name(ttype);
+}
+
+/**
+ * Converts the parse type to a Ruby tyoe
+ */
+string t_rb_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "::Thrift::Types::STRING";
+    case t_base_type::TYPE_BOOL:
+      return "::Thrift::Types::BOOL";
+    case t_base_type::TYPE_I8:
+      return "::Thrift::Types::BYTE";
+    case t_base_type::TYPE_I16:
+      return "::Thrift::Types::I16";
+    case t_base_type::TYPE_I32:
+      return "::Thrift::Types::I32";
+    case t_base_type::TYPE_I64:
+      return "::Thrift::Types::I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "::Thrift::Types::DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "::Thrift::Types::I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "::Thrift::Types::STRUCT";
+  } else if (type->is_map()) {
+    return "::Thrift::Types::MAP";
+  } else if (type->is_set()) {
+    return "::Thrift::Types::SET";
+  } else if (type->is_list()) {
+    return "::Thrift::Types::LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+string t_rb_generator::rb_namespace_to_path_prefix(string rb_namespace) {
+  string namespaces_left = rb_namespace;
+  string::size_type loc;
+
+  string path_prefix = "";
+
+  while ((loc = namespaces_left.find(".")) != string::npos) {
+    path_prefix = path_prefix + underscore(namespaces_left.substr(0, loc)) + "/";
+    namespaces_left = namespaces_left.substr(loc + 1);
+  }
+  if (namespaces_left.size() > 0) {
+    path_prefix = path_prefix + underscore(namespaces_left) + "/";
+  }
+  return path_prefix;
+}
+
+void t_rb_generator::generate_rdoc(t_rb_ofstream& out, t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    out.indent();
+    generate_docstring_comment(out, "", "# ", tdoc->get_doc(), "");
+  }
+}
+
+void t_rb_generator::generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct) {
+  out.indent() << "def validate" << endl;
+  out.indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    if (field->get_req() == t_field::T_REQUIRED) {
+      out.indent() << "raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, "
+                      "'Required field " << field->get_name() << " is unset!')";
+      if (field->get_type()->is_bool()) {
+        out << " if @" << field->get_name() << ".nil?";
+      } else {
+        out << " unless @" << field->get_name();
+      }
+      out << endl;
+    }
+  }
+
+  // if field is an enum, check that its value is valid
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+
+    if (field->get_type()->is_enum()) {
+      out.indent() << "unless @" << field->get_name() << ".nil? || "
+                   << full_type_name(field->get_type()) << "::VALID_VALUES.include?(@"
+                   << field->get_name() << ")" << endl;
+      out.indent_up();
+      out.indent() << "raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, "
+                      "'Invalid value of field " << field->get_name() << "!')" << endl;
+      out.indent_down();
+      out.indent() << "end" << endl;
+    }
+  }
+
+  out.indent_down();
+  out.indent() << "end" << endl << endl;
+}
+
+void t_rb_generator::generate_rb_union_validator(t_rb_ofstream& out, t_struct* tstruct) {
+  out.indent() << "def validate" << endl;
+  out.indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out.indent()
+      << "raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil?"
+      << endl;
+
+  // if field is an enum, check that its value is valid
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    const t_field* field = (*f_iter);
+
+    if (field->get_type()->is_enum()) {
+      out.indent() << "if get_set_field == :" << field->get_name() << endl;
+      out.indent() << "  raise "
+                      "::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, "
+                      "'Invalid value of field " << field->get_name() << "!') unless "
+                   << full_type_name(field->get_type()) << "::VALID_VALUES.include?(get_value)"
+                   << endl;
+      out.indent() << "end" << endl;
+    }
+  }
+
+  out.indent_down();
+  out.indent() << "end" << endl << endl;
+}
+
+THRIFT_REGISTER_GENERATOR(
+    rb,
+    "Ruby",
+    "    rubygems:        Add a \"require 'rubygems'\" line to the top of each generated file.\n"
+    "    namespaced:      Generate files in idiomatic namespaced directories.\n")


[06/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_json_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_json_generator.cc b/compiler/cpp/src/thrift/generate/t_json_generator.cc
new file mode 100644
index 0000000..36e9216
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_json_generator.cc
@@ -0,0 +1,727 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <limits>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+using std::stack;
+
+static const string endl = "\n";
+static const string quot = "\"";
+static const bool NO_INDENT = false;
+static const bool FORCE_STRING = true;
+
+class t_json_generator : public t_generator {
+public:
+  t_json_generator(t_program* program,
+                   const std::map<std::string, std::string>& parsed_options,
+                   const std::string& option_string)
+    : t_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    should_merge_includes_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("merge") == 0) {
+        should_merge_includes_ = true;
+      } else {
+        throw "unknown option json:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-json";
+  }
+
+  virtual ~t_json_generator() {}
+
+  /**
+  * Init and close methods
+  */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_program();
+  void generate_function(t_function* tfunc);
+  void generate_field(t_field* field);
+
+  void generate_service(t_service* tservice);
+  void generate_struct(t_struct* tstruct);
+
+private:
+  bool should_merge_includes_;
+
+  std::ofstream f_json_;
+  std::stack<bool> comma_needed_;
+
+  template <typename T>
+  string number_to_string(T t) {
+    std::ostringstream out;
+    out.imbue(std::locale::classic());
+    out.precision(std::numeric_limits<T>::digits10);
+    out << t;
+    return out.str();
+  }
+
+  template <typename T>
+  void write_number(T n) {
+    f_json_ << number_to_string(n);
+  }
+
+  string get_type_name(t_type* ttype);
+  string get_qualified_name(t_type* ttype);
+
+  void start_object(bool should_indent = true);
+  void start_array();
+  void end_object();
+  void end_array();
+  void write_comma_if_needed();
+  void indicate_comma_needed();
+  string escape_json_string(const string& input);
+  string json_str(const string& str);
+  void merge_includes(t_program*);
+
+  void generate_constant(t_const* con);
+
+  void write_type_spec_entry(const char* name, t_type* ttype);
+  void write_type_spec_object(const char* name, t_type* ttype);
+  void write_type_spec(t_type* ttype);
+  void write_string(const string& value);
+  void write_value(t_type* tvalue);
+  void write_const_value(t_const_value* value, bool force_string = false);
+  void write_key_and(string key);
+  void write_key_and_string(string key, string val);
+  void write_key_and_integer(string key, int val);
+  void write_key_and_bool(string key, bool val);
+};
+
+void t_json_generator::init_generator() {
+  MKDIR(get_out_dir().c_str());
+
+  string f_json_name = get_out_dir() + program_->get_name() + ".json";
+  f_json_.open(f_json_name.c_str());
+
+  // Merge all included programs into this one so we can output one big file.
+  if (should_merge_includes_) {
+    merge_includes(program_);
+  }
+}
+
+string t_json_generator::escape_json_string(const string& input) {
+  std::ostringstream ss;
+  for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
+    switch (*iter) {
+    case '\\':
+      ss << "\\\\";
+      break;
+    case '"':
+      ss << "\\\"";
+      break;
+    case '/':
+      ss << "\\/";
+      break;
+    case '\b':
+      ss << "\\b";
+      break;
+    case '\f':
+      ss << "\\f";
+      break;
+    case '\n':
+      ss << "\\n";
+      break;
+    case '\r':
+      ss << "\\r";
+      break;
+    case '\t':
+      ss << "\\t";
+      break;
+    default:
+      ss << *iter;
+      break;
+    }
+  }
+  return ss.str();
+}
+
+void t_json_generator::start_object(bool should_indent) {
+  f_json_ << (should_indent ? indent() : "") << "{" << endl;
+  indent_up();
+  comma_needed_.push(false);
+}
+
+void t_json_generator::start_array() {
+  f_json_ << "[" << endl;
+  indent_up();
+  comma_needed_.push(false);
+}
+
+void t_json_generator::write_comma_if_needed() {
+  if (comma_needed_.top()) {
+    f_json_ << "," << endl;
+  }
+}
+
+void t_json_generator::indicate_comma_needed() {
+  comma_needed_.pop();
+  comma_needed_.push(true);
+}
+
+void t_json_generator::write_key_and(string key) {
+  write_comma_if_needed();
+  indent(f_json_) << json_str(key) << ": ";
+  indicate_comma_needed();
+}
+
+void t_json_generator::write_key_and_integer(string key, int val) {
+  write_comma_if_needed();
+  indent(f_json_) << json_str(key) << ": " << number_to_string(val);
+  indicate_comma_needed();
+}
+
+void t_json_generator::write_key_and_string(string key, string val) {
+  write_comma_if_needed();
+  indent(f_json_) << json_str(key) << ": " << json_str(val);
+  indicate_comma_needed();
+}
+
+void t_json_generator::write_key_and_bool(string key, bool val) {
+  write_comma_if_needed();
+  indent(f_json_) << json_str(key) << ": " << (val ? "true" : "false");
+  indicate_comma_needed();
+}
+
+void t_json_generator::end_object() {
+  indent_down();
+  f_json_ << endl << indent() << "}";
+  comma_needed_.pop();
+}
+
+void t_json_generator::end_array() {
+  indent_down();
+  if (comma_needed_.top()) {
+    f_json_ << endl;
+  }
+  indent(f_json_) << "]";
+  comma_needed_.pop();
+}
+
+void t_json_generator::write_type_spec_object(const char* name, t_type* ttype) {
+  ttype = ttype->get_true_type();
+  if (ttype->is_struct() || ttype->is_xception() || ttype->is_container()) {
+    write_key_and(name);
+    start_object(NO_INDENT);
+    write_key_and("typeId");
+    write_type_spec(ttype);
+    end_object();
+  }
+}
+
+void t_json_generator::write_type_spec_entry(const char* name, t_type* ttype) {
+  write_key_and(name);
+  write_type_spec(ttype);
+}
+
+void t_json_generator::write_type_spec(t_type* ttype) {
+  ttype = ttype->get_true_type();
+
+  write_string(get_type_name(ttype));
+
+  if (ttype->is_struct() || ttype->is_xception()) {
+    write_key_and_string("class", get_qualified_name(ttype));
+  } else if (ttype->is_map()) {
+    t_type* ktype = ((t_map*)ttype)->get_key_type();
+    t_type* vtype = ((t_map*)ttype)->get_val_type();
+    write_key_and_string("keyTypeId", get_type_name(ktype));
+    write_key_and_string("valueTypeId", get_type_name(vtype));
+    write_type_spec_object("keyType", ktype);
+    write_type_spec_object("valueType", vtype);
+  } else if (ttype->is_list() || ttype->is_set()) {
+    t_type* etype = ((t_list*)ttype)->get_elem_type();
+    write_key_and_string("elemTypeId", get_type_name(etype));
+    write_type_spec_object("elemType", etype);
+  }
+}
+
+void t_json_generator::close_generator() {
+  f_json_ << endl;
+  f_json_.close();
+}
+
+void t_json_generator::merge_includes(t_program* program) {
+  vector<t_program*> includes = program->get_includes();
+  vector<t_program*>::iterator inc_iter;
+  for (inc_iter = includes.begin(); inc_iter != includes.end(); ++inc_iter) {
+    t_program* include = *inc_iter;
+    // recurse in case we get crazy
+    merge_includes(include);
+    // merge enums
+    vector<t_enum*> enums = include->get_enums();
+    vector<t_enum*>::iterator en_iter;
+    for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
+      program->add_enum(*en_iter);
+    }
+    // merge typedefs
+    vector<t_typedef*> typedefs = include->get_typedefs();
+    vector<t_typedef*>::iterator td_iter;
+    for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
+      program->add_typedef(*td_iter);
+    }
+    // merge structs
+    vector<t_struct*> objects = include->get_objects();
+    vector<t_struct*>::iterator o_iter;
+    for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
+      program->add_struct(*o_iter);
+    }
+    // merge constants
+    vector<t_const*> consts = include->get_consts();
+    vector<t_const*>::iterator c_iter;
+    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+      program->add_const(*c_iter);
+    }
+
+    // merge services
+    vector<t_service*> services = include->get_services();
+    vector<t_service*>::iterator sv_iter;
+    for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+      program->add_service(*sv_iter);
+    }
+  }
+}
+
+void t_json_generator::generate_program() {
+
+  init_generator();
+
+  start_object();
+  write_key_and_string("name", program_->get_name());
+  if (program_->has_doc()) {
+    write_key_and_string("doc", program_->get_doc());
+  }
+
+  // When merging includes, the "namespaces" and "includes" sections
+  // become ambiguous, so just skip them.
+  if (!should_merge_includes_) {
+    // Generate namespaces
+    write_key_and("namespaces");
+    start_object(NO_INDENT);
+    const map<string, string>& namespaces = program_->get_namespaces();
+    map<string, string>::const_iterator ns_it;
+    for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) {
+      write_key_and_string(ns_it->first, ns_it->second);
+      indicate_comma_needed();
+    }
+    end_object();
+
+    // Generate includes
+    write_key_and("includes");
+    start_array();
+    const vector<t_program*> includes = program_->get_includes();
+    vector<t_program*>::const_iterator inc_it;
+    for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) {
+      write_comma_if_needed();
+      write_string((*inc_it)->get_name());
+      indicate_comma_needed();
+    }
+    end_array();
+  }
+
+  // Generate enums
+  write_key_and("enums");
+  start_array();
+  vector<t_enum*> enums = program_->get_enums();
+  vector<t_enum*>::iterator en_iter;
+  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
+    write_comma_if_needed();
+    generate_enum(*en_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  // Generate typedefs
+  write_key_and("typedefs");
+  start_array();
+  vector<t_typedef*> typedefs = program_->get_typedefs();
+  vector<t_typedef*>::iterator td_iter;
+  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
+    write_comma_if_needed();
+    generate_typedef(*td_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  // Generate structs, exceptions, and unions in declared order
+  write_key_and("structs");
+  start_array();
+  vector<t_struct*> objects = program_->get_objects();
+  vector<t_struct*>::iterator o_iter;
+  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
+    write_comma_if_needed();
+    if ((*o_iter)->is_xception()) {
+      generate_xception(*o_iter);
+    } else {
+      generate_struct(*o_iter);
+    }
+    indicate_comma_needed();
+  }
+  end_array();
+
+  // Generate constants
+  write_key_and("constants");
+  start_array();
+  vector<t_const*> consts = program_->get_consts();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    write_comma_if_needed();
+    generate_constant(*c_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  // Generate services
+  write_key_and("services");
+  start_array();
+  vector<t_service*> services = program_->get_services();
+  vector<t_service*>::iterator sv_iter;
+  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+    write_comma_if_needed();
+    generate_service(*sv_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  end_object();
+
+  // Close the generator
+  close_generator();
+}
+
+void t_json_generator::generate_typedef(t_typedef* ttypedef) {
+  start_object();
+  write_key_and_string("name", get_qualified_name(ttypedef));
+  write_key_and_string("typeId", get_type_name(ttypedef->get_true_type()));
+  write_type_spec_object("type", ttypedef->get_true_type());
+  if (ttypedef->has_doc()) {
+    write_key_and_string("doc", ttypedef->get_doc());
+  }
+  end_object();
+}
+
+void t_json_generator::write_string(const string& value) {
+  f_json_ << quot << escape_json_string(value) << quot;
+}
+
+void t_json_generator::write_const_value(t_const_value* value, bool should_force_string) {
+
+  switch (value->get_type()) {
+
+  case t_const_value::CV_IDENTIFIER:
+  case t_const_value::CV_INTEGER:
+    if (should_force_string) {
+      write_string(number_to_string(value->get_integer()));
+    } else {
+      write_number(value->get_integer());
+    }
+    break;
+
+  case t_const_value::CV_DOUBLE:
+    if (should_force_string) {
+      write_string(number_to_string(value->get_double()));
+    } else {
+      write_number(value->get_double());
+    }
+    break;
+
+  case t_const_value::CV_STRING:
+    write_string(value->get_string());
+    break;
+
+  case t_const_value::CV_LIST: {
+    start_array();
+    std::vector<t_const_value*> list = value->get_list();
+    std::vector<t_const_value*>::iterator lit;
+    for (lit = list.begin(); lit != list.end(); ++lit) {
+      write_comma_if_needed();
+      f_json_ << indent();
+      write_const_value(*lit);
+      indicate_comma_needed();
+    }
+    end_array();
+    break;
+  }
+
+  case t_const_value::CV_MAP: {
+    start_object(NO_INDENT);
+    std::map<t_const_value*, t_const_value*> map = value->get_map();
+    std::map<t_const_value*, t_const_value*>::iterator mit;
+    for (mit = map.begin(); mit != map.end(); ++mit) {
+      write_comma_if_needed();
+      f_json_ << indent();
+      // JSON objects only allow string keys
+      write_const_value(mit->first, FORCE_STRING);
+      f_json_ << ": ";
+      write_const_value(mit->second);
+      indicate_comma_needed();
+    }
+    end_object();
+    break;
+  }
+
+  default:
+    f_json_ << "null";
+    break;
+  }
+}
+
+string t_json_generator::json_str(const string& str) {
+  return quot + escape_json_string(str) + quot;
+}
+
+void t_json_generator::generate_constant(t_const* con) {
+  start_object();
+
+  write_key_and_string("name", con->get_name());
+  write_key_and_string("typeId", get_type_name(con->get_type()));
+  write_type_spec_object("type", con->get_type());
+
+  if (con->has_doc()) {
+    write_key_and_string("doc", con->get_doc());
+  }
+
+  write_key_and("value");
+  write_const_value(con->get_value());
+
+  end_object();
+}
+
+void t_json_generator::generate_enum(t_enum* tenum) {
+  start_object();
+
+  write_key_and_string("name", tenum->get_name());
+
+  if (tenum->has_doc()) {
+    write_key_and_string("doc", tenum->get_doc());
+  }
+
+  write_key_and("members");
+  start_array();
+  vector<t_enum_value*> values = tenum->get_constants();
+  vector<t_enum_value*>::iterator val_iter;
+  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
+    write_comma_if_needed();
+    t_enum_value* val = (*val_iter);
+    start_object();
+    write_key_and_string("name", val->get_name());
+    write_key_and_integer("value", val->get_value());
+    if (val->has_doc()) {
+      write_key_and_string("doc", val->get_doc());
+    }
+    end_object();
+    indicate_comma_needed();
+  }
+  end_array();
+
+  end_object();
+}
+
+void t_json_generator::generate_struct(t_struct* tstruct) {
+  start_object();
+
+  write_key_and_string("name", tstruct->get_name());
+
+  if (tstruct->has_doc()) {
+    write_key_and_string("doc", tstruct->get_doc());
+  }
+
+  write_key_and_bool("isException", tstruct->is_xception());
+
+  write_key_and_bool("isUnion", tstruct->is_union());
+
+  write_key_and("fields");
+  start_array();
+  vector<t_field*> members = tstruct->get_members();
+  vector<t_field*>::iterator mem_iter;
+  for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) {
+    write_comma_if_needed();
+    generate_field(*mem_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  end_object();
+}
+
+void t_json_generator::generate_service(t_service* tservice) {
+  start_object();
+
+  write_key_and_string("name", get_qualified_name(tservice));
+
+  if (tservice->get_extends()) {
+    write_key_and_string("extends", get_qualified_name(tservice->get_extends()));
+  }
+
+  if (tservice->has_doc()) {
+    write_key_and_string("doc", tservice->get_doc());
+  }
+
+  write_key_and("functions");
+  start_array();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator fn_iter = functions.begin();
+  for (; fn_iter != functions.end(); fn_iter++) {
+    write_comma_if_needed();
+    generate_function(*fn_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  end_object();
+}
+
+void t_json_generator::generate_function(t_function* tfunc) {
+  start_object();
+
+  write_key_and_string("name", tfunc->get_name());
+
+  write_key_and_string("returnTypeId", get_type_name(tfunc->get_returntype()));
+  write_type_spec_object("returnType", tfunc->get_returntype());
+
+  write_key_and_bool("oneway", tfunc->is_oneway());
+
+  if (tfunc->has_doc()) {
+    write_key_and_string("doc", tfunc->get_doc());
+  }
+
+  write_key_and("arguments");
+  start_array();
+  vector<t_field*> members = tfunc->get_arglist()->get_members();
+  vector<t_field*>::iterator mem_iter = members.begin();
+  for (; mem_iter != members.end(); mem_iter++) {
+    write_comma_if_needed();
+    generate_field(*mem_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  write_key_and("exceptions");
+  start_array();
+  vector<t_field*> excepts = tfunc->get_xceptions()->get_members();
+  vector<t_field*>::iterator ex_iter = excepts.begin();
+  for (; ex_iter != excepts.end(); ex_iter++) {
+    write_comma_if_needed();
+    generate_field(*ex_iter);
+    indicate_comma_needed();
+  }
+  end_array();
+
+  end_object();
+}
+
+void t_json_generator::generate_field(t_field* field) {
+  start_object();
+
+  write_key_and_integer("key", field->get_key());
+  write_key_and_string("name", field->get_name());
+  write_key_and_string("typeId", get_type_name(field->get_type()));
+  write_type_spec_object("type", field->get_type());
+
+  if (field->has_doc()) {
+    write_key_and_string("doc", field->get_doc());
+  }
+
+  write_key_and("required");
+  switch (field->get_req()) {
+  case t_field::T_REQUIRED:
+    write_string("required");
+    break;
+  case t_field::T_OPT_IN_REQ_OUT:
+    write_string("req_out");
+    break;
+  default:
+    write_string("optional");
+    break;
+  }
+
+  if (field->get_value()) {
+    write_key_and("default");
+    write_const_value(field->get_value());
+  }
+
+  end_object();
+}
+
+string t_json_generator::get_type_name(t_type* ttype) {
+  ttype = ttype->get_true_type();
+  if (ttype->is_list()) {
+    return "list";
+  }
+  if (ttype->is_set()) {
+    return "set";
+  }
+  if (ttype->is_map()) {
+    return "map";
+  }
+  if (ttype->is_enum()) {
+    return "i32";
+  }
+  if (ttype->is_struct()) {
+    return ((t_struct*)ttype)->is_union() ? "union" : "struct";
+  }
+  if (ttype->is_xception()) {
+    return "exception";
+  }
+  if (ttype->is_base_type()) {
+    t_base_type* tbasetype = (t_base_type*)ttype;
+    return tbasetype->is_binary() ? "binary" : t_base_type::t_base_name(tbasetype->get_base());
+  }
+
+  return "(unknown)";
+}
+
+string t_json_generator::get_qualified_name(t_type* ttype) {
+  if (should_merge_includes_ || ttype->get_program() == program_) {
+    return ttype->get_name();
+  }
+  return ttype->get_program()->get_name() + "." + ttype->get_name();
+}
+
+THRIFT_REGISTER_GENERATOR(json,
+                          "JSON",
+                          "    merge:           Generate output with included files merged\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_lua_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_lua_generator.cc b/compiler/cpp/src/thrift/generate/t_lua_generator.cc
new file mode 100644
index 0000000..97b8aa3
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_lua_generator.cc
@@ -0,0 +1,1138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::ofstream;
+using std::string;
+using std::vector;
+using std::map;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * LUA code generator.
+ *
+ */
+class t_lua_generator : public t_oop_generator {
+public:
+  t_lua_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    gen_requires_ = true;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("omit_requires") == 0) {
+        gen_requires_ = false;
+      } else {
+        throw "unknown option lua:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-lua";
+  }
+
+  /**
+   * Init and close methods
+   */
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+private:
+  /**
+   * True iff we should generate lua require statements.
+   */
+  bool gen_requires_;
+
+  /**
+   * Struct-level generation functions
+   */
+  void generate_lua_struct_definition(std::ofstream& out,
+                                      t_struct* tstruct,
+                                      bool is_xception = false);
+  void generate_lua_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_lua_struct_writer(std::ofstream& out, t_struct* tstruct);
+
+  /**
+   * Service-level generation functions
+   */
+  void generate_service_client(std::ofstream& out, t_service* tservice);
+  void generate_service_interface(std::ofstream& out, t_service* tservice);
+  void generate_service_processor(std::ofstream& out, t_service* tservice);
+  void generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction);
+  void generate_service_helpers(ofstream& out, t_service* tservice);
+  void generate_function_helpers(ofstream& out, t_function* tfunction);
+
+  /**
+   * Deserialization (Read)
+   */
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  bool local,
+                                  std::string prefix = "");
+
+  void generate_deserialize_struct(std::ofstream& out,
+                                   t_struct* tstruct,
+                                   bool local,
+                                   std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out,
+                                      t_type* ttype,
+                                      bool local,
+                                      std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  /**
+   * Serialization (Write)
+   */
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  /**
+   * Helper rendering functions
+   */
+  std::string lua_includes();
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct, std::string prefix = "");
+  std::string type_to_enum(t_type* ttype);
+  static std::string get_namespace(const t_program* program);
+
+  std::string autogen_comment() {
+    return std::string("--\n") + "-- Autogenerated by Thrift\n" + "--\n"
+           + "-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "-- @"
+                                                                                       "generated\n"
+           + "--\n";
+  }
+
+  /**
+   * File streams
+   */
+  std::ofstream f_types_;
+  std::ofstream f_consts_;
+  std::ofstream f_service_;
+};
+
+/**
+ * Init and close methods
+ */
+void t_lua_generator::init_generator() {
+  // Make output directory
+  string outdir = get_out_dir();
+  MKDIR(outdir.c_str());
+
+  // Make output files
+  string cur_namespace = get_namespace(program_);
+  string f_consts_name = outdir + cur_namespace + "constants.lua";
+  f_consts_.open(f_consts_name.c_str());
+  string f_types_name = outdir + cur_namespace + "ttypes.lua";
+  f_types_.open(f_types_name.c_str());
+
+  // Add headers
+  f_consts_ << autogen_comment() << lua_includes();
+  f_types_ << autogen_comment() << lua_includes();
+  if (gen_requires_) {
+    f_types_ << endl << "require '" << cur_namespace << "constants'";
+  }
+}
+
+void t_lua_generator::close_generator() {
+  // Close types file
+  f_types_.close();
+  f_consts_.close();
+}
+
+/**
+ * Generate a typedef (essentially a constant)
+ */
+void t_lua_generator::generate_typedef(t_typedef* ttypedef) {
+  f_types_ << endl << endl << indent() << ttypedef->get_symbolic() << " = "
+           << ttypedef->get_type()->get_name();
+}
+
+/**
+ * Generates code for an enumerated type (table)
+ */
+void t_lua_generator::generate_enum(t_enum* tenum) {
+  f_types_ << endl << endl << tenum->get_name() << " = {" << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end();) {
+    int32_t value = (*c_iter)->get_value();
+
+    f_types_ << "  " << (*c_iter)->get_name() << " = " << value;
+    ++c_iter;
+    if (c_iter != constants.end()) {
+      f_types_ << ",";
+    }
+    f_types_ << endl;
+  }
+  f_types_ << "}";
+}
+
+/**
+ * Generate a constant (non-local) value
+ */
+void t_lua_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  f_consts_ << endl << endl << name << " = ";
+  f_consts_ << render_const_value(type, value);
+}
+
+/**
+ * Prints the value of a constant with the given type.
+ */
+string t_lua_generator::render_const_value(t_type* type, t_const_value* value) {
+  std::ostringstream out;
+
+  type = get_true_type(type);
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << "'" << value->get_string() << "'";
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      out << "lualongnumber.new('" << value->get_string() << "')";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    out << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << type->get_name() << " = {" << endl;
+    indent_up();
+
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end();) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+
+      indent(out);
+      out << render_const_value(g_type_string, v_iter->first);
+      out << " = ";
+      out << render_const_value(field_type, v_iter->second);
+      ++v_iter;
+      if (v_iter != val.end()) {
+        out << ",";
+      }
+    }
+
+    out << "}";
+    indent_down();
+  } else if (type->is_map()) {
+    out << type->get_name() << "{" << endl;
+    indent_up();
+
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end();) {
+      indent(out) << "[" << render_const_value(ktype, v_iter->first)
+                  << "] = " << render_const_value(vtype, v_iter->second);
+      ++v_iter;
+      if (v_iter != val.end()) {
+        out << ",";
+      }
+      out << endl;
+    }
+    indent_down();
+    indent(out) << "}";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    out << type->get_name() << " = {" << endl;
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end();) {
+      indent(out);
+      out << "[" << render_const_value(etype, *v_iter) << "]";
+      if (type->is_set()) {
+        out << " = true";
+      } else {
+        out << " = false";
+      }
+      ++v_iter;
+      if (v_iter != val.end()) {
+        out << "," << endl;
+      }
+    }
+    out << "}";
+  }
+  return out.str();
+}
+
+/**
+ * Generate a thrift struct
+ */
+void t_lua_generator::generate_struct(t_struct* tstruct) {
+  generate_lua_struct_definition(f_types_, tstruct, false);
+}
+
+/**
+ * Generate a thrift exception
+ */
+void t_lua_generator::generate_xception(t_struct* txception) {
+  generate_lua_struct_definition(f_types_, txception, true);
+}
+
+/**
+ * Generate a thrift struct or exception (lua table)
+ */
+void t_lua_generator::generate_lua_struct_definition(ofstream& out,
+                                                     t_struct* tstruct,
+                                                     bool is_exception) {
+  vector<t_field*>::const_iterator m_iter;
+  const vector<t_field*>& members = tstruct->get_members();
+
+  indent(out) << endl << endl << tstruct->get_name();
+  if (is_exception) {
+    out << " = TException:new{" << endl << indent() << "  __type = '" << tstruct->get_name() << "'";
+    if (members.size() > 0) {
+      out << ",";
+    }
+    out << endl;
+  } else {
+    out << " = __TObject:new{" << endl;
+  }
+  indent_up();
+  for (m_iter = members.begin(); m_iter != members.end();) {
+    indent(out);
+    out << (*m_iter)->get_name();
+    ++m_iter;
+    if (m_iter != members.end()) {
+      out << "," << endl;
+    }
+  }
+  indent_down();
+  indent(out);
+  out << endl << "}";
+
+  generate_lua_struct_reader(out, tstruct);
+  generate_lua_struct_writer(out, tstruct);
+}
+
+/**
+ * Generate a struct/exception reader
+ */
+void t_lua_generator::generate_lua_struct_reader(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // function
+  indent(out) << endl << endl << "function " << tstruct->get_name() << ":read(iprot)" << endl;
+  indent_up();
+
+  indent(out) << "iprot:readStructBegin()" << endl;
+
+  // while: Read in fields
+  indent(out) << "while true do" << endl;
+  indent_up();
+
+  // if: Check what to read
+  indent(out) << "local fname, ftype, fid = iprot:readFieldBegin()" << endl;
+  indent(out) << "if ftype == TType.STOP then" << endl;
+  indent_up();
+  indent(out) << "break" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent_down();
+    indent(out) << "elseif fid == " << (*f_iter)->get_key() << " then" << endl;
+    indent_up();
+    indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << " then" << endl;
+    indent_up();
+
+    // Read field contents
+    generate_deserialize_field(out, *f_iter, false, "self.");
+
+    indent_down();
+    indent(out) << "else" << endl;
+    indent(out) << "  iprot:skip(ftype)" << endl;
+    indent(out) << "end" << endl;
+  }
+
+  // end if
+  indent_down();
+  indent(out) << "else" << endl;
+  indent(out) << "  iprot:skip(ftype)" << endl;
+  indent(out) << "end" << endl;
+  indent(out) << "iprot:readFieldEnd()" << endl;
+
+  // end while
+  indent_down();
+  indent(out) << "end" << endl;
+  indent(out) << "iprot:readStructEnd()" << endl;
+
+  // end function
+  indent_down();
+  indent(out);
+  out << "end";
+}
+
+/**
+ * Generate a struct/exception writer
+ */
+void t_lua_generator::generate_lua_struct_writer(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // function
+  indent(out) << endl << endl << "function " << tstruct->get_name() << ":write(oprot)" << endl;
+  indent_up();
+
+  indent(out) << "oprot:writeStructBegin('" << tstruct->get_name() << "')" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    // To check element of self whether nil or not.
+    // avoid the value(false) of BOOL is lost.
+    indent(out) << "if self." << (*f_iter)->get_name() << " ~= nil then" << endl;
+    indent_up();
+    indent(out) << "oprot:writeFieldBegin('" << (*f_iter)->get_name() << "', "
+                << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ")"
+                << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "self.");
+
+    indent(out) << "oprot:writeFieldEnd()" << endl;
+    indent_down();
+    indent(out) << "end" << endl;
+  }
+  indent(out) << "oprot:writeFieldStop()" << endl;
+  indent(out) << "oprot:writeStructEnd()" << endl;
+
+  // end function
+  indent_down();
+  indent(out);
+  out << "end";
+}
+
+/**
+ * Generate a thrift service
+ */
+void t_lua_generator::generate_service(t_service* tservice) {
+  // Get output directory
+  string outdir = get_out_dir();
+
+  // Open the file for writing
+  string cur_ns = get_namespace(program_);
+  string f_service_name = outdir + cur_ns + tservice->get_name() + ".lua";
+  f_service_.open(f_service_name.c_str());
+
+  // Headers
+  f_service_ << autogen_comment() << lua_includes();
+  if (gen_requires_) {
+    f_service_ << endl << "require '" << cur_ns << "ttypes'" << endl;
+
+    if (tservice->get_extends() != NULL) {
+      f_service_ << "require '" << get_namespace(tservice->get_extends()->get_program())
+                 << tservice->get_extends()->get_name() << "'" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_client(f_service_, tservice);
+  generate_service_interface(f_service_, tservice);
+  generate_service_processor(f_service_, tservice);
+  generate_service_helpers(f_service_, tservice);
+
+  // Close the file
+  f_service_.close();
+}
+
+void t_lua_generator::generate_service_interface(ofstream& out, t_service* tservice) {
+  string classname = tservice->get_name() + "Iface";
+  t_service* extends_s = tservice->get_extends();
+
+  // Interface object definition
+  out << classname << " = ";
+  if (extends_s) {
+    out << extends_s->get_name() << "Iface:new{" << endl;
+  } else {
+    out << "__TObject:new{" << endl;
+  }
+  out << "  __type = '" << classname << "'" << endl << "}" << endl << endl;
+}
+
+void t_lua_generator::generate_service_client(ofstream& out, t_service* tservice) {
+  string classname = tservice->get_name() + "Client";
+  t_service* extends_s = tservice->get_extends();
+
+  // Client object definition
+  out << classname << " = __TObject.new(";
+  if (extends_s != NULL) {
+    out << extends_s->get_name() << "Client";
+  } else {
+    out << "__TClient";
+  }
+  out << ", {" << endl << "  __type = '" << classname << "'" << endl << "})" << endl;
+
+  // Send/Recv functions
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string sig = function_signature(*f_iter);
+    string funcname = (*f_iter)->get_name();
+
+    // Wrapper function
+    indent(out) << endl << "function " << classname << ":" << sig << endl;
+    indent_up();
+
+    indent(out) << "self:send_" << sig << endl << indent();
+    if (!(*f_iter)->is_oneway()) {
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        out << "return ";
+      }
+      out << "self:recv_" << sig << endl;
+    }
+
+    indent_down();
+    indent(out) << "end" << endl;
+
+    // Send function
+    indent(out) << endl << "function " << classname << ":send_" << sig << endl;
+    indent_up();
+
+    indent(out) << "self.oprot:writeMessageBegin('" << funcname << "', "
+                << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
+                << ", self._seqid)" << endl;
+    indent(out) << "local args = " << funcname << "_args:new{}" << endl;
+
+    // Set the args
+    const vector<t_field*>& args = (*f_iter)->get_arglist()->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    for (fld_iter = args.begin(); fld_iter != args.end(); ++fld_iter) {
+      std::string argname = (*fld_iter)->get_name();
+      indent(out) << "args." << argname << " = " << argname << endl;
+    }
+
+    indent(out) << "args:write(self.oprot)" << endl;
+    indent(out) << "self.oprot:writeMessageEnd()" << endl;
+    indent(out) << "self.oprot.trans:flush()" << endl;
+
+    indent_down();
+    indent(out) << "end" << endl;
+
+    // Recv function
+    if (!(*f_iter)->is_oneway()) {
+      indent(out) << endl << "function " << classname << ":recv_" << sig << endl;
+      indent_up();
+
+      out << indent() << "local fname, mtype, rseqid = self.iprot:"
+          << "readMessageBegin()" << endl << indent() << "if mtype == TMessageType.EXCEPTION then"
+          << endl << indent() << "  local x = TApplicationException:new{}" << endl << indent()
+          << "  x:read(self.iprot)" << endl << indent() << "  self.iprot:readMessageEnd()" << endl
+          << indent() << "  error(x)" << endl << indent() << "end" << endl << indent()
+          << "local result = " << funcname << "_result:new{}" << endl << indent()
+          << "result:read(self.iprot)" << endl << indent() << "self.iprot:readMessageEnd()" << endl;
+
+      // Return the result if it's not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        out << indent() << "if result.success ~= nil then" << endl << indent() << "  return result.success"
+            << endl;
+
+        // Throw custom exceptions
+        const std::vector<t_field*>& xf = (*f_iter)->get_xceptions()->get_members();
+        vector<t_field*>::const_iterator x_iter;
+        for (x_iter = xf.begin(); x_iter != xf.end(); ++x_iter) {
+          out << indent() << "elseif result." << (*x_iter)->get_name() << " then" << endl
+              << indent() << "  error(result." << (*x_iter)->get_name() << ")" << endl;
+        }
+
+        out << indent() << "end" << endl << indent()
+            << "error(TApplicationException:new{errorCode = "
+            << "TApplicationException.MISSING_RESULT})" << endl;
+      }
+
+      indent_down();
+      indent(out) << "end" << endl;
+    }
+  }
+}
+
+void t_lua_generator::generate_service_processor(ofstream& out, t_service* tservice) {
+  string classname = tservice->get_name() + "Processor";
+  t_service* extends_s = tservice->get_extends();
+
+  // Define processor table
+  out << endl << classname << " = __TObject.new(";
+  if (extends_s != NULL) {
+    out << extends_s << "Processor" << endl;
+  } else {
+    out << "__TProcessor" << endl;
+  }
+  out << ", {" << endl << " __type = '" << classname << "'" << endl << "})" << endl;
+
+  // Process function
+  indent(out) << endl << "function " << classname << ":process(iprot, oprot, server_ctx)" << endl;
+  indent_up();
+
+  indent(out) << "local name, mtype, seqid = iprot:readMessageBegin()" << endl;
+  indent(out) << "local func_name = 'process_' .. name" << endl;
+  indent(out) << "if not self[func_name] or ttype(self[func_name]) ~= 'function' then";
+  indent_up();
+  out << endl << indent() << "iprot:skip(TType.STRUCT)" << endl << indent()
+      << "iprot:readMessageEnd()" << endl << indent() << "x = TApplicationException:new{" << endl
+      << indent() << "  errorCode = TApplicationException.UNKNOWN_METHOD" << endl << indent() << "}"
+      << endl << indent() << "oprot:writeMessageBegin(name, TMessageType.EXCEPTION, "
+      << "seqid)" << endl << indent() << "x:write(oprot)" << endl << indent()
+      << "oprot:writeMessageEnd()" << endl << indent() << "oprot.trans:flush()" << endl;
+  indent_down();
+  indent(out) << "else" << endl << indent()
+              << "  self[func_name](self, seqid, iprot, oprot, server_ctx)" << endl << indent()
+              << "end" << endl;
+
+  indent_down();
+  indent(out) << "end" << endl;
+
+  // Generate the process subfunctions
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(out, tservice, *f_iter);
+  }
+}
+
+void t_lua_generator::generate_process_function(ofstream& out,
+                                                t_service* tservice,
+                                                t_function* tfunction) {
+  string classname = tservice->get_name() + "Processor";
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+  string fn_name = tfunction->get_name();
+
+  indent(out) << endl << "function " << classname << ":process_" << fn_name
+              << "(seqid, iprot, oprot, server_ctx)" << endl;
+  indent_up();
+
+  // Read the request
+  out << indent() << "local args = " << argsname << ":new{}" << endl << indent()
+      << "local reply_type = TMessageType.REPLY" << endl << indent() << "args:read(iprot)" << endl
+      << indent() << "iprot:readMessageEnd()" << endl << indent() << "local result = " << resultname
+      << ":new{}" << endl << indent() << "local status, res = pcall(self.handler." << fn_name
+      << ", self.handler";
+
+  // Print arguments
+  t_struct* args = tfunction->get_arglist();
+  if (args->get_members().size() > 0) {
+    out << ", " << argument_list(args, "args.");
+  }
+
+  // Check for errors
+  out << ")" << endl << indent() << "if not status then" << endl << indent()
+      << "  reply_type = TMessageType.EXCEPTION" << endl << indent()
+      << "  result = TApplicationException:new{message = res}" << endl;
+
+  // Handle custom exceptions
+  const std::vector<t_field*>& xf = tfunction->get_xceptions()->get_members();
+  if (xf.size() > 0) {
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xf.begin(); x_iter != xf.end(); ++x_iter) {
+      out << indent() << "elseif ttype(res) == '" << (*x_iter)->get_type()->get_name() << "' then"
+          << endl << indent() << "  result." << (*x_iter)->get_name() << " = res" << endl;
+    }
+  }
+
+  // Set the result and write the reply
+  out << indent() << "else" << endl << indent() << "  result.success = res" << endl << indent()
+      << "end" << endl << indent() << "oprot:writeMessageBegin('" << fn_name << "', reply_type, "
+      << "seqid)" << endl << indent() << "result:write(oprot)" << endl << indent()
+      << "oprot:writeMessageEnd()" << endl << indent() << "oprot.trans:flush()" << endl;
+
+  indent_down();
+  indent(out) << "end" << endl;
+}
+
+// Service helpers
+void t_lua_generator::generate_service_helpers(ofstream& out, t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  out << endl << "-- HELPER FUNCTIONS AND STRUCTURES";
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_lua_struct_definition(out, ts, false);
+    generate_function_helpers(out, *f_iter);
+  }
+}
+
+void t_lua_generator::generate_function_helpers(ofstream& out, t_function* tfunction) {
+  if (!tfunction->is_oneway()) {
+    t_struct result(program_, tfunction->get_name() + "_result");
+    t_field success(tfunction->get_returntype(), "success", 0);
+    if (!tfunction->get_returntype()->is_void()) {
+      result.append(&success);
+    }
+
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& fields = xs->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      result.append(*f_iter);
+    }
+    generate_lua_struct_definition(out, &result, false);
+  }
+}
+
+/**
+ * Deserialize (Read)
+ */
+void t_lua_generator::generate_deserialize_field(ofstream& out,
+                                                 t_field* tfield,
+                                                 bool local,
+                                                 string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, local, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, local, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << (local ? "local " : "") << name << " = iprot:";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << "readString()";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool()";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte()";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16()";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32()";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64()";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble()";
+        break;
+      default:
+        throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32()";
+    }
+    out << endl;
+
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+void t_lua_generator::generate_deserialize_struct(ofstream& out,
+                                                  t_struct* tstruct,
+                                                  bool local,
+                                                  string prefix) {
+  indent(out) << (local ? "local " : "") << prefix << " = " << tstruct->get_name() << ":new{}"
+              << endl << indent() << prefix << ":read(iprot)" << endl;
+}
+
+void t_lua_generator::generate_deserialize_container(ofstream& out,
+                                                     t_type* ttype,
+                                                     bool local,
+                                                     string prefix) {
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_i8, ktype);
+  t_field fvtype(g_type_i8, vtype);
+  t_field fetype(g_type_i8, etype);
+
+  // Declare variables, read header
+  indent(out) << (local ? "local " : "") << prefix << " = {}" << endl;
+  if (ttype->is_map()) {
+    indent(out) << "local " << ktype << ", " << vtype << ", " << size << " = iprot:readMapBegin() "
+                << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "local " << etype << ", " << size << " = iprot:readSetBegin()" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "local " << etype << ", " << size << " = iprot:readListBegin()" << endl;
+  }
+
+  // Deserialize
+  indent(out) << "for _i=1," << size << " do" << endl;
+  indent_up();
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  indent_down();
+  indent(out) << "end" << endl;
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "iprot:readMapEnd()" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot:readSetEnd()" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "iprot:readListEnd()" << endl;
+  }
+}
+
+void t_lua_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  // A map is represented by a table indexable by any lua type
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  generate_deserialize_field(out, &fkey, true);
+  generate_deserialize_field(out, &fval, true);
+
+  indent(out) << prefix << "[" << key << "] = " << val << endl;
+}
+
+void t_lua_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  // A set is represented by a table indexed by the value
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  generate_deserialize_field(out, &felem, true);
+
+  indent(out) << prefix << "[" << elem << "] = " << elem << endl;
+}
+
+void t_lua_generator::generate_deserialize_list_element(ofstream& out,
+                                                        t_list* tlist,
+                                                        string prefix) {
+  // A list is represented by a table indexed by integer values
+  // LUA natively provides all of the functions required to maintain a list
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  generate_deserialize_field(out, &felem, true);
+
+  indent(out) << "table.insert(" << prefix << ", " << elem << ")" << endl;
+}
+
+/**
+ * Serialize (Write)
+ */
+void t_lua_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+  string name = prefix + tfield->get_name();
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << "oprot:";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << "writeString(" << name << ")";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ")";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ")";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ")";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ")";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ")";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ")";
+        break;
+      default:
+        throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ")";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
+           name.c_str(),
+           type->get_name().c_str());
+  }
+}
+
+void t_lua_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << prefix << ":write(oprot)" << endl;
+}
+
+void t_lua_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  // Begin writing
+  if (ttype->is_map()) {
+    indent(out) << "oprot:writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
+                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
+                << "ttable_size(" << prefix << "))" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot:writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
+                << "ttable_size(" << prefix << "))" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot:writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
+                << ", "
+                << "#" << prefix << ")" << endl;
+  }
+
+  // Serialize
+  if (ttype->is_map()) {
+    string kiter = tmp("kiter");
+    string viter = tmp("viter");
+    indent(out) << "for " << kiter << "," << viter << " in pairs(" << prefix << ") do" << endl;
+    indent_up();
+    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+    indent_down();
+    indent(out) << "end" << endl;
+  } else if (ttype->is_set()) {
+    string iter = tmp("iter");
+    indent(out) << "for " << iter << ",_ in pairs(" << prefix << ") do" << endl;
+    indent_up();
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    indent_down();
+    indent(out) << "end" << endl;
+  } else if (ttype->is_list()) {
+    string iter = tmp("iter");
+    indent(out) << "for _," << iter << " in ipairs(" << prefix << ") do" << endl;
+    indent_up();
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    indent_down();
+    indent(out) << "end" << endl;
+  }
+
+  // Finish writing
+  if (ttype->is_map()) {
+    indent(out) << "oprot:writeMapEnd()" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot:writeSetEnd()" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot:writeListEnd()" << endl;
+  }
+}
+
+void t_lua_generator::generate_serialize_map_element(ofstream& out,
+                                                     t_map* tmap,
+                                                     string kiter,
+                                                     string viter) {
+  t_field kfield(tmap->get_key_type(), kiter);
+  generate_serialize_field(out, &kfield, "");
+
+  t_field vfield(tmap->get_val_type(), viter);
+  generate_serialize_field(out, &vfield, "");
+}
+
+void t_lua_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+void t_lua_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ *  Helper rendering functions
+ */
+string t_lua_generator::lua_includes() {
+  if (gen_requires_) {
+    return "\n\nrequire 'Thrift'";
+  } else {
+    return "";
+  }
+}
+
+string t_lua_generator::get_namespace(const t_program* program) {
+  std::string real_module = program->get_namespace("lua");
+  if (real_module.empty()) {
+    return program->get_name() + "_";
+  }
+  return real_module + "_";
+}
+
+string t_lua_generator::function_signature(t_function* tfunction, string prefix) {
+  (void)prefix;
+  std::string ret = tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")";
+  return ret;
+}
+
+string t_lua_generator::argument_list(t_struct* tstruct, string prefix) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  std::string ret = "";
+  for (fld_iter = fields.begin(); fld_iter != fields.end();) {
+    ret += prefix + (*fld_iter)->get_name();
+    ++fld_iter;
+    if (fld_iter != fields.end()) {
+      ret += ", ";
+    }
+  }
+  return ret;
+}
+
+string t_lua_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_list()) {
+    return "TType.LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+THRIFT_REGISTER_GENERATOR(
+    lua,
+    "Lua",
+    "    omit_requires:   Suppress generation of require 'somefile'.\n")


[18/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_d_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_d_generator.cc b/compiler/cpp/src/thrift/generate/t_d_generator.cc
new file mode 100644
index 0000000..4816681
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_d_generator.cc
@@ -0,0 +1,728 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <cassert>
+
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <sys/stat.h>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostream;
+using std::ostringstream;
+using std::set;
+using std::string;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * D code generator.
+ *
+ * generate_*() functions are called by the base class to emit code for the
+ * given entity, print_*() functions write a piece of code to the passed
+ * stream, and render_*() return a string containing the D representation of
+ * the passed entity.
+ */
+class t_d_generator : public t_oop_generator {
+public:
+  t_d_generator(t_program* program,
+                const std::map<string, string>& parsed_options,
+                const string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option d:" + iter->first;
+    }
+
+    out_dir_base_ = "gen-d";
+  }
+
+protected:
+  virtual void init_generator() {
+    // Make output directory
+    MKDIR(get_out_dir().c_str());
+
+    string dir = program_->get_namespace("d");
+    string subdir = get_out_dir();
+    string::size_type loc;
+    while ((loc = dir.find(".")) != string::npos) {
+      subdir = subdir + "/" + dir.substr(0, loc);
+      MKDIR(subdir.c_str());
+      dir = dir.substr(loc + 1);
+    }
+    if (!dir.empty()) {
+      subdir = subdir + "/" + dir;
+      MKDIR(subdir.c_str());
+    }
+
+    package_dir_ = subdir + "/";
+
+    // Make output file
+    string f_types_name = package_dir_ + program_name_ + "_types.d";
+    f_types_.open(f_types_name.c_str());
+
+    // Print header
+    f_types_ << autogen_comment() << "module " << render_package(*program_) << program_name_
+             << "_types;" << endl << endl;
+
+    print_default_imports(f_types_);
+
+    // Include type modules from other imported programs.
+    const vector<t_program*>& includes = program_->get_includes();
+    for (size_t i = 0; i < includes.size(); ++i) {
+      f_types_ << "import " << render_package(*(includes[i])) << includes[i]->get_name()
+               << "_types;" << endl;
+    }
+    if (!includes.empty())
+      f_types_ << endl;
+  }
+
+  virtual void close_generator() {
+    // Close output file
+    f_types_.close();
+  }
+
+  virtual void generate_consts(std::vector<t_const*> consts) {
+    if (!consts.empty()) {
+      string f_consts_name = package_dir_ + program_name_ + "_constants.d";
+      ofstream f_consts;
+      f_consts.open(f_consts_name.c_str());
+
+      f_consts << autogen_comment() << "module " << render_package(*program_) << program_name_
+               << "_constants;" << endl << endl;
+
+      print_default_imports(f_consts);
+
+      f_consts << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl
+               << endl;
+
+      vector<t_const*>::iterator c_iter;
+      for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+        string name = (*c_iter)->get_name();
+        t_type* type = (*c_iter)->get_type();
+        indent(f_consts) << "immutable(" << render_type_name(type) << ") " << name << ";" << endl;
+      }
+
+      f_consts << endl << "static this() {" << endl;
+      indent_up();
+
+      bool first = true;
+      for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+        if (first) {
+          first = false;
+        } else {
+          f_consts << endl;
+        }
+        t_type* type = (*c_iter)->get_type();
+        indent(f_consts) << (*c_iter)->get_name() << " = ";
+        if (!is_immutable_type(type)) {
+          f_consts << "cast(immutable(" << render_type_name(type) << ")) ";
+        }
+        f_consts << render_const_value(type, (*c_iter)->get_value()) << ";" << endl;
+      }
+      indent_down();
+      indent(f_consts) << "}" << endl;
+    }
+  }
+
+  virtual void generate_typedef(t_typedef* ttypedef) {
+    f_types_ << indent() << "alias " << render_type_name(ttypedef->get_type()) << " "
+             << ttypedef->get_symbolic() << ";" << endl << endl;
+  }
+
+  virtual void generate_enum(t_enum* tenum) {
+    vector<t_enum_value*> constants = tenum->get_constants();
+
+    string enum_name = tenum->get_name();
+    f_types_ << indent() << "enum " << enum_name << " {" << endl;
+
+    indent_up();
+
+    vector<t_enum_value*>::const_iterator c_iter;
+    bool first = true;
+    for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_types_ << "," << endl;
+      }
+      indent(f_types_) << (*c_iter)->get_name();
+      f_types_ << " = " << (*c_iter)->get_value();
+    }
+
+    f_types_ << endl;
+    indent_down();
+    indent(f_types_) << "}" << endl;
+
+    f_types_ << endl;
+  }
+
+  virtual void generate_struct(t_struct* tstruct) {
+    print_struct_definition(f_types_, tstruct, false);
+  }
+
+  virtual void generate_xception(t_struct* txception) {
+    print_struct_definition(f_types_, txception, true);
+  }
+
+  virtual void generate_service(t_service* tservice) {
+    string svc_name = tservice->get_name();
+
+    // Service implementation file includes
+    string f_servicename = package_dir_ + svc_name + ".d";
+    std::ofstream f_service;
+    f_service.open(f_servicename.c_str());
+    f_service << autogen_comment() << "module " << render_package(*program_) << svc_name << ";"
+              << endl << endl;
+
+    print_default_imports(f_service);
+
+    f_service << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl;
+
+    t_service* extends_service = tservice->get_extends();
+    if (extends_service != NULL) {
+      f_service << "import " << render_package(*(extends_service->get_program()))
+                << extends_service->get_name() << ";" << endl;
+    }
+
+    f_service << endl;
+
+    string extends = "";
+    if (tservice->get_extends() != NULL) {
+      extends = " : " + render_type_name(tservice->get_extends());
+    }
+
+    f_service << indent() << "interface " << svc_name << extends << " {" << endl;
+    indent_up();
+
+    // Collect all the exception types service methods can throw so we can
+    // emit the necessary aliases later.
+    set<t_type*> exception_types;
+
+    // Print the method signatures.
+    vector<t_function*> functions = tservice->get_functions();
+    vector<t_function*>::iterator fn_iter;
+    for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
+      f_service << indent();
+      print_function_signature(f_service, *fn_iter);
+      f_service << ";" << endl;
+
+      const vector<t_field*>& exceptions = (*fn_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator ex_iter;
+      for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) {
+        exception_types.insert((*ex_iter)->get_type());
+      }
+    }
+
+    // Alias the exception types into the current scope.
+    if (!exception_types.empty())
+      f_service << endl;
+    set<t_type*>::const_iterator et_iter;
+    for (et_iter = exception_types.begin(); et_iter != exception_types.end(); ++et_iter) {
+      indent(f_service) << "alias " << render_package(*(*et_iter)->get_program())
+                        << (*et_iter)->get_program()->get_name() << "_types"
+                        << "." << (*et_iter)->get_name() << " " << (*et_iter)->get_name() << ";"
+                        << endl;
+    }
+
+    // Write the method metadata.
+    ostringstream meta;
+    indent_up();
+    bool first = true;
+    for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
+      if ((*fn_iter)->get_arglist()->get_members().empty()
+          && (*fn_iter)->get_xceptions()->get_members().empty() && !(*fn_iter)->is_oneway()) {
+        continue;
+      }
+
+      if (first) {
+        first = false;
+      } else {
+        meta << ",";
+      }
+
+      meta << endl << indent() << "TMethodMeta(`" << (*fn_iter)->get_name() << "`, " << endl;
+      indent_up();
+      indent(meta) << "[";
+
+      bool first = true;
+      const vector<t_field*>& params = (*fn_iter)->get_arglist()->get_members();
+      vector<t_field*>::const_iterator p_iter;
+      for (p_iter = params.begin(); p_iter != params.end(); ++p_iter) {
+        if (first) {
+          first = false;
+        } else {
+          meta << ", ";
+        }
+
+        meta << "TParamMeta(`" << (*p_iter)->get_name() << "`, " << (*p_iter)->get_key();
+
+        t_const_value* cv = (*p_iter)->get_value();
+        if (cv != NULL) {
+          meta << ", q{" << render_const_value((*p_iter)->get_type(), cv) << "}";
+        }
+        meta << ")";
+      }
+
+      meta << "]";
+
+      if (!(*fn_iter)->get_xceptions()->get_members().empty() || (*fn_iter)->is_oneway()) {
+        meta << "," << endl << indent() << "[";
+
+        bool first = true;
+        const vector<t_field*>& exceptions = (*fn_iter)->get_xceptions()->get_members();
+        vector<t_field*>::const_iterator ex_iter;
+        for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) {
+          if (first) {
+            first = false;
+          } else {
+            meta << ", ";
+          }
+
+          meta << "TExceptionMeta(`" << (*ex_iter)->get_name() << "`, " << (*ex_iter)->get_key()
+               << ", `" << (*ex_iter)->get_type()->get_name() << "`)";
+        }
+
+        meta << "]";
+      }
+
+      if ((*fn_iter)->is_oneway()) {
+        meta << "," << endl << indent() << "TMethodType.ONEWAY";
+      }
+
+      indent_down();
+      meta << endl << indent() << ")";
+    }
+    indent_down();
+
+    string meta_str(meta.str());
+    if (!meta_str.empty()) {
+      f_service << endl << indent() << "enum methodMeta = [" << meta_str << endl << indent() << "];"
+                << endl;
+    }
+
+    indent_down();
+    indent(f_service) << "}" << endl;
+
+    // Server skeleton generation.
+    string f_skeletonname = package_dir_ + svc_name + "_server.skeleton.d";
+    std::ofstream f_skeleton;
+    f_skeleton.open(f_skeletonname.c_str());
+    print_server_skeleton(f_skeleton, tservice);
+    f_skeleton.close();
+  }
+
+private:
+  /**
+   * Writes a server skeleton for the passed service to out.
+   */
+  void print_server_skeleton(ostream& out, t_service* tservice) {
+    string svc_name = tservice->get_name();
+
+    out << "/*" << endl
+        << " * This auto-generated skeleton file illustrates how to build a server. If you" << endl
+        << " * intend to customize it, you should edit a copy with another file name to " << endl
+        << " * avoid overwriting it when running the generator again." << endl << " */" << endl
+        << "module " << render_package(*tservice->get_program()) << svc_name << "_server;" << endl
+        << endl << "import std.stdio;" << endl << "import thrift.codegen.processor;" << endl
+        << "import thrift.protocol.binary;" << endl << "import thrift.server.simple;" << endl
+        << "import thrift.server.transport.socket;" << endl << "import thrift.transport.buffered;"
+        << endl << "import thrift.util.hashset;" << endl << endl << "import "
+        << render_package(*tservice->get_program()) << svc_name << ";" << endl << "import "
+        << render_package(*get_program()) << program_name_ << "_types;" << endl << endl << endl
+        << "class " << svc_name << "Handler : " << svc_name << " {" << endl;
+
+    indent_up();
+    out << indent() << "this() {" << endl << indent() << "  // Your initialization goes here."
+        << endl << indent() << "}" << endl << endl;
+
+    vector<t_function*> functions = tservice->get_functions();
+    vector<t_function*>::iterator f_iter;
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      out << indent();
+      print_function_signature(out, *f_iter);
+      out << " {" << endl;
+
+      indent_up();
+
+      out << indent() << "// Your implementation goes here." << endl << indent() << "writeln(\""
+          << (*f_iter)->get_name() << " called\");" << endl;
+
+      t_base_type* rt = (t_base_type*)(*f_iter)->get_returntype();
+      if (rt->get_base() != t_base_type::TYPE_VOID) {
+        indent(out) << "return typeof(return).init;" << endl;
+      }
+
+      indent_down();
+
+      out << indent() << "}" << endl << endl;
+    }
+
+    indent_down();
+    out << "}" << endl << endl;
+
+    out << indent() << "void main() {" << endl;
+    indent_up();
+    out << indent() << "auto protocolFactory = new TBinaryProtocolFactory!();" << endl << indent()
+        << "auto processor = new TServiceProcessor!" << svc_name << "(new " << svc_name
+        << "Handler);" << endl << indent() << "auto serverTransport = new TServerSocket(9090);"
+        << endl << indent() << "auto transportFactory = new TBufferedTransportFactory;" << endl
+        << indent() << "auto server = new TSimpleServer(" << endl << indent()
+        << "  processor, serverTransport, transportFactory, protocolFactory);" << endl << indent()
+        << "server.serve();" << endl;
+    indent_down();
+    out << "}" << endl;
+  }
+
+  /**
+   * Writes the definition of a struct or an exception type to out.
+   */
+  void print_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) {
+    const vector<t_field*>& members = tstruct->get_members();
+
+    if (is_exception) {
+      indent(out) << "class " << tstruct->get_name() << " : TException {" << endl;
+    } else {
+      indent(out) << "struct " << tstruct->get_name() << " {" << endl;
+    }
+    indent_up();
+
+    // Declare all fields.
+    vector<t_field*>::const_iterator m_iter;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      indent(out) << render_type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name() << ";"
+                  << endl;
+    }
+
+    if (!members.empty())
+      indent(out) << endl;
+    indent(out) << "mixin TStructHelpers!(";
+
+    if (!members.empty()) {
+      // If there are any fields, construct the TFieldMeta array to pass to
+      // TStructHelpers. We can't just pass an empty array if not because []
+      // doesn't pass the TFieldMeta[] constraint.
+      out << "[";
+      indent_up();
+
+      bool first = true;
+      vector<t_field*>::const_iterator m_iter;
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        if (first) {
+          first = false;
+        } else {
+          out << ",";
+        }
+        out << endl;
+
+        indent(out) << "TFieldMeta(`" << (*m_iter)->get_name() << "`, " << (*m_iter)->get_key();
+
+        t_const_value* cv = (*m_iter)->get_value();
+        t_field::e_req req = (*m_iter)->get_req();
+        out << ", " << render_req(req);
+        if (cv != NULL) {
+          out << ", q{" << render_const_value((*m_iter)->get_type(), cv) << "}";
+        }
+        out << ")";
+      }
+
+      indent_down();
+      out << endl << indent() << "]";
+    }
+
+    out << ");" << endl;
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+
+  /**
+   * Prints the D function signature (including return type) for the given
+   * method.
+   */
+  void print_function_signature(ostream& out, t_function* fn) {
+    out << render_type_name(fn->get_returntype()) << " " << fn->get_name() << "(";
+
+    const vector<t_field*>& fields = fn->get_arglist()->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        out << ", ";
+      }
+      out << render_type_name((*f_iter)->get_type(), true) << " " << (*f_iter)->get_name();
+    }
+
+    out << ")";
+  }
+
+  /**
+   * Returns the D representation of value. The result is guaranteed to be a
+   * single expression; for complex types, immediately called delegate
+   * literals are used to achieve this.
+   */
+  string render_const_value(t_type* type, t_const_value* value) {
+    // Resolve any typedefs.
+    type = get_true_type(type);
+
+    ostringstream out;
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_STRING:
+        out << '"' << get_escaped_string(value) << '"';
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << ((value->get_integer() > 0) ? "true" : "false");
+        break;
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+        out << "cast(" << render_type_name(type) << ")" << value->get_integer();
+        break;
+      case t_base_type::TYPE_I32:
+        out << value->get_integer();
+        break;
+      case t_base_type::TYPE_I64:
+        out << value->get_integer() << "L";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        if (value->get_type() == t_const_value::CV_INTEGER) {
+          out << value->get_integer();
+        } else {
+          out << value->get_double();
+        }
+        break;
+      default:
+        throw "Compiler error: No const of base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "cast(" << render_type_name(type) << ")" << value->get_integer();
+    } else {
+      out << "{" << endl;
+      indent_up();
+
+      indent(out) << render_type_name(type) << " v;" << endl;
+      if (type->is_struct() || type->is_xception()) {
+        indent(out) << "v = " << (type->is_xception() ? "new " : "") << render_type_name(type)
+                    << "();" << endl;
+
+        const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+        vector<t_field*>::const_iterator f_iter;
+        const map<t_const_value*, t_const_value*>& val = value->get_map();
+        map<t_const_value*, t_const_value*>::const_iterator v_iter;
+        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+          t_type* field_type = NULL;
+          for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+            if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+              field_type = (*f_iter)->get_type();
+            }
+          }
+          if (field_type == NULL) {
+            throw "Type error: " + type->get_name() + " has no field "
+                + v_iter->first->get_string();
+          }
+          string val = render_const_value(field_type, v_iter->second);
+          indent(out) << "v.set!`" << v_iter->first->get_string() << "`(" << val << ");" << endl;
+        }
+      } else if (type->is_map()) {
+        t_type* ktype = ((t_map*)type)->get_key_type();
+        t_type* vtype = ((t_map*)type)->get_val_type();
+        const map<t_const_value*, t_const_value*>& val = value->get_map();
+        map<t_const_value*, t_const_value*>::const_iterator v_iter;
+        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+          string key = render_const_value(ktype, v_iter->first);
+          string val = render_const_value(vtype, v_iter->second);
+          indent(out) << "v[";
+          if (!is_immutable_type(ktype)) {
+            out << "cast(immutable(" << render_type_name(ktype) << "))";
+          }
+          out << key << "] = " << val << ";" << endl;
+        }
+      } else if (type->is_list()) {
+        t_type* etype = ((t_list*)type)->get_elem_type();
+        const vector<t_const_value*>& val = value->get_list();
+        vector<t_const_value*>::const_iterator v_iter;
+        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+          string val = render_const_value(etype, *v_iter);
+          indent(out) << "v ~= " << val << ";" << endl;
+        }
+      } else if (type->is_set()) {
+        t_type* etype = ((t_set*)type)->get_elem_type();
+        const vector<t_const_value*>& val = value->get_list();
+        vector<t_const_value*>::const_iterator v_iter;
+        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+          string val = render_const_value(etype, *v_iter);
+          indent(out) << "v ~= " << val << ";" << endl;
+        }
+      } else {
+        throw "Compiler error: Invalid type in render_const_value: " + type->get_name();
+      }
+      indent(out) << "return v;" << endl;
+
+      indent_down();
+      indent(out) << "}()";
+    }
+
+    return out.str();
+  }
+
+  /**
+   * Returns the D package to which modules for program are written (with a
+   * trailing dot, if not empty).
+   */
+  string render_package(const t_program& program) const {
+    string package = program.get_namespace("d");
+    if (package.size() == 0)
+      return "";
+    return package + ".";
+  }
+
+  /**
+   * Returns the name of the D repesentation of ttype.
+   *
+   * If isArg is true, a const reference to the type will be returned for
+   * structs.
+   */
+  string render_type_name(const t_type* ttype, bool isArg = false) const {
+    if (ttype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        return "void";
+      case t_base_type::TYPE_STRING:
+        return "string";
+      case t_base_type::TYPE_BOOL:
+        return "bool";
+      case t_base_type::TYPE_I8:
+        return "byte";
+      case t_base_type::TYPE_I16:
+        return "short";
+      case t_base_type::TYPE_I32:
+        return "int";
+      case t_base_type::TYPE_I64:
+        return "long";
+      case t_base_type::TYPE_DOUBLE:
+        return "double";
+      default:
+        throw "Compiler error: No D type name for base type " + t_base_type::t_base_name(tbase);
+      }
+    }
+
+    if (ttype->is_container()) {
+      t_container* tcontainer = (t_container*)ttype;
+      if (tcontainer->has_cpp_name()) {
+        return tcontainer->get_cpp_name();
+      } else if (ttype->is_map()) {
+        t_map* tmap = (t_map*)ttype;
+        t_type* ktype = tmap->get_key_type();
+
+        string name = render_type_name(tmap->get_val_type()) + "[";
+        if (!is_immutable_type(ktype)) {
+          name += "immutable(";
+        }
+        name += render_type_name(ktype);
+        if (!is_immutable_type(ktype)) {
+          name += ")";
+        }
+        name += "]";
+        return name;
+      } else if (ttype->is_set()) {
+        t_set* tset = (t_set*)ttype;
+        return "HashSet!(" + render_type_name(tset->get_elem_type()) + ")";
+      } else if (ttype->is_list()) {
+        t_list* tlist = (t_list*)ttype;
+        return render_type_name(tlist->get_elem_type()) + "[]";
+      }
+    }
+
+    if (ttype->is_struct() && isArg) {
+      return "ref const(" + ttype->get_name() + ")";
+    } else {
+      return ttype->get_name();
+    }
+  }
+
+  /**
+   * Returns the D TReq enum member corresponding to req.
+   */
+  string render_req(t_field::e_req req) const {
+    switch (req) {
+    case t_field::T_OPT_IN_REQ_OUT:
+      return "TReq.OPT_IN_REQ_OUT";
+    case t_field::T_OPTIONAL:
+      return "TReq.OPTIONAL";
+    case t_field::T_REQUIRED:
+      return "TReq.REQUIRED";
+    default: {
+      std::stringstream ss;
+      ss << "Compiler error: Invalid requirement level " << req;
+      throw ss.str();
+    }
+    }
+  }
+
+  /**
+   * Writes the default list of imports (which are written to every generated
+   * module) to f.
+   */
+  void print_default_imports(ostream& out) {
+    indent(out) << "import thrift.base;" << endl << "import thrift.codegen.base;" << endl
+                << "import thrift.util.hashset;" << endl << endl;
+  }
+
+  /**
+   * Returns whether type is �intrinsically immutable�, in the sense that
+   * a value of that type is implicitly castable to immutable(type), and it is
+   * allowed for AA keys without an immutable() qualifier.
+   */
+  bool is_immutable_type(t_type* type) const {
+    t_type* ttype = get_true_type(type);
+    return ttype->is_base_type() || ttype->is_enum();
+  }
+
+  /*
+   * File streams, stored here to avoid passing them as parameters to every
+   * function.
+   */
+  ofstream f_types_;
+  ofstream f_header_;
+
+  string package_dir_;
+};
+
+THRIFT_REGISTER_GENERATOR(d, "D", "")


[24/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin.cc b/compiler/cpp/src/plugin/plugin.cc
deleted file mode 100644
index d969f50..0000000
--- a/compiler/cpp/src/plugin/plugin.cc
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include "plugin/plugin.h"
-
-#ifdef _WIN32
-#include <fcntl.h>
-#include <io.h>
-#endif
-
-#include <cassert>
-#include <iostream>
-
-#include <boost/bind.hpp>
-#include <boost/range/adaptor/map.hpp>
-#include <boost/range/algorithm/for_each.hpp>
-#include <boost/smart_ptr.hpp>
-
-#include "generate/t_generator.h"
-#include "plugin/type_util.h"
-#include "thrift/protocol/TBinaryProtocol.h"
-#include "thrift/transport/TBufferTransports.h"
-#include "thrift/transport/TFDTransport.h"
-
-#include "plugin/plugin_types.h"
-
-namespace apache {
-namespace thrift {
-namespace plugin {
-
-using apache::thrift::protocol::TBinaryProtocol;
-using apache::thrift::transport::TFDTransport;
-using apache::thrift::transport::TFramedTransport;
-
-#define THRIFT_CONVERT_FORWARD(from_type)                                                          \
-  template <>                                                                                      \
-  typename ToType<from_type>::type* convert_forward<from_type>(const from_type& from)
-
-#define THRIFT_CONVERT_COMPLETE_DECL(from_type)                                                    \
-  template <>                                                                                      \
-  void convert(const from_type& from, ToType<from_type>::type* to)
-
-#define THRIFT_CONVERT_UNARY_DECL(from_type)                                                       \
-  template <>                                                                                      \
-  typename ToType<from_type>::type* convert<from_type>(const from_type& from)
-
-#define THRIFT_CONVERSION_DECL(from_type)                                                          \
-  THRIFT_CONVERT_FORWARD(from_type);                                                               \
-  THRIFT_CONVERT_COMPLETE_DECL(from_type);                                                         \
-  THRIFT_CONVERT_UNARY_DECL(from_type)
-
-#define THRIFT_CONVERT_COMPLETE(from_type)                                                         \
-  THRIFT_CONVERSION_DECL(from_type) {                                                              \
-    ToType<from_type>::type* to = convert_forward(from);                                           \
-    convert(from, to);                                                                             \
-    return to;                                                                                     \
-  }                                                                                                \
-  THRIFT_CONVERT_COMPLETE_DECL(from_type)
-
-#define THRIFT_CONVERSION(from_type, ...)                                                          \
-  THRIFT_CONVERT_FORWARD(from_type) {                                                              \
-    (void)from;                                                                                    \
-    return new ToType<from_type>::type(__VA_ARGS__);                                               \
-  }                                                                                                \
-  THRIFT_CONVERT_COMPLETE(from_type)
-
-#define THRIFT_ASSIGN_DOC()                                                                        \
-  do {                                                                                             \
-    if (from.__isset.doc)                                                                          \
-      to->set_doc(from.doc);                                                                       \
-  } while (0)
-
-#define THRIFT_ASSIGN_ANNOTATIONS()                                                                \
-  THRIFT_ASSIGN_DOC();                                                                             \
-  do {                                                                                             \
-    if (from.__isset.annotations)                                                                  \
-      to->annotations_ = from.annotations;                                                         \
-  } while (0)
-
-#define THRIFT_ASSIGN_METADATA()                                                                   \
-  do {                                                                                             \
-    to->set_name(from.metadata.name);                                                              \
-    if (from.metadata.__isset.doc)                                                                 \
-      to->set_doc(from.metadata.doc);                                                              \
-    if (from.metadata.__isset.annotations)                                                         \
-      to->annotations_ = from.metadata.annotations;                                                \
-  } while (0)
-
-::t_program* g_program = 0;
-
-template <typename C, typename S>
-struct TypeCache {
-  C* operator[](const int64_t& k) {
-    typename std::map<int64_t, C*>::iterator it = cache.find(k);
-    if (it != cache.end()) {
-      return it->second;
-    } else {
-      typename std::map<int64_t, S>::const_iterator cit = source->find(k);
-      if (cit == source->end()) {
-        throw ThriftPluginError("Type not found");
-      }
-      return (cache)[k] = convert_forward(cit->second);
-    }
-  }
-
-  void compileAll() {
-    boost::for_each(*source | boost::adaptors::map_keys,
-                    boost::bind(&TypeCache::compile, this, _1));
-  }
-
-  std::map<int64_t, S> const* source;
-
-protected:
-  std::map<int64_t, C*> cache;
-
-private:
-  void compile(const int64_t& k) {
-    typename std::map<int64_t, S>::const_iterator cit = source->find(k);
-    if (cit == source->end()) {
-      throw ThriftPluginError("Type not found ");
-    }
-    convert(cit->second, (*this)[k]);
-  }
-};
-std::map<int64_t, ::t_program*> g_program_cache;
-TypeCache< ::t_type, t_type> g_type_cache;
-TypeCache< ::t_const, t_const> g_const_cache;
-TypeCache< ::t_service, t_service> g_service_cache;
-
-void set_global_cache(const TypeRegistry& from) {
-  g_type_cache.source = &from.types;
-  g_const_cache.source = &from.constants;
-  g_service_cache.source = &from.services;
-
-  g_type_cache.compileAll();
-  g_const_cache.compileAll();
-  g_service_cache.compileAll();
-}
-
-template <typename T>
-T* resolve_type(int64_t name) {
-  return reinterpret_cast<T*>(g_type_cache[name]);
-}
-
-::t_const* resolve_const(int64_t name) {
-  return g_const_cache[name];
-}
-
-::t_service* resolve_service(int64_t name) {
-  return g_service_cache[name];
-}
-
-THRIFT_CONVERT_FORWARD(t_base_type) {
-#define T_BASETYPE_CASE(type)                                                                      \
-  case t_base::TYPE_##type:                                                                        \
-    t = ::t_base_type::TYPE_##type;                                                                \
-    break
-
-  ::t_base_type::t_base t = ::t_base_type::TYPE_VOID;
-  bool is_binary = false;
-  switch (from.value) {
-    T_BASETYPE_CASE(VOID);
-    T_BASETYPE_CASE(STRING);
-    T_BASETYPE_CASE(BOOL);
-    T_BASETYPE_CASE(I8);
-    T_BASETYPE_CASE(I16);
-    T_BASETYPE_CASE(I32);
-    T_BASETYPE_CASE(I64);
-    T_BASETYPE_CASE(DOUBLE);
-  case t_base::TYPE_BINARY:
-    t = ::t_base_type::TYPE_STRING;
-    is_binary = true;
-    break;
-  }
-  ::t_base_type* to = new ::t_base_type(from.metadata.name, t);
-  to->set_binary(is_binary);
-  return to;
-#undef T_BASETYPE_CASE
-}
-THRIFT_CONVERT_COMPLETE(t_base_type) {
-  THRIFT_ASSIGN_METADATA();
-}
-
-THRIFT_CONVERT_FORWARD(t_typedef) {
-  ::t_typedef* to;
-  if (from.forward) {
-    to = new ::t_typedef(g_program_cache[from.metadata.program_id], from.symbolic, true);
-  } else {
-    to = new ::t_typedef(g_program_cache[from.metadata.program_id],
-                         resolve_type< ::t_type>(from.type), from.symbolic);
-  }
-  return to;
-}
-THRIFT_CONVERT_COMPLETE(t_typedef) {
-  THRIFT_ASSIGN_METADATA();
-}
-THRIFT_CONVERSION(t_enum_value, from.name, from.value) {
-  assert(to);
-  THRIFT_ASSIGN_ANNOTATIONS();
-}
-THRIFT_CONVERSION(t_enum, g_program_cache[from.metadata.program_id]) {
-  assert(to);
-  THRIFT_ASSIGN_METADATA();
-  boost::for_each(from.constants | boost::adaptors::transformed(convert<t_enum_value>),
-                  boost::bind(&::t_enum::append, to, _1));
-}
-THRIFT_CONVERSION(t_list, resolve_type< ::t_type>(from.elem_type)) {
-  assert(to);
-  THRIFT_ASSIGN_METADATA();
-  if (from.__isset.cpp_name)
-    to->set_cpp_name(from.cpp_name);
-}
-THRIFT_CONVERSION(t_set, resolve_type< ::t_type>(from.elem_type)) {
-  assert(to);
-  THRIFT_ASSIGN_METADATA();
-  if (from.__isset.cpp_name)
-    to->set_cpp_name(from.cpp_name);
-}
-THRIFT_CONVERSION(t_map,
-                  resolve_type< ::t_type>(from.key_type),
-                  resolve_type< ::t_type>(from.val_type)) {
-  assert(to);
-  THRIFT_ASSIGN_METADATA();
-  if (from.__isset.cpp_name)
-    to->set_cpp_name(from.cpp_name);
-}
-THRIFT_CONVERSION(t_const_value, ) {
-#define T_CONST_VALUE_CASE(type)                                                                   \
-  if (from.__isset.type##_val)                                                                     \
-  to->set_##type(from.type##_val)
-
-  assert(to);
-  if (from.__isset.map_val) {
-    to->set_map();
-    for (std::map<t_const_value, t_const_value>::const_iterator it = from.map_val.begin();
-         it != from.map_val.end(); it++) {
-      to->add_map(convert(it->first), convert(it->second));
-    }
-  } else if (from.__isset.list_val) {
-    to->set_list();
-    boost::for_each(from.list_val | boost::adaptors::transformed(&convert<t_const_value>),
-                    boost::bind(&::t_const_value::add_list, to, _1));
-  } else
-    T_CONST_VALUE_CASE(string);
-  else T_CONST_VALUE_CASE(integer);
-  else T_CONST_VALUE_CASE(double);
-  else {
-    T_CONST_VALUE_CASE(identifier);
-    if (from.__isset.enum_val)
-      to->set_enum(resolve_type< ::t_enum>(from.enum_val));
-  }
-#undef T_CONST_VALUE_CASE
-}
-THRIFT_CONVERSION(t_field, resolve_type< ::t_type>(from.type), from.name, from.key) {
-  assert(to);
-  THRIFT_ASSIGN_ANNOTATIONS();
-  to->set_reference(from.reference);
-  to->set_req(static_cast< ::t_field::e_req>(from.req));
-  if (from.__isset.value) {
-    to->set_value(convert(from.value));
-  }
-}
-THRIFT_CONVERSION(t_struct, g_program_cache[from.metadata.program_id]) {
-  assert(to);
-  THRIFT_ASSIGN_METADATA();
-  to->set_union(from.is_union);
-  to->set_xception(from.is_xception);
-  boost::for_each(from.members | boost::adaptors::transformed(convert<t_field>),
-                  boost::bind(&::t_struct::append, to, _1));
-}
-THRIFT_CONVERSION(t_const,
-                  resolve_type< ::t_type>(from.type),
-                  from.name,
-                  convert<t_const_value>(from.value)) {
-  assert(to);
-  THRIFT_ASSIGN_DOC();
-}
-
-THRIFT_CONVERSION(t_function,
-                  resolve_type< ::t_type>(from.returntype),
-                  from.name,
-                  resolve_type< ::t_struct>(from.arglist),
-                  resolve_type< ::t_struct>(from.xceptions),
-                  from.is_oneway) {
-  assert(to);
-  THRIFT_ASSIGN_DOC();
-}
-
-THRIFT_CONVERSION(t_service, g_program_cache[from.metadata.program_id]) {
-  assert(to);
-  assert(from.metadata.program_id);
-  assert(g_program_cache[from.metadata.program_id]);
-  THRIFT_ASSIGN_METADATA();
-
-  boost::for_each(from.functions | boost::adaptors::transformed(convert<t_function>),
-                  boost::bind(&::t_service::add_function, to, _1));
-
-  if (from.__isset.extends_)
-    to->set_extends(resolve_service(from.extends_));
-}
-
-THRIFT_CONVERT_FORWARD(t_type) {
-#define T_TYPE_CASE_FW_T(case, type)                                                               \
-  if (from.__isset.case##_val)                                                                     \
-  return convert_forward<type>(from.case##_val)
-#define T_TYPE_CASE_FW(case) T_TYPE_CASE_FW_T(case, t_##case)
-
-  T_TYPE_CASE_FW(base_type);
-  T_TYPE_CASE_FW(typedef);
-  T_TYPE_CASE_FW(enum);
-  T_TYPE_CASE_FW(struct);
-  T_TYPE_CASE_FW_T(xception, t_struct);
-  T_TYPE_CASE_FW(list);
-  T_TYPE_CASE_FW(set);
-  T_TYPE_CASE_FW(map);
-  T_TYPE_CASE_FW(service);
-  throw ThriftPluginError("Invalid data: Type union has no value.");
-#undef T_TYPE_CASE_FW_T
-#undef T_TYPE_CASE_FW
-}
-THRIFT_CONVERT_COMPLETE(t_type) {
-#define T_TYPE_CASE_T(case, type)                                                                  \
-  else if (from.__isset.case##_val)                                                                \
-      convert<type, ::type>(from.case##_val, reinterpret_cast< ::type*>(to))
-#define T_TYPE_CASE(case) T_TYPE_CASE_T(case, t_##case)
-
-  if (false) {
-  }
-  T_TYPE_CASE(base_type);
-  T_TYPE_CASE(typedef);
-  T_TYPE_CASE(enum);
-  T_TYPE_CASE(struct);
-  T_TYPE_CASE_T(xception, t_struct);
-  T_TYPE_CASE(list);
-  T_TYPE_CASE(set);
-  T_TYPE_CASE(map);
-  T_TYPE_CASE(service);
-  else {
-    throw ThriftPluginError("Invalid data: Type union has no value.");
-  }
-#undef T_TYPE_CASE_T
-#undef T_TYPE_CASE
-}
-
-THRIFT_CONVERSION(t_scope, ) {
-  assert(to);
-#define T_SCOPE_RESOLVE(type, name, a)                                                             \
-  for (std::vector<int64_t>::const_iterator it = from.name##s.begin(); it != from.name##s.end();   \
-       it++) {                                                                                     \
-    ::t_##type* t = resolve_##type a(*it);                                                         \
-    to->add_##name(t->get_name(), t);                                                              \
-  }
-  T_SCOPE_RESOLVE(type, type, < ::t_type>);
-  T_SCOPE_RESOLVE(const, constant, );
-  T_SCOPE_RESOLVE(service, service, );
-#undef T_SCOPE_RESOLVE
-}
-
-THRIFT_CONVERT_FORWARD(t_program) {
-  ::t_program* to = new ::t_program(from.path, from.name);
-  for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
-       it++) {
-    to->add_include(convert_forward(*it));
-  }
-  g_program_cache[from.program_id] = to;
-  return to;
-}
-THRIFT_CONVERT_COMPLETE(t_program) {
-  assert(to);
-  g_program = to;
-  convert<t_scope, ::t_scope>(from.scope, to->scope());
-  THRIFT_ASSIGN_DOC();
-
-  to->set_out_path(from.out_path, from.out_path_is_absolute);
-
-  boost::for_each(from.typedefs | boost::adaptors::transformed(&resolve_type< ::t_typedef>),
-                  boost::bind(&::t_program::add_typedef, to, _1));
-  boost::for_each(from.enums | boost::adaptors::transformed(&resolve_type< ::t_enum>),
-                  boost::bind(&::t_program::add_enum, to, _1));
-  for (std::vector<int64_t>::const_iterator it = from.objects.begin(); it != from.objects.end();
-       it++) {
-    ::t_struct* t2 = resolve_type< ::t_struct>(*it);
-    if (t2->is_xception()) {
-      to->add_xception(t2);
-    } else {
-      to->add_struct(t2);
-    }
-  }
-  boost::for_each(from.consts | boost::adaptors::transformed(&resolve_const),
-                  boost::bind(&::t_program::add_const, to, _1));
-  boost::for_each(from.services | boost::adaptors::transformed(&resolve_service),
-                  boost::bind(&::t_program::add_service, to, _1));
-
-  for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
-       it++) {
-    convert(*it, g_program_cache[it->program_id]);
-  }
-  std::for_each(from.c_includes.begin(), from.c_includes.end(),
-                boost::bind(&::t_program::add_c_include, to, _1));
-  std::for_each(from.cpp_includes.begin(), from.cpp_includes.end(),
-                boost::bind(&::t_program::add_cpp_include, to, _1));
-  for (std::map<std::string, std::string>::const_iterator it = from.namespaces.begin();
-       it != from.namespaces.end(); it++) {
-    to->set_namespace(it->first, it->second);
-  }
-
-  to->set_include_prefix(from.include_prefix);
-  to->set_namespace(from.namespace_);
-}
-
-int GeneratorPlugin::exec(int, char* []) {
-#ifdef _WIN32
-  _setmode(fileno(stdin), _O_BINARY);
-#endif
-  boost::shared_ptr<TFramedTransport> transport(
-      new TFramedTransport(boost::make_shared<TFDTransport>(fileno(stdin))));
-  TBinaryProtocol proto(transport);
-  GeneratorInput input;
-  try {
-    input.read(&proto);
-  } catch (std::exception& err) {
-    std::cerr << "Error while receiving plugin data: " << err.what() << std::endl;
-    return -1;
-  }
-  initGlobals();
-  ::t_program* p = g_program = convert_forward(input.program);
-  set_global_cache(input.type_registry);
-  convert(input.program, p);
-
-  int ret = generate(p, input.parsed_options);
-  clearGlobals();
-
-  return ret;
-}
-
-::t_const_value::t_const_value_type const_value_case(const t_const_value& v) {
-  if (v.__isset.map_val)
-    return ::t_const_value::CV_MAP;
-  if (v.__isset.list_val)
-    return ::t_const_value::CV_LIST;
-  if (v.__isset.string_val)
-    return ::t_const_value::CV_STRING;
-  if (v.__isset.integer_val)
-    return ::t_const_value::CV_INTEGER;
-  if (v.__isset.double_val)
-    return ::t_const_value::CV_DOUBLE;
-  if (v.__isset.identifier_val)
-    return ::t_const_value::CV_IDENTIFIER;
-  if (v.__isset.enum_val)
-    return ::t_const_value::CV_IDENTIFIER;
-  throw ThriftPluginError("Unknown const value type");
-}
-
-bool t_const_value::operator<(const t_const_value& that) const {
-  ::t_const_value::t_const_value_type t1 = const_value_case(*this);
-  ::t_const_value::t_const_value_type t2 = const_value_case(that);
-  if (t1 != t2)
-    return t1 < t2;
-  switch (t1) {
-  case ::t_const_value::CV_INTEGER:
-    return integer_val < that.integer_val;
-  case ::t_const_value::CV_DOUBLE:
-    return double_val < that.double_val;
-  case ::t_const_value::CV_STRING:
-    return string_val < that.string_val;
-  case ::t_const_value::CV_MAP:
-    if (that.map_val.empty())
-      return false;
-    else if (map_val.empty())
-      return true;
-    else
-      return map_val.begin()->first < that.map_val.begin()->first;
-  case ::t_const_value::CV_LIST:
-    if (that.list_val.empty())
-      return false;
-    else if (list_val.empty())
-      return true;
-    else
-      return list_val.front() < that.list_val.front();
-  case ::t_const_value::CV_IDENTIFIER:
-    return integer_val < that.integer_val;
-  }
-  throw ThriftPluginError("Unknown const value type");
-}
-}
-}
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin.h b/compiler/cpp/src/plugin/plugin.h
deleted file mode 100644
index 705cd41..0000000
--- a/compiler/cpp/src/plugin/plugin.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PLUGIN_PLUGIN_H
-#define T_PLUGIN_PLUGIN_H
-
-#include "thrift/Thrift.h"
-
-class t_program;
-
-namespace apache {
-namespace thrift {
-namespace plugin {
-
-struct ThriftPluginError : public apache::thrift::TException {
-  ThriftPluginError(const std::string& msg) : apache::thrift::TException(msg) {}
-};
-
-class GeneratorPlugin {
-public:
-  int exec(int argc, char* argv[]);
-  virtual int generate(::t_program*, const std::map<std::string, std::string>&) = 0;
-};
-}
-}
-}
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin.thrift
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin.thrift b/compiler/cpp/src/plugin/plugin.thrift
deleted file mode 100644
index a93873d..0000000
--- a/compiler/cpp/src/plugin/plugin.thrift
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-namespace as3 org.apache.thrift.plugin
-namespace cpp apache.thrift.plugin
-namespace csharp Thrift.Plugin
-namespace d thrift.plugin
-namespace delphi Thrift.Plugin
-namespace erl thrift.plugin
-namespace go thrift
-namespace haxe org.apache.thrift.plugin
-namespace hs Thrift.Plugin
-namespace java org.apache.thrift.plugin
-namespace ocaml Thrift
-namespace perl Thrift.Plugin
-namespace php thrift.plugin
-namespace py thrift.plugin
-namespace rb Thrift
-
-typedef i64 t_program_id
-typedef i64 t_type_id
-typedef i64 t_const_id
-typedef i64 t_service_id
-
-enum t_base {
-    TYPE_VOID
-    TYPE_STRING
-    TYPE_BOOL
-    TYPE_I8
-    TYPE_I16
-    TYPE_I32
-    TYPE_I64
-    TYPE_DOUBLE
-    TYPE_BINARY
-}
-
-struct TypeMetadata {
-  1: required string name
-  2: required t_program_id program_id
-  99: optional map<string, string> annotations
-  100: optional string doc
-}
-
-struct t_base_type {
-  1: required TypeMetadata metadata
-  2: required t_base value
-}
-
-struct t_list {
-  1: required TypeMetadata metadata
-  2: optional string cpp_name
-  3: required t_type_id elem_type
-}
-
-struct t_set {
-  1: required TypeMetadata metadata
-  2: optional string cpp_name
-  3: required t_type_id elem_type
-}
-
-struct t_map {
-  1: required TypeMetadata metadata
-  2: optional string cpp_name
-  3: required t_type_id key_type
-  4: required t_type_id val_type
-}
-
-struct t_typedef {
-  1: required TypeMetadata metadata
-  2: required t_type_id type
-  3: required string symbolic
-  4: required bool forward
-}
-
-struct t_enum_value {
-  1: required string name
-  2: required i32 value
-  99: optional map<string, string> annotations
-  100: optional string doc
-}
-struct t_enum {
-  1: required TypeMetadata metadata
-  2: required list<t_enum_value> constants
-}
-
-enum Requiredness {
-  T_REQUIRED = 0
-  T_OPTIONAL = 1
-  T_OPT_IN_REQ_OUT = 2
-}
-
-union t_const_value {
-  1: optional map<t_const_value, t_const_value> map_val
-  2: optional list<t_const_value> list_val
-  3: optional string string_val
-  4: optional i64 integer_val
-  5: optional double double_val
-  6: optional string identifier_val
-  7: optional t_type_id enum_val
-}
-struct t_const {
-  1: required string name
-  2: required t_type_id type
-  3: required t_const_value value
-  100: optional string doc
-}
-struct t_struct {
-  1: required TypeMetadata metadata
-  2: required list<t_field> members
-  3: required bool is_union
-  4: required bool is_xception
-}
-struct t_field {
-  1: required string name
-  2: required t_type_id type
-  3: required i32 key
-  4: required Requiredness req
-  5: optional t_const_value value
-  10: required bool reference
-  99: optional map<string, string> annotations
-  100: optional string doc
-}
-struct t_function {
-  1: required string name
-  2: required t_type_id returntype
-  3: required t_type_id arglist
-  4: required t_type_id xceptions
-  5: required bool is_oneway
-  100: optional string doc
-}
-struct t_service {
-  1: required TypeMetadata metadata
-  2: required list<t_function> functions
-  3: optional t_service_id extends_
-}
-union t_type {
-  1: optional t_base_type base_type_val
-  2: optional t_typedef typedef_val
-  3: optional t_enum enum_val
-  4: optional t_struct struct_val
-  5: optional t_struct xception_val
-  6: optional t_list list_val
-  7: optional t_set set_val
-  8: optional t_map map_val
-  9: optional t_service service_val
-}
-struct t_scope {
-  1: required list<t_type_id> types
-  2: required list<t_const_id> constants
-  3: required list<t_service_id> services
-}
-
-struct TypeRegistry {
-  1: required map<t_type_id, t_type> types
-  2: required map<t_const_id, t_const> constants
-  3: required map<t_service_id, t_service> services
-}
-
-struct t_program {
-  1: required string name
-  2: required t_program_id program_id
-  3: required string path
-  4: required string namespace_
-  5: required string out_path
-  6: required bool out_path_is_absolute
-  8: required list<t_program> includes
-  9: required string include_prefix
-  10: required t_scope scope
-
-  11: required list<t_type_id> typedefs
-  12: required list<t_type_id> enums
-  13: required list<t_const_id> consts
-  14: required list<t_type_id> objects
-  15: required list<t_service_id> services
-
-  16: required map<string, string> namespaces
-  17: required list<string> cpp_includes
-  18: required list<string> c_includes
-  100: optional string doc
-}
-
-struct GeneratorInput {
-  1: required t_program program
-  2: required TypeRegistry type_registry
-  3: required map<string, string> parsed_options
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin_output.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin_output.cc b/compiler/cpp/src/plugin/plugin_output.cc
deleted file mode 100644
index 1ab015e..0000000
--- a/compiler/cpp/src/plugin/plugin_output.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifdef _WIN32
-#include <cstdio>
-#include <fcntl.h>
-#include <io.h>
-#include <iostream>
-#define THRIFT_POPEN(cmd) _popen(cmd, "wb")
-#define THRIFT_PCLOSE _pclose
-#else
-#define THRIFT_POPEN(cmd) popen(cmd, "w")
-#define THRIFT_PCLOSE pclose
-#endif
-
-#include "plugin/plugin_output.h"
-
-#include <boost/range/adaptor/map.hpp>
-#include <boost/range/algorithm/copy.hpp>
-#include <boost/range/algorithm/transform.hpp>
-#include <boost/smart_ptr.hpp>
-
-#include "generate/t_generator.h"
-#include "plugin/plugin.h"
-#include "plugin/type_util.h"
-#include "thrift/protocol/TBinaryProtocol.h"
-#include "thrift/transport/TBufferTransports.h"
-#include "thrift/transport/TFDTransport.h"
-
-#include "plugin/plugin_types.h"
-
-namespace plugin_output {
-
-template <typename From>
-typename apache::thrift::plugin::ToType<From>::type convert(From* from) {
-  typename apache::thrift::plugin::ToType<From>::type to;
-  convert(from, to);
-  return to;
-}
-
-using apache::thrift::protocol::TBinaryProtocol;
-using apache::thrift::transport::TFDTransport;
-using apache::thrift::transport::TFramedTransport;
-
-using namespace apache::thrift;
-
-#define THRIFT_CONVERSION_N(from_type, to_type)                                                    \
-  template <>                                                                                      \
-  void convert<from_type, to_type>(from_type * from, to_type & to)
-#define THRIFT_CONVERSION(type) THRIFT_CONVERSION_N(::type, plugin::type)
-
-#define THRIFT_ASSIGN_N(from_name, to_name, prefix)                                                \
-  do {                                                                                             \
-    if (from)                                                                                      \
-      to.__set_##to_name(prefix(from->from_name));                                                 \
-  } while (0)
-
-#define THRIFT_ASSIGN(name) THRIFT_ASSIGN_N(get_##name(), name, )
-#define THRIFT_ASSIGN_CONVERT(type, from_name, to_name)                                            \
-  do {                                                                                             \
-    if (from && from->from_name) {                                                                 \
-      to.__set_##to_name(convert(from->from_name));                                                \
-    }                                                                                              \
-  } while (0)
-
-#define THRIFT_ASSIGN_OPT(name)                                                                    \
-  do {                                                                                             \
-    if (from->has_##name())                                                                        \
-      THRIFT_ASSIGN(name);                                                                         \
-  } while (0)
-
-#define THRIFT_ASSIGN_LIST_N(type, from_name, to_name)                                             \
-  do {                                                                                             \
-    if (from && !from->from_name.empty()) {                                                        \
-      std::transform(from->from_name.begin(),                                                      \
-                     from->from_name.end(),                                                        \
-                     std::back_inserter(to.to_name),                                               \
-                     convert< ::type>);                                                            \
-    }                                                                                              \
-  } while (0)
-
-#define THRIFT_ASSIGN_METADATA() convert(reinterpret_cast<t_type*>(from), to.metadata)
-
-// To avoid multiple instances of same type, t_type, t_const and t_service are stored in one place
-// and referenced by ID.
-template <typename T>
-struct TypeCache {
-  typedef typename plugin::ToType<T>::type to_type;
-  std::map<int64_t, to_type> cache;
-
-  template <typename T2>
-  int64_t store(T2* t) {
-    intptr_t id = reinterpret_cast<intptr_t>(t);
-    if (id) {
-      typename std::map<int64_t, to_type>::iterator it = cache.find(id);
-      if (it == cache.end()) {
-        // HACK: fake resolve for recursive type
-        cache.insert(std::make_pair(id, to_type()));
-        // overwrite with true value
-        cache[id] = convert(t);
-      }
-    }
-    return static_cast<int64_t>(id);
-  }
-
-  void clear() { cache.clear(); }
-};
-
-template <typename T>
-int64_t store_type(T* t);
-
-#define T_STORE(type)                                                                              \
-  TypeCache<t_##type> type##_cache;                                                                \
-  template <>                                                                                      \
-  plugin::t_##type##_id store_type<t_##type>(t_##type * t) {                                       \
-    return type##_cache.store<t_##type>(t);                                                        \
-  }
-T_STORE(type)
-T_STORE(const)
-T_STORE(service)
-#undef T_STORE
-
-#define THRIFT_ASSIGN_ID_N(t, from_name, to_name)                                                  \
-  do {                                                                                             \
-    if (from && from->from_name)                                                                   \
-      to.__set_##to_name(store_type<t>(from->from_name));                                          \
-  } while (0)
-
-#define THRIFT_ASSIGN_ID(name) THRIFT_ASSIGN_ID_N(t_type, get_##name(), name)
-
-#define THRIFT_ASSIGN_LIST_ID(t, name)                                                             \
-  do {                                                                                             \
-    if (from && !from->get_##name##s().empty()) {                                                  \
-      std::transform(from->get_##name##s().begin(),                                                \
-                     from->get_##name##s().end(),                                                  \
-                     std::back_inserter(to.name##s),                                               \
-                     &store_type<t>);                                                              \
-    }                                                                                              \
-  } while (0)
-
-THRIFT_CONVERSION_N(::t_type, plugin::TypeMetadata) {
-  to.program_id = reinterpret_cast<int64_t>(from->get_program());
-  THRIFT_ASSIGN_N(annotations_, annotations, );
-  if (from->has_doc()) {
-    to.__set_doc(from->get_doc());
-  }
-  THRIFT_ASSIGN(name);
-}
-
-THRIFT_CONVERSION(t_typedef) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_ID(type);
-  THRIFT_ASSIGN(symbolic);
-  THRIFT_ASSIGN_N(is_forward_typedef(), forward, );
-}
-
-THRIFT_CONVERSION(t_enum_value) {
-  THRIFT_ASSIGN_OPT(doc);
-  THRIFT_ASSIGN(name);
-  THRIFT_ASSIGN(value);
-}
-
-THRIFT_CONVERSION(t_enum) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_LIST_N(t_enum_value, get_constants(), constants);
-}
-
-THRIFT_CONVERSION(t_const_value) {
-  switch (from->get_type()) {
-  case t_const_value::CV_INTEGER:
-    THRIFT_ASSIGN_N(get_integer(), integer_val, );
-    break;
-  case t_const_value::CV_DOUBLE:
-    THRIFT_ASSIGN_N(get_double(), double_val, );
-    break;
-  case t_const_value::CV_STRING:
-    THRIFT_ASSIGN_N(get_string(), string_val, );
-    break;
-  case t_const_value::CV_IDENTIFIER:
-    THRIFT_ASSIGN_ID_N(t_type, enum_, enum_val);
-    THRIFT_ASSIGN_N(get_identifier(), identifier_val, );
-    break;
-  case t_const_value::CV_MAP:
-    to.__isset.map_val = true;
-    if (from && !from->get_map().empty()) {
-      for (std::map< ::t_const_value*, ::t_const_value*>::const_iterator it
-           = from->get_map().begin();
-           it != from->get_map().end();
-           it++) {
-        to.map_val.insert(std::make_pair(convert(it->first), convert(it->second)));
-      }
-    }
-    break;
-  case t_const_value::CV_LIST:
-    to.__isset.list_val = true;
-    THRIFT_ASSIGN_LIST_N(t_const_value, get_list(), list_val);
-    break;
-  default:
-    throw plugin::ThriftPluginError("const value has no value");
-  }
-}
-THRIFT_CONVERSION(t_const) {
-  THRIFT_ASSIGN_OPT(doc);
-  THRIFT_ASSIGN(name);
-  THRIFT_ASSIGN_ID(type);
-  THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value);
-}
-THRIFT_CONVERSION(t_field) {
-  THRIFT_ASSIGN_OPT(doc);
-  THRIFT_ASSIGN(name);
-  THRIFT_ASSIGN(key);
-  THRIFT_ASSIGN_N(get_req(), req, (plugin::Requiredness::type));
-  THRIFT_ASSIGN(reference);
-  THRIFT_ASSIGN_ID(type);
-  THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value);
-}
-THRIFT_CONVERSION(t_struct) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_LIST_N(t_field, get_members(), members);
-  THRIFT_ASSIGN_N(is_union(), is_union, );
-  THRIFT_ASSIGN_N(is_xception(), is_xception, );
-}
-THRIFT_CONVERSION(t_function) {
-  THRIFT_ASSIGN_OPT(doc);
-  THRIFT_ASSIGN(name);
-  THRIFT_ASSIGN_ID(returntype);
-  THRIFT_ASSIGN_N(is_oneway(), is_oneway, );
-  THRIFT_ASSIGN_ID(arglist);
-  THRIFT_ASSIGN_ID(xceptions);
-}
-
-THRIFT_CONVERSION(t_list) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_OPT(cpp_name);
-  THRIFT_ASSIGN_ID(elem_type);
-}
-THRIFT_CONVERSION(t_set) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_OPT(cpp_name);
-  THRIFT_ASSIGN_ID(elem_type);
-}
-THRIFT_CONVERSION(t_map) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_OPT(cpp_name);
-  THRIFT_ASSIGN_ID(key_type);
-  THRIFT_ASSIGN_ID(val_type);
-}
-
-THRIFT_CONVERSION(t_service) {
-  THRIFT_ASSIGN_METADATA();
-  THRIFT_ASSIGN_LIST_N(t_function, get_functions(), functions);
-  THRIFT_ASSIGN_ID_N(t_service, get_extends(), extends_);
-}
-
-THRIFT_CONVERSION(t_base_type) {
-  THRIFT_ASSIGN_METADATA();
-  if (from->is_binary()) {
-    to.value = plugin::t_base::TYPE_BINARY;
-  } else {
-    switch (from->get_base()) {
-#define T_BASETYPE_CASE(name)                                                                      \
-  case t_base_type::TYPE_##name:                                                                   \
-    to.value = plugin::t_base::TYPE_##name;                                                        \
-    break
-      T_BASETYPE_CASE(VOID);
-      T_BASETYPE_CASE(STRING);
-      T_BASETYPE_CASE(BOOL);
-      T_BASETYPE_CASE(I8);
-      T_BASETYPE_CASE(I16);
-      T_BASETYPE_CASE(I32);
-      T_BASETYPE_CASE(I64);
-      T_BASETYPE_CASE(DOUBLE);
-    default:
-      throw plugin::ThriftPluginError("Base type union has no value");
-      break;
-#undef T_BASETYPE_CASE
-    }
-  }
-}
-THRIFT_CONVERSION(t_type) {
-#define T_CONVERT_UNION_N(name, type)                                                              \
-  else if (from->is_##name()) {                                                                    \
-    to.__isset.name##_val = true;                                                                  \
-    convert(reinterpret_cast< ::type*>(from), to.name##_val);                                      \
-  }
-#define T_CONVERT_UNION(name) T_CONVERT_UNION_N(name, t_##name)
-  if (false) {
-  }
-  T_CONVERT_UNION(base_type)
-  T_CONVERT_UNION(typedef)
-  T_CONVERT_UNION(enum)
-  T_CONVERT_UNION(struct)
-  T_CONVERT_UNION_N(xception, t_struct)
-  T_CONVERT_UNION(list)
-  T_CONVERT_UNION(set)
-  T_CONVERT_UNION(map)
-  T_CONVERT_UNION(service)
-  else {
-    throw plugin::ThriftPluginError("Type union has no value");
-  }
-#undef T_CONVERT_UNION_N
-#undef T_CONVERT_UNION
-}
-
-THRIFT_CONVERSION(t_scope) {
-#define T_SCOPE_ASSIGN(name, type)                                                                 \
-  boost::copy(from->name##s_ | boost::adaptors::map_values                                         \
-              | boost::adaptors::transformed(&store_type<type>),                                   \
-              std::back_inserter(to.name##s))
-  T_SCOPE_ASSIGN(type, t_type);
-  T_SCOPE_ASSIGN(constant, t_const);
-  T_SCOPE_ASSIGN(service, t_service);
-#undef T_SCOPE_ASSIGN
-}
-
-void get_global_cache(plugin::TypeRegistry& reg) {
-  reg.types = type_cache.cache;
-  reg.constants = const_cache.cache;
-  reg.services = service_cache.cache;
-}
-
-void clear_global_cache() {
-  type_cache.clear();
-  const_cache.clear();
-  service_cache.clear();
-}
-
-THRIFT_CONVERSION(t_program) {
-  THRIFT_ASSIGN_CONVERT(t_scope, scope(), scope);
-  THRIFT_ASSIGN(path);
-  THRIFT_ASSIGN(out_path);
-  THRIFT_ASSIGN(name);
-  THRIFT_ASSIGN(include_prefix);
-  THRIFT_ASSIGN(cpp_includes);
-  THRIFT_ASSIGN(c_includes);
-  THRIFT_ASSIGN(namespaces);
-  THRIFT_ASSIGN_N(is_out_path_absolute(), out_path_is_absolute, );
-  THRIFT_ASSIGN_N(get_namespace(), namespace_, );
-  THRIFT_ASSIGN_LIST_ID(t_type, typedef);
-  THRIFT_ASSIGN_LIST_ID(t_type, enum);
-  THRIFT_ASSIGN_LIST_ID(t_type, object);
-  THRIFT_ASSIGN_LIST_ID(t_const, const);
-  THRIFT_ASSIGN_LIST_ID(t_service, service);
-  THRIFT_ASSIGN_LIST_N(t_program, get_includes(), includes);
-  to.program_id = reinterpret_cast<plugin::t_program_id>(from);
-}
-
-PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options) {
-  std::string language;
-  std::map<std::string, std::string> parsed_options;
-  t_generator::parse_options(options, language, parsed_options);
-  std::string cmd = "thrift-gen-";
-  if (language.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789")
-      != std::string::npos) {
-    std::cerr << "Invalid language name" << std::endl;
-    return PLUGIN_FAILURE;
-  }
-  cmd.append(language);
-  FILE* fd = THRIFT_POPEN(cmd.c_str());
-  if (fd) {
-#ifdef _WIN32
-    _setmode(fileno(fd), _O_BINARY);
-#endif
-    boost::shared_ptr<TFramedTransport> transport(
-        new TFramedTransport(boost::make_shared<TFDTransport>(fileno(fd))));
-    TBinaryProtocol proto(transport);
-
-    plugin::GeneratorInput input;
-    input.__set_parsed_options(parsed_options);
-    clear_global_cache();
-    convert(program, input.program);
-    get_global_cache(input.type_registry);
-    try {
-      input.write(&proto);
-      transport->flush();
-    } catch (std::exception& err) {
-      std::cerr << "Error while sending data to plugin: " << err.what() << std::endl;
-      THRIFT_PCLOSE(fd);
-      return PLUGIN_FAILURE;
-    }
-
-    // TODO: be prepared for hang or crash of child process
-    int ret = THRIFT_PCLOSE(fd);
-    if (!ret) {
-      return PLUGIN_SUCCEESS;
-    } else {
-      std::cerr << "plugin process returned non zero exit code: " << ret << std::endl;
-      return PLUGIN_FAILURE;
-    }
-  }
-  clear_global_cache();
-  return PLUGIN_NOT_FOUND;
-}
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin_output.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin_output.h b/compiler/cpp/src/plugin/plugin_output.h
deleted file mode 100644
index eab2d1b..0000000
--- a/compiler/cpp/src/plugin/plugin_output.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PLUGIN_PLUGIN_OUTPUT_H
-#define T_PLUGIN_PLUGIN_OUTPUT_H
-
-#include <string>
-
-class t_program;
-
-namespace plugin_output {
-
-enum PluginDelegateResult {
-  PLUGIN_NOT_FOUND,
-  PLUGIN_FAILURE,
-  PLUGIN_SUCCEESS,
-};
-
-PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options);
-}
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/type_util.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/type_util.h b/compiler/cpp/src/plugin/type_util.h
deleted file mode 100644
index 508b741..0000000
--- a/compiler/cpp/src/plugin/type_util.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PLUGIN_TYPE_UTIL_H
-#define T_PLUGIN_TYPE_UTIL_H
-
-namespace apache {
-namespace thrift {
-namespace plugin {
-
-template <typename From>
-struct ToType {};
-
-template <typename From>
-typename ToType<From>::type* convert_forward(const From&);
-
-template <typename From, typename To>
-void convert(const From&, To*);
-
-template <typename From>
-typename ToType<From>::type* convert(const From& from);
-
-class TypeRegistry;
-void set_global_cache(const TypeRegistry&);
-}
-}
-}
-
-// conversion from raw compiler types to plugin wire type
-namespace plugin_output {
-
-template <typename From, typename To>
-void convert(From* from, To& to);
-
-template <typename From>
-typename apache::thrift::plugin::ToType<From>::type convert(From* from);
-
-void get_global_cache(apache::thrift::plugin::TypeRegistry&);
-void clear_global_cache();
-}
-
-#define THRIFT_TYPE_MAPPING(TYPE)                                                                  \
-  class TYPE;                                                                                      \
-  namespace apache {                                                                               \
-  namespace thrift {                                                                               \
-  namespace plugin {                                                                               \
-  class TYPE;                                                                                      \
-  template <>                                                                                      \
-  struct ToType< ::TYPE> {                                                                         \
-    typedef TYPE type;                                                                             \
-  };                                                                                               \
-  template <>                                                                                      \
-  struct ToType<TYPE> {                                                                            \
-    typedef ::TYPE type;                                                                           \
-  };                                                                                               \
-  }                                                                                                \
-  }                                                                                                \
-  }
-THRIFT_TYPE_MAPPING(t_base_type)
-THRIFT_TYPE_MAPPING(t_const)
-THRIFT_TYPE_MAPPING(t_const_value)
-THRIFT_TYPE_MAPPING(t_container)
-THRIFT_TYPE_MAPPING(t_doc)
-THRIFT_TYPE_MAPPING(t_enum)
-THRIFT_TYPE_MAPPING(t_enum_value)
-THRIFT_TYPE_MAPPING(t_field)
-THRIFT_TYPE_MAPPING(t_function)
-THRIFT_TYPE_MAPPING(t_list)
-THRIFT_TYPE_MAPPING(t_map)
-THRIFT_TYPE_MAPPING(t_program)
-THRIFT_TYPE_MAPPING(t_scope)
-THRIFT_TYPE_MAPPING(t_service)
-THRIFT_TYPE_MAPPING(t_set)
-THRIFT_TYPE_MAPPING(t_struct)
-THRIFT_TYPE_MAPPING(t_type)
-THRIFT_TYPE_MAPPING(t_typedef)
-#undef THRIFT_TYPE_MAPPING
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/audit/t_audit.cpp
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/audit/t_audit.cpp b/compiler/cpp/src/thrift/audit/t_audit.cpp
new file mode 100644
index 0000000..1386f3b
--- /dev/null
+++ b/compiler/cpp/src/thrift/audit/t_audit.cpp
@@ -0,0 +1,464 @@
+
+#include <cassert>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+// Careful: must include globals first for extern definitions
+#include "thrift/globals.h"
+
+#include "thrift/parse/t_program.h"
+#include "thrift/parse/t_scope.h"
+#include "thrift/parse/t_const.h"
+#include "thrift/parse/t_field.h"
+
+#include "thrift/version.h"
+
+#include "thrift/audit/t_audit.h"
+
+extern int g_warn;
+extern std::string g_curpath;
+extern bool g_return_failure;
+
+void thrift_audit_warning(int level, const char* fmt, ...) {
+   if (g_warn < level) {
+      return;
+   }
+   va_list args;
+   printf("[Thrift Audit Warning:%s] ", g_curpath.c_str());
+   va_start(args, fmt);
+   vprintf(fmt, args);
+   va_end(args);
+   printf("\n");
+}
+
+void thrift_audit_failure(const char* fmt, ...) {
+  va_list args;
+  fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str());
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+  va_end(args);
+  fprintf(stderr, "\n");
+  g_return_failure = true;
+}
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram)
+{
+   const std::map<std::string, std::string>& newNamespaceMap = newProgram->get_all_namespaces();
+   const std::map<std::string, std::string>& oldNamespaceMap = oldProgram->get_all_namespaces();
+
+   for(std::map<std::string, std::string>::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin();
+         oldNamespaceMapIt != oldNamespaceMap.end();
+         oldNamespaceMapIt++)
+   {
+      std::map<std::string, std::string>::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first);
+      if(newNamespaceMapIt == newNamespaceMap.end())
+      {
+         thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str());
+      }
+      else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second)
+      {
+         thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str());
+      }
+   }
+}
+
+void compare_enum_values(t_enum* newEnum,t_enum* oldEnum)
+{
+   const std::vector<t_enum_value*>& oldEnumValues = oldEnum->get_constants();
+   for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt = oldEnumValues.begin();
+         oldEnumValuesIt != oldEnumValues.end();
+         oldEnumValuesIt++)
+   {
+      int enumValue = (*oldEnumValuesIt)->get_value();
+      t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue);
+      if(newEnumValue != NULL)
+      {
+         std::string enumName = (*oldEnumValuesIt)->get_name();
+         if(enumName != newEnumValue->get_name())
+         {
+            thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str());
+         }
+      }
+      else
+      {
+         thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str());
+      }
+
+   }
+}
+
+void compare_enums(const std::vector<t_enum*>& newEnumList, const std::vector<t_enum*>& oldEnumList)
+{
+   std::map<std::string,t_enum*> newEnumMap;
+   std::vector<t_enum*>::const_iterator newEnumIt;
+   for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++)
+   {
+      newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt;
+   }
+   std::vector<t_enum*>::const_iterator oldEnumIt;
+   for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++)
+   {
+      std::map<std::string,t_enum*>::iterator newEnumMapIt;
+      newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name());
+
+      if(newEnumMapIt == newEnumMap.end())
+      {
+         thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str());
+      }
+      else
+      {
+         compare_enum_values(newEnumMapIt->second, *oldEnumIt);
+      }
+   }
+}
+
+//This function returns 'true' if the two arguements are of same types.
+//Returns false if they are of different type
+bool compare_type(t_type* newType, t_type* oldType)
+{
+   //Comparing names of two types will work when the newType and oldType are basic types or structs or enums.
+   //However, when they are containers, get_name() returns empty for which we have to compare the type of
+   //their elements as well.
+   if((newType->get_name()).empty() && (oldType->get_name()).empty())
+   {
+
+      if(newType->is_list() && oldType->is_list())
+      {
+         t_type* newElementType = ((t_list*)newType)->get_elem_type();
+         t_type* oldElementType = ((t_list*)oldType)->get_elem_type();
+         return compare_type(newElementType, oldElementType);
+      }
+      else if(newType->is_map() && oldType->is_map())
+      {
+         t_type* newKeyType = ((t_map*)newType)->get_key_type();
+         t_type* oldKeyType = ((t_map*)oldType)->get_key_type();
+
+         t_type* newValType = ((t_map*)newType)->get_val_type();
+         t_type* oldValType = ((t_map*)oldType)->get_val_type();
+
+         return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType));
+      }
+      else if(newType->is_set() && oldType->is_set())
+      {
+         t_type* newElementType = ((t_set*)newType)->get_elem_type();
+         t_type* oldElementType = ((t_set*)oldType)->get_elem_type();
+         return compare_type(newElementType, oldElementType);
+      }
+      else
+      {
+         return false;
+      }
+   }
+   else if(newType->get_name() == oldType->get_name())
+   {
+      return true;
+   }
+   else
+   {
+      return false;
+   }
+}
+
+bool compare_pair(std::pair<t_const_value*, t_const_value*> newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair)
+{
+   return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second);
+}
+
+// This function returns 'true' if the default values are same. Returns false if they are different.
+bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault)
+{
+   if(newStructDefault == NULL && oldStructDefault == NULL) return true;
+   else if(newStructDefault == NULL && oldStructDefault != NULL) return false;
+   else if (newStructDefault != NULL && oldStructDefault == NULL) return false;
+
+   if(newStructDefault->get_type() != oldStructDefault->get_type())
+   {
+      return false;
+   }
+
+   switch(newStructDefault->get_type())
+   {
+      case t_const_value::CV_INTEGER:
+         return (newStructDefault->get_integer() == oldStructDefault->get_integer());
+      case t_const_value::CV_DOUBLE:
+         return (newStructDefault->get_double() == oldStructDefault->get_double());
+      case t_const_value::CV_STRING:
+         return (newStructDefault->get_string() == oldStructDefault->get_string());
+      case t_const_value::CV_LIST:
+         {
+            const std::vector<t_const_value*>& oldDefaultList = oldStructDefault->get_list();
+            const std::vector<t_const_value*>& newDefaultList = newStructDefault->get_list();
+            bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size());
+
+            return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults);
+         }
+      case t_const_value::CV_MAP:
+         {
+            const std::map<t_const_value*, t_const_value*> newMap = newStructDefault->get_map();
+            const std::map<t_const_value*, t_const_value*> oldMap = oldStructDefault->get_map();
+
+            bool defaultValuesCompare = (oldMap.size() == newMap.size());
+
+            return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair);
+         }
+      case t_const_value::CV_IDENTIFIER:
+         return (newStructDefault->get_identifier() == oldStructDefault->get_identifier());
+      default:
+         return false;
+   }
+
+}
+
+void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName)
+{
+   t_type* newFieldType = newField->get_type();
+   t_type* oldFieldType = oldField->get_type();
+   if(!compare_type(newFieldType, oldFieldType))
+   {
+      thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+   }
+
+   // A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values.
+   bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED);
+   bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED);
+
+   if(newStructFieldOptional != oldStructFieldOptional)
+   {
+      thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+   }
+   if(newStructFieldOptional || oldStructFieldOptional)
+   {
+      if(!compare_defaults(newField->get_value(), oldField->get_value()))
+      {
+         thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+      }
+   }
+
+   std::string fieldName = newField->get_name();
+   if(fieldName != oldField->get_name())
+   {
+      thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str());
+   }
+
+}
+
+void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string())
+{
+   std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName;
+   const std::vector<t_field*>& oldStructMembersInIdOrder = oldStruct->get_sorted_members();
+   const std::vector<t_field*>& newStructMembersInIdOrder = newStruct->get_sorted_members();
+   std::vector<t_field*>::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin();
+   std::vector<t_field*>::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin();
+
+   // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member
+   // lists together.
+   while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end()))
+   {
+      if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end())
+      {
+         // A field ID has been removed from the end.
+         thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
+         oldStructMemberIt++;
+      }
+      else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end())
+      {
+         //New field ID has been added to the end.
+         if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED)
+         {
+            thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str());
+         }
+         newStructMemberIt++;
+      }
+      else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key())
+      {
+         //Field ID found in both structs. Compare field types, default values.
+         compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName);
+
+         newStructMemberIt++;
+         oldStructMemberIt++;
+      }
+      else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key())
+      {
+         //New Field Id is inserted in between
+         //Adding fields to struct is fine, but adding them in the middle is suspicious. Error!!
+         thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n",  (*newStructMemberIt)->get_key(),  structName.c_str());
+         newStructMemberIt++;
+      }
+      else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key())
+      {
+         //A field is deleted in newStruct.
+         thrift_audit_failure("Struct Field removed for Id = %d in %s \n",  (*oldStructMemberIt)->get_key(), structName.c_str());
+         oldStructMemberIt++;
+      }
+
+   }
+}
+
+void compare_structs(const std::vector<t_struct*>& newStructList, const std::vector<t_struct*>& oldStructList)
+{
+   std::map<std::string,t_struct*> newStructMap;
+   std::vector<t_struct*>::const_iterator newStructListIt;
+   for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++)
+   {
+      newStructMap[(*newStructListIt)->get_name()] = *newStructListIt;
+   }
+
+   std::vector<t_struct*>::const_iterator oldStructListIt;
+   for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++)
+   {
+      std::map<std::string, t_struct*>::iterator newStructMapIt;
+      newStructMapIt = newStructMap.find((*oldStructListIt)->get_name());
+      if(newStructMapIt == newStructMap.end())
+      {
+         thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str());
+      }
+      else
+      {
+         compare_single_struct(newStructMapIt->second, *oldStructListIt);
+      }
+   }
+
+}
+
+void compare_single_function(t_function* newFunction, t_function* oldFunction)
+{
+   t_type* newFunctionReturnType = newFunction->get_returntype();
+
+   if(newFunction->is_oneway() != oldFunction->is_oneway())
+   {
+      thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str());
+   }
+   if(!compare_type(newFunctionReturnType, oldFunction->get_returntype()))
+   {
+      thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str());
+   }
+
+   //Compare function arguments.
+   compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist());
+   std::string exceptionName = oldFunction->get_name();
+   exceptionName += "_exception";
+   compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName);
+}
+
+void compare_functions(const std::vector<t_function*>& newFunctionList, const std::vector<t_function*>& oldFunctionList)
+{
+   std::map<std::string, t_function*> newFunctionMap;
+   std::map<std::string, t_function*>::iterator newFunctionMapIt;
+   for(std::vector<t_function*>::const_iterator newFunctionIt = newFunctionList.begin();
+         newFunctionIt != newFunctionList.end();
+         newFunctionIt++)
+   {
+      newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt;
+   }
+
+   for(std::vector<t_function*>::const_iterator oldFunctionIt = oldFunctionList.begin();
+         oldFunctionIt != oldFunctionList.end();
+         oldFunctionIt++)
+   {
+      newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name());
+      if(newFunctionMapIt == newFunctionMap.end())
+      {
+         thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str());
+         continue;
+      }
+      else
+      {
+         //Function is found in both thrift files. Compare return type and argument list
+         compare_single_function(newFunctionMapIt->second, *oldFunctionIt);
+      }
+   }
+
+}
+
+void compare_services(const std::vector<t_service*>& newServices, const std::vector<t_service*>& oldServices)
+{
+   std::vector<t_service*>::const_iterator oldServiceIt;
+
+   std::map<std::string, t_service*> newServiceMap;
+   for(std::vector<t_service*>::const_iterator newServiceIt = newServices.begin();
+         newServiceIt != newServices.end();
+         newServiceIt++)
+   {
+      newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt;
+   }
+
+
+   for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++)
+   {
+      const std::string oldServiceName = (*oldServiceIt)->get_name();
+      std::map<std::string, t_service*>::iterator newServiceMapIt = newServiceMap.find(oldServiceName);
+
+      if(newServiceMapIt == newServiceMap.end())
+      {
+         thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str());
+      }
+      else
+      {
+         t_service* oldServiceExtends = (*oldServiceIt)->get_extends();
+         t_service* newServiceExtends = (newServiceMapIt->second)->get_extends();
+
+         if(oldServiceExtends == NULL)
+         {
+            // It is fine to add extends. So if service in older thrift did not have any extends, we are fine.
+            // DO Nothing
+         }
+         else if(oldServiceExtends != NULL && newServiceExtends == NULL)
+         {
+            thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
+         }
+         else
+         {
+            std::string oldExtendsName = oldServiceExtends->get_name();
+            std::string newExtendsName = newServiceExtends->get_name();
+
+            if( newExtendsName != oldExtendsName)
+            {
+               thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
+            }
+         }
+
+         compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions());
+      }
+
+   }
+
+}
+
+void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst)
+{
+   std::vector<t_const*>::const_iterator newConstIt;
+   std::vector<t_const*>::const_iterator oldConstIt;
+
+   std::map<std::string, t_const*> newConstMap;
+
+   for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++)
+   {
+      newConstMap[(*newConstIt)->get_name()] = *newConstIt;
+   }
+
+   std::map<std::string, t_const*>::const_iterator newConstMapIt;
+   for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++)
+   {
+      newConstMapIt = newConstMap.find((*oldConstIt)->get_name());
+      if(newConstMapIt == newConstMap.end())
+      {
+         thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str());
+      }
+      else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type()))
+      {
+         thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str());
+      }
+      else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value()))
+      {
+         thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str());
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/audit/t_audit.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/audit/t_audit.h b/compiler/cpp/src/thrift/audit/t_audit.h
new file mode 100644
index 0000000..be79e31
--- /dev/null
+++ b/compiler/cpp/src/thrift/audit/t_audit.h
@@ -0,0 +1,14 @@
+#ifndef T_AUDIT_H
+#define T_AUDIT_H
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram);
+void compare_enums(const std::vector<t_enum*>& newEnumList,
+                   const std::vector<t_enum*>& oldEnumList);
+bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault);
+void compare_structs(const std::vector<t_struct*>& newStructList,
+                     const std::vector<t_struct*>& oldStructList);
+void compare_services(const std::vector<t_service*>& newServices,
+                      const std::vector<t_service*>& oldServices);
+void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst);
+
+#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/common.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/common.cc b/compiler/cpp/src/thrift/common.cc
new file mode 100644
index 0000000..3a2b9d3
--- /dev/null
+++ b/compiler/cpp/src/thrift/common.cc
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include "thrift/common.h"
+#include "thrift/parse/t_base_type.h"
+
+t_type* g_type_void;
+t_type* g_type_string;
+t_type* g_type_binary;
+t_type* g_type_slist;
+t_type* g_type_bool;
+t_type* g_type_i8;
+t_type* g_type_i16;
+t_type* g_type_i32;
+t_type* g_type_i64;
+t_type* g_type_double;
+
+void initGlobals() {
+  g_type_void = new t_base_type("void", t_base_type::TYPE_VOID);
+  g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
+  g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING);
+  ((t_base_type*)g_type_binary)->set_binary(true);
+  g_type_slist = new t_base_type("string", t_base_type::TYPE_STRING);
+  ((t_base_type*)g_type_slist)->set_string_list(true);
+  g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL);
+  g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8);
+  g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16);
+  g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32);
+  g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64);
+  g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
+}
+
+void clearGlobals() {
+  delete g_type_void;
+  delete g_type_string;
+  delete g_type_bool;
+  delete g_type_i8;
+  delete g_type_i16;
+  delete g_type_i32;
+  delete g_type_i64;
+  delete g_type_double;
+}
+
+/**
+ * Those are not really needed for plugins but causes link errors without
+ */
+
+/**
+ * The location of the last parsed doctext comment.
+ */
+int g_doctext_lineno;
+int g_program_doctext_lineno = 0;
+PROGDOCTEXT_STATUS g_program_doctext_status = INVALID;

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/common.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/common.h b/compiler/cpp/src/thrift/common.h
new file mode 100644
index 0000000..6948846
--- /dev/null
+++ b/compiler/cpp/src/thrift/common.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef T_COMMON_H
+#define T_COMMON_H
+
+#include "thrift/parse/t_type.h"
+
+/**
+ * Global types for the parser to be able to reference
+ */
+
+extern t_type* g_type_void;
+extern t_type* g_type_string;
+extern t_type* g_type_binary;
+extern t_type* g_type_slist;
+extern t_type* g_type_bool;
+extern t_type* g_type_i8;
+extern t_type* g_type_i16;
+extern t_type* g_type_i32;
+extern t_type* g_type_i64;
+extern t_type* g_type_double;
+
+void initGlobals();
+void clearGlobals();
+
+#endif


[31/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_perl_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_perl_generator.cc b/compiler/cpp/src/generate/t_perl_generator.cc
deleted file mode 100644
index 45cfe4b..0000000
--- a/compiler/cpp/src/generate/t_perl_generator.cc
+++ /dev/null
@@ -1,1648 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <list>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_oop_generator.h"
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * PERL code generator.
- *
- */
-class t_perl_generator : public t_oop_generator {
-public:
-  t_perl_generator(t_program* program,
-                   const std::map<std::string, std::string>& parsed_options,
-                   const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option perl:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-perl";
-    escape_['$'] = "\\$";
-    escape_['@'] = "\\@";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-
-  /**
-   * Structs!
-   */
-
-  void generate_perl_struct(t_struct* tstruct, bool is_exception);
-  void generate_perl_struct_definition(std::ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_xception = false);
-  void generate_perl_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_perl_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_perl_function_helpers(t_function* tfunction);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_rest(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_processor(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  bool inclass = false);
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string perl_includes();
-  std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-
-  std::string autogen_comment() {
-    return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-           + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n";
-  }
-
-  void perl_namespace_dirs(t_program* p, std::list<std::string>& dirs) {
-    std::string ns = p->get_namespace("perl");
-    std::string::size_type loc;
-
-    if (ns.size() > 0) {
-      while ((loc = ns.find(".")) != std::string::npos) {
-        dirs.push_back(ns.substr(0, loc));
-        ns = ns.substr(loc + 1);
-      }
-    }
-
-    if (ns.size() > 0) {
-      dirs.push_back(ns);
-    }
-  }
-
-  std::string perl_namespace(t_program* p) {
-    std::string ns = p->get_namespace("perl");
-    std::string result = "";
-    std::string::size_type loc;
-
-    if (ns.size() > 0) {
-      while ((loc = ns.find(".")) != std::string::npos) {
-        result += ns.substr(0, loc);
-        result += "::";
-        ns = ns.substr(loc + 1);
-      }
-
-      if (ns.size() > 0) {
-        result += ns + "::";
-      }
-    }
-
-    return result;
-  }
-
-  std::string get_namespace_out_dir() {
-    std::string outdir = get_out_dir();
-    std::list<std::string> dirs;
-    perl_namespace_dirs(program_, dirs);
-    std::list<std::string>::iterator it;
-    for (it = dirs.begin(); it != dirs.end(); it++) {
-      outdir += *it + "/";
-    }
-    return outdir;
-  }
-
-private:
-  /**
-   * File streams
-   */
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_helpers_;
-  std::ofstream f_service_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_perl_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  string outdir = get_out_dir();
-  std::list<std::string> dirs;
-  perl_namespace_dirs(program_, dirs);
-  std::list<std::string>::iterator it;
-  for (it = dirs.begin(); it != dirs.end(); it++) {
-    outdir += *it + "/";
-    MKDIR(outdir.c_str());
-  }
-
-  // Make output file
-  string f_types_name = outdir + "Types.pm";
-  f_types_.open(f_types_name.c_str());
-  string f_consts_name = outdir + "Constants.pm";
-  f_consts_.open(f_consts_name.c_str());
-
-  // Print header
-  f_types_ << autogen_comment() << perl_includes();
-
-  // Print header
-  f_consts_ << autogen_comment() << "package " << perl_namespace(program_) << "Constants;" << endl
-            << perl_includes() << endl;
-}
-
-/**
- * Prints standard java imports
- */
-string t_perl_generator::perl_includes() {
-  string inc;
-
-  inc = "require 5.6.0;\n";
-  inc += "use strict;\n";
-  inc += "use warnings;\n";
-  inc += "use Thrift;\n\n";
-
-  return inc;
-}
-
-/**
- * Close up (or down) some filez.
- */
-void t_perl_generator::close_generator() {
-  // Close types file
-  f_types_ << "1;" << endl;
-  f_types_.close();
-
-  f_consts_ << "1;" << endl;
-  f_consts_.close();
-}
-
-/**
- * Generates a typedef. This is not done in PERL, types are all implicit.
- *
- * @param ttypedef The type definition
- */
-void t_perl_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Generates code for an enumerated type. Since define is expensive to lookup
- * in PERL, we use a global array for this.
- *
- * @param tenum The enumeration
- */
-void t_perl_generator::generate_enum(t_enum* tenum) {
-  f_types_ << "package " << perl_namespace(program_) << tenum->get_name() << ";" << endl;
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    f_types_ << "use constant " << (*c_iter)->get_name() << " => " << value << ";" << endl;
-  }
-}
-
-/**
- * Generate a constant value
- */
-void t_perl_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  f_consts_ << "use constant " << name << " => ";
-  f_consts_ << render_const_value(type, value);
-  f_consts_ << ";" << endl << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_perl_generator::render_const_value(t_type* type, t_const_value* value) {
-  std::ostringstream out;
-
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "1" : "0");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    out << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << "new " << perl_namespace(type->get_program()) << type->get_name() << "({" << endl;
-    indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      out << render_const_value(g_type_string, v_iter->first);
-      out << " => ";
-      out << render_const_value(field_type, v_iter->second);
-      out << ",";
-      out << endl;
-    }
-
-    out << "})";
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    out << "{" << endl;
-
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << render_const_value(ktype, v_iter->first);
-      out << " => ";
-      out << render_const_value(vtype, v_iter->second);
-      out << "," << endl;
-    }
-
-    out << "}";
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    out << "[" << endl;
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-
-      out << render_const_value(etype, *v_iter);
-      if (type->is_set()) {
-        out << " => 1";
-      }
-      out << "," << endl;
-    }
-    out << "]";
-  }
-  return out.str();
-}
-
-/**
- * Make a struct
- */
-void t_perl_generator::generate_struct(t_struct* tstruct) {
-  generate_perl_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_perl_generator::generate_xception(t_struct* txception) {
-  generate_perl_struct(txception, true);
-}
-
-/**
- * Structs can be normal or exceptions.
- */
-void t_perl_generator::generate_perl_struct(t_struct* tstruct, bool is_exception) {
-  generate_perl_struct_definition(f_types_, tstruct, is_exception);
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is nothing in PERL
- * where the objects are all just associative arrays (unless of course we
- * decide to start using objects for them...)
- *
- * @param tstruct The struct definition
- */
-void t_perl_generator::generate_perl_struct_definition(ofstream& out,
-                                                       t_struct* tstruct,
-                                                       bool is_exception) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  out << "package " << perl_namespace(tstruct->get_program()) << tstruct->get_name() << ";\n";
-  if (is_exception) {
-    out << "use base qw(Thrift::TException);\n";
-  }
-
-  // Create simple acessor methods
-  out << "use base qw(Class::Accessor);\n";
-
-  if (members.size() > 0) {
-    out << perl_namespace(tstruct->get_program()) << tstruct->get_name() << "->mk_accessors( qw( ";
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      if (!t->is_xception()) {
-        out << (*m_iter)->get_name() << " ";
-      }
-    }
-
-    out << ") );\n";
-  }
-
-  out << endl;
-
-  // new()
-  indent_up();
-  out << "sub new {" << endl << indent() << "my $classname = shift;" << endl << indent()
-      << "my $self      = {};" << endl << indent() << "my $vals      = shift || {};" << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    string dval = "undef";
-    t_type* t = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
-      dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
-    }
-    out << indent() << "$self->{" << (*m_iter)->get_name() << "} = " << dval << ";" << endl;
-  }
-
-  // Generate constructor from array
-  if (members.size() > 0) {
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
-        indent(out) << "$self->{" << (*m_iter)->get_name()
-                    << "} = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
-      }
-    }
-
-    out << indent() << "if (UNIVERSAL::isa($vals,'HASH')) {" << endl;
-    indent_up();
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      out << indent() << "if (defined $vals->{" << (*m_iter)->get_name() << "}) {" << endl
-          << indent() << "  $self->{" << (*m_iter)->get_name() << "} = $vals->{"
-          << (*m_iter)->get_name() << "};" << endl << indent() << "}" << endl;
-    }
-    indent_down();
-    out << indent() << "}" << endl;
-  }
-
-  out << indent() << "return bless ($self, $classname);" << endl;
-  indent_down();
-  out << "}\n\n";
-
-  out << "sub getName {" << endl << indent() << "  return '" << tstruct->get_name() << "';" << endl
-      << indent() << "}" << endl << endl;
-
-  generate_perl_struct_reader(out, tstruct);
-  generate_perl_struct_writer(out, tstruct);
-}
-
-/**
- * Generates the read() method for a struct
- */
-void t_perl_generator::generate_perl_struct_reader(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << "sub read {" << endl;
-
-  indent_up();
-
-  out << indent() << "my ($self, $input) = @_;" << endl << indent() << "my $xfer  = 0;" << endl
-      << indent() << "my $fname;" << endl << indent() << "my $ftype = 0;" << endl << indent()
-      << "my $fid   = 0;" << endl;
-
-  indent(out) << "$xfer += $input->readStructBegin(\\$fname);" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (1) " << endl;
-
-  scope_up(out);
-
-  indent(out) << "$xfer += $input->readFieldBegin(\\$fname, \\$ftype, \\$fid);" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if ($ftype == TType::STOP) {" << endl;
-  indent_up();
-  indent(out) << "last;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  // Switch statement on the field we are reading
-  indent(out) << "SWITCH: for($fid)" << endl;
-
-  scope_up(out);
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-
-    indent(out) << "/^" << (*f_iter)->get_key() << "$/ && do{";
-    indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-
-    indent_up();
-    generate_deserialize_field(out, *f_iter, "self->");
-    indent_down();
-
-    indent(out) << "} else {" << endl;
-
-    indent(out) << "  $xfer += $input->skip($ftype);" << endl;
-
-    out << indent() << "}" << endl << indent() << "last; };" << endl;
-  }
-  // In the default case we skip the field
-
-  indent(out) << "  $xfer += $input->skip($ftype);" << endl;
-
-  scope_down(out);
-
-  indent(out) << "$xfer += $input->readFieldEnd();" << endl;
-
-  scope_down(out);
-
-  indent(out) << "$xfer += $input->readStructEnd();" << endl;
-
-  indent(out) << "return $xfer;" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates the write() method for a struct
- */
-void t_perl_generator::generate_perl_struct_writer(ofstream& out, t_struct* tstruct) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << "sub write {" << endl;
-
-  indent_up();
-  indent(out) << "my ($self, $output) = @_;" << endl;
-  indent(out) << "my $xfer   = 0;" << endl;
-
-  indent(out) << "$xfer += $output->writeStructBegin('" << name << "');" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    out << indent() << "if (defined $self->{" << (*f_iter)->get_name() << "}) {" << endl;
-    indent_up();
-
-    indent(out) << "$xfer += $output->writeFieldBegin("
-                << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
-                << ", " << (*f_iter)->get_key() << ");" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "self->");
-
-    indent(out) << "$xfer += $output->writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}" << endl;
-  }
-
-  out << indent() << "$xfer += $output->writeFieldStop();" << endl << indent()
-      << "$xfer += $output->writeStructEnd();" << endl;
-
-  out << indent() << "return $xfer;" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_perl_generator::generate_service(t_service* tservice) {
-  string f_service_name = get_namespace_out_dir() + service_name_ + ".pm";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ <<
-      ///      "package "<<service_name_<<";"<<endl<<
-      autogen_comment() << perl_includes();
-
-  f_service_ << "use " << perl_namespace(tservice->get_program()) << "Types;" << endl;
-
-  t_service* extends_s = tservice->get_extends();
-  if (extends_s != NULL) {
-    f_service_ << "use " << perl_namespace(extends_s->get_program()) << extends_s->get_name() << ";"
-               << endl;
-  }
-
-  f_service_ << endl;
-
-  // Generate the three main parts of the service (well, two for now in PERL)
-  generate_service_helpers(tservice);
-  generate_service_interface(tservice);
-  generate_service_rest(tservice);
-  generate_service_client(tservice);
-  generate_service_processor(tservice);
-
-  // Close service file
-  f_service_ << "1;" << endl;
-  f_service_.close();
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_perl_generator::generate_service_processor(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-  t_service* extends_s = tservice->get_extends();
-  if (extends_s != NULL) {
-    extends = perl_namespace(extends_s->get_program()) + extends_s->get_name();
-    extends_processor = "use base qw(" + extends + "Processor);";
-  }
-
-  indent_up();
-
-  // Generate the header portion
-  f_service_ << "package " << perl_namespace(program_) << service_name_ << "Processor;" << endl
-             << endl << "use strict;" << endl << extends_processor << endl << endl;
-
-  if (extends.empty()) {
-    f_service_ << "sub new {" << endl;
-
-    indent_up();
-
-    f_service_ << indent() << "my ($classname, $handler) = @_;" << endl << indent()
-               << "my $self      = {};" << endl;
-
-    f_service_ << indent() << "$self->{handler} = $handler;" << endl;
-
-    f_service_ << indent() << "return bless ($self, $classname);" << endl;
-
-    indent_down();
-
-    f_service_ << "}" << endl << endl;
-  }
-
-  // Generate the server implementation
-  f_service_ << "sub process {" << endl;
-  indent_up();
-
-  f_service_ << indent() << "my ($self, $input, $output) = @_;" << endl;
-
-  f_service_ << indent() << "my $rseqid = 0;" << endl << indent() << "my $fname  = undef;" << endl
-             << indent() << "my $mtype  = 0;" << endl << endl;
-
-  f_service_ << indent() << "$input->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);" << endl;
-
-  // HOT: check for method implementation
-  f_service_ << indent() << "my $methodname = 'process_'.$fname;" << endl << indent()
-             << "if (!$self->can($methodname)) {" << endl;
-  indent_up();
-
-  f_service_ << indent() << "$input->skip(TType::STRUCT);" << endl << indent()
-             << "$input->readMessageEnd();" << endl << indent()
-             << "my $x = new TApplicationException('Function '.$fname.' not implemented.', "
-                "TApplicationException::UNKNOWN_METHOD);" << endl << indent()
-             << "$output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);" << endl
-             << indent() << "$x->write($output);" << endl << indent()
-             << "$output->writeMessageEnd();" << endl << indent()
-             << "$output->getTransport()->flush();" << endl << indent() << "return;" << endl;
-
-  indent_down();
-  f_service_ << indent() << "}" << endl << indent()
-             << "$self->$methodname($rseqid, $input, $output);" << endl << indent() << "return 1;"
-             << endl;
-
-  indent_down();
-
-  f_service_ << "}" << endl << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_perl_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  // Open function
-  f_service_ << "sub process_" << tfunction->get_name() << " {" << endl;
-
-  indent_up();
-
-  f_service_ << indent() << "my ($self, $seqid, $input, $output) = @_;" << endl;
-
-  string argsname = perl_namespace(tservice->get_program()) + service_name_ + "_"
-                    + tfunction->get_name() + "_args";
-  string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_"
-                      + tfunction->get_name() + "_result";
-
-  f_service_ << indent() << "my $args = new " << argsname << "();" << endl << indent()
-             << "$args->read($input);" << endl;
-
-  f_service_ << indent() << "$input->readMessageEnd();" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "my $result = new " << resultname << "();" << endl;
-  }
-
-  // Try block for a function with exceptions
-  if (xceptions.size() > 0) {
-    f_service_ << indent() << "eval {" << endl;
-    indent_up();
-  }
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_ << indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "$result->{success} = ";
-  }
-  f_service_ << "$self->{handler}->" << tfunction->get_name() << "(";
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_service_ << ", ";
-    }
-    f_service_ << "$args->" << (*f_iter)->get_name();
-  }
-  f_service_ << ");" << endl;
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    indent_down();
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << indent() << "}; if( UNIVERSAL::isa($@,'"
-                 << perl_namespace((*x_iter)->get_type()->get_program())
-                 << (*x_iter)->get_type()->get_name() << "') ){ " << endl;
-
-      indent_up();
-      f_service_ << indent() << "$result->{" << (*x_iter)->get_name() << "} = $@;" << endl;
-      f_service_ << indent() << "$@ = undef;" << endl;
-      indent_down();
-      f_service_ << indent();
-    }
-    f_service_ << "}" << endl;
-
-    // catch-all for unexpected exceptions (THRIFT-3191)
-    f_service_ << indent() << "if ($@) {" << endl;
-    indent_up();
-    f_service_ << indent() << "$@ =~ s/^\\s+|\\s+$//g;" << endl
-               << indent() << "my $err = new TApplicationException(\"Unexpected Exception: \" . $@, TApplicationException::INTERNAL_ERROR);" << endl
-               << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', TMessageType::EXCEPTION, $seqid);" << endl
-               << indent() << "$err->write($output);" << endl
-               << indent() << "$output->writeMessageEnd();" << endl
-               << indent() << "$output->getTransport()->flush();" << endl
-               << indent() << "$@ = undef;" << endl
-               << indent() << "return;" << endl;
-    indent_down();
-    f_service_ << indent() << "}" << endl;
-  }
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "return;" << endl;
-    indent_down();
-    f_service_ << "}" << endl;
-    return;
-  }
-
-  // Serialize the reply
-  f_service_ << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', TMessageType::REPLY, $seqid);" << endl
-             << indent() << "$result->write($output);" << endl
-             << indent() << "$output->writeMessageEnd();" << endl
-             << indent() << "$output->getTransport()->flush();" << endl;
-
-  // Close function
-  indent_down();
-  f_service_ << "}" << endl << endl;
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_perl_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  f_service_ << "# HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    string name = ts->get_name();
-    ts->set_name(service_name_ + "_" + name);
-    generate_perl_struct_definition(f_service_, ts, false);
-    generate_perl_function_helpers(*f_iter);
-    ts->set_name(name);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_perl_generator::generate_perl_function_helpers(t_function* tfunction) {
-  t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_perl_struct_definition(f_service_, &result, false);
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_perl_generator::generate_service_interface(t_service* tservice) {
-  string extends_if = "";
-  t_service* extends_s = tservice->get_extends();
-  if (extends_s != NULL) {
-    extends_if = "use base qw(" + perl_namespace(extends_s->get_program()) + extends_s->get_name()
-                 + "If);";
-  }
-
-  f_service_ << "package " << perl_namespace(program_) << service_name_ << "If;" << endl << endl
-             << "use strict;" << endl << extends_if << endl << endl;
-
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << "sub " << function_signature(*f_iter) << endl << "  die 'implement interface';\n}"
-               << endl << endl;
-  }
-  indent_down();
-}
-
-/**
- * Generates a REST interface
- */
-void t_perl_generator::generate_service_rest(t_service* tservice) {
-  string extends = "";
-  string extends_if = "";
-  t_service* extends_s = tservice->get_extends();
-  if (extends_s != NULL) {
-    extends = extends_s->get_name();
-    extends_if = "use base qw(" + perl_namespace(extends_s->get_program()) + extends_s->get_name()
-                 + "Rest);";
-  }
-  f_service_ << "package " << perl_namespace(program_) << service_name_ << "Rest;" << endl << endl
-             << "use strict;" << endl << extends_if << endl << endl;
-
-  if (extends.empty()) {
-    f_service_ << "sub new {" << endl;
-
-    indent_up();
-
-    f_service_ << indent() << "my ($classname, $impl) = @_;" << endl << indent()
-               << "my $self     ={ impl => $impl };" << endl << endl << indent()
-               << "return bless($self,$classname);" << endl;
-
-    indent_down();
-
-    f_service_ << "}" << endl << endl;
-  }
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << "sub " << (*f_iter)->get_name() << "{" << endl;
-
-    indent_up();
-
-    f_service_ << indent() << "my ($self, $request) = @_;" << endl << endl;
-
-    const vector<t_field*>& args = (*f_iter)->get_arglist()->get_members();
-    vector<t_field*>::const_iterator a_iter;
-    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
-      t_type* atype = get_true_type((*a_iter)->get_type());
-      string req = "$request->{'" + (*a_iter)->get_name() + "'}";
-      f_service_ << indent() << "my $" << (*a_iter)->get_name() << " = (" << req << ") ? " << req
-                 << " : undef;" << endl;
-      if (atype->is_string() && ((t_base_type*)atype)->is_string_list()) {
-        f_service_ << indent() << "my @" << (*a_iter)->get_name() << " = split(/,/, $"
-                   << (*a_iter)->get_name() << ");" << endl << indent() << "$"
-                   << (*a_iter)->get_name() << " = \\@" << (*a_iter)->get_name() << endl;
-      }
-    }
-    f_service_ << indent() << "return $self->{impl}->" << (*f_iter)->get_name() << "("
-               << argument_list((*f_iter)->get_arglist()) << ");" << endl;
-    indent_down();
-    indent(f_service_) << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_perl_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  t_service* extends_s = tservice->get_extends();
-  if (extends_s != NULL) {
-    extends = perl_namespace(extends_s->get_program()) + extends_s->get_name();
-    extends_client = "use base qw(" + extends + "Client);";
-  }
-
-  f_service_ << "package " << perl_namespace(program_) << service_name_ << "Client;" << endl << endl
-             << extends_client << endl << "use base qw(" << perl_namespace(program_)
-             << service_name_ << "If);" << endl;
-
-  // Constructor function
-  f_service_ << "sub new {" << endl;
-
-  indent_up();
-
-  f_service_ << indent() << "my ($classname, $input, $output) = @_;" << endl << indent()
-             << "my $self      = {};" << endl;
-
-  if (!extends.empty()) {
-    f_service_ << indent() << "$self = $classname->SUPER::new($input, $output);" << endl;
-  } else {
-    f_service_ << indent() << "$self->{input}  = $input;" << endl << indent()
-               << "$self->{output} = defined $output ? $output : $input;" << endl << indent()
-               << "$self->{seqid}  = 0;" << endl;
-  }
-
-  f_service_ << indent() << "return bless($self,$classname);" << endl;
-
-  indent_down();
-
-  f_service_ << "}" << endl << endl;
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    f_service_ << "sub " << function_signature(*f_iter) << endl;
-
-    indent_up();
-
-    indent(f_service_) << indent() << "$self->send_" << funname << "(";
-
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "$" << (*fld_iter)->get_name();
-    }
-    f_service_ << ");" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_service_ << indent();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
-      }
-      f_service_ << "$self->recv_" << funname << "();" << endl;
-    }
-
-    indent_down();
-
-    f_service_ << "}" << endl << endl;
-
-    f_service_ << "sub send_" << function_signature(*f_iter) << endl;
-
-    indent_up();
-
-    std::string argsname = perl_namespace(tservice->get_program()) + service_name_ + "_"
-                           + (*f_iter)->get_name() + "_args";
-
-    // Serialize the request header
-    f_service_ << indent() << "$self->{output}->writeMessageBegin('" << (*f_iter)->get_name()
-               << "', " << ((*f_iter)->is_oneway() ? "TMessageType::ONEWAY" : "TMessageType::CALL")
-               << ", $self->{seqid});" << endl;
-
-    f_service_ << indent() << "my $args = new " << argsname << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "$args->{" << (*fld_iter)->get_name() << "} = $"
-                 << (*fld_iter)->get_name() << ";" << endl;
-    }
-
-    // Write to the stream
-    f_service_ << indent() << "$args->write($self->{output});" << endl << indent()
-               << "$self->{output}->writeMessageEnd();" << endl << indent()
-               << "$self->{output}->getTransport()->flush();" << endl;
-
-    indent_down();
-
-    f_service_ << "}" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_"
-                               + (*f_iter)->get_name() + "_result";
-      t_struct noargs(program_);
-
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs);
-      // Open function
-      f_service_ << endl << "sub " << function_signature(&recv_function) << endl;
-
-      indent_up();
-
-      f_service_ << indent() << "my $rseqid = 0;" << endl << indent() << "my $fname;" << endl
-                 << indent() << "my $mtype = 0;" << endl << endl;
-
-      f_service_ << indent() << "$self->{input}->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);"
-                 << endl << indent() << "if ($mtype == TMessageType::EXCEPTION) {" << endl
-                 << indent() << "  my $x = new TApplicationException();" << endl << indent()
-                 << "  $x->read($self->{input});" << endl << indent()
-                 << "  $self->{input}->readMessageEnd();" << endl << indent() << "  die $x;" << endl
-                 << indent() << "}" << endl;
-
-      f_service_ << indent() << "my $result = new " << resultname << "();" << endl << indent()
-                 << "$result->read($self->{input});" << endl;
-
-      f_service_ << indent() << "$self->{input}->readMessageEnd();" << endl << endl;
-
-      // Careful, only return result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "if (defined $result->{success} ) {" << endl << indent()
-                   << "  return $result->{success};" << endl << indent() << "}" << endl;
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "if (defined $result->{" << (*x_iter)->get_name() << "}) {"
-                   << endl << indent() << "  die $result->{" << (*x_iter)->get_name() << "};"
-                   << endl << indent() << "}" << endl;
-      }
-
-      // Careful, only return _result if not a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "return;" << endl;
-      } else {
-        f_service_ << indent() << "die \"" << (*f_iter)->get_name() << " failed: unknown result\";"
-                   << endl;
-      }
-
-      // Close function
-      indent_down();
-      f_service_ << "}" << endl;
-    }
-  }
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_perl_generator::generate_deserialize_field(ofstream& out,
-                                                  t_field* tfield,
-                                                  string prefix,
-                                                  bool inclass) {
-  (void)inclass;
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = tfield->get_name();
-
-  // Hack for when prefix is defined (always a hash ref)
-  if (!prefix.empty()) {
-    name = prefix + "{" + tfield->get_name() + "}";
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-    indent(out) << "$xfer += $input->";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << "readString(\\$" << name << ");";
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool(\\$" << name << ");";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte(\\$" << name << ");";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16(\\$" << name << ");";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32(\\$" << name << ");";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64(\\$" << name << ");";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble(\\$" << name << ");";
-        break;
-      default:
-        throw "compiler error: no PERL name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32(\\$" << name << ");";
-    }
-    out << endl;
-
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a variable. This makes two key assumptions,
- * first that there is a const char* variable named data that points to the
- * buffer for deserialization, and that there is a variable protocol which
- * is a reference to a TProtocol serialization object.
- */
-void t_perl_generator::generate_deserialize_struct(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   string prefix) {
-  out << indent() << "$" << prefix << " = new " << perl_namespace(tstruct->get_program())
-      << tstruct->get_name() << "();" << endl << indent() << "$xfer += $" << prefix
-      << "->read($input);" << endl;
-}
-
-void t_perl_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
-
-  t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  out << indent() << "my $" << size << " = 0;" << endl;
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << ktype << " = 0;"
-        << endl << indent() << "my $" << vtype << " = 0;" << endl;
-
-    out << indent() << "$xfer += $input->readMapBegin("
-        << "\\$" << ktype << ", \\$" << vtype << ", \\$" << size << ");" << endl;
-
-  } else if (ttype->is_set()) {
-
-    out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << etype << " = 0;"
-        << endl << indent() << "$xfer += $input->readSetBegin("
-        << "\\$" << etype << ", \\$" << size << ");" << endl;
-
-  } else if (ttype->is_list()) {
-
-    out << indent() << "$" << prefix << " = [];" << endl << indent() << "my $" << etype << " = 0;"
-        << endl << indent() << "$xfer += $input->readListBegin("
-        << "\\$" << etype << ", \\$" << size << ");" << endl;
-  }
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) << "for (my $" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")"
-              << endl;
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  scope_down(out);
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "$xfer += $input->readMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "$xfer += $input->readSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "$xfer += $input->readListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_perl_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("key");
-  string val = tmp("val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  indent(out) << declare_field(&fkey, true, true) << endl;
-  indent(out) << declare_field(&fval, true, true) << endl;
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << "$" << prefix << "->{$" << key << "} = $" << val << ";" << endl;
-}
-
-void t_perl_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  indent(out) << "my $" << elem << " = undef;" << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << "$" << prefix << "->{$" << elem << "} = 1;" << endl;
-}
-
-void t_perl_generator::generate_deserialize_list_element(ofstream& out,
-                                                         t_list* tlist,
-                                                         string prefix) {
-  string elem = tmp("elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  indent(out) << "my $" << elem << " = undef;" << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << "push(@{$" << prefix << "},$" << elem << ");" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_perl_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + "{" + tfield->get_name() + "}");
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + "{" + tfield->get_name() + "}");
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = tfield->get_name();
-
-    // Hack for when prefix is defined (always a hash ref)
-    if (!prefix.empty())
-      name = prefix + "{" + tfield->get_name() + "}";
-
-    indent(out) << "$xfer += $output->";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << "writeString($" << name << ");";
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool($" << name << ");";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte($" << name << ");";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16($" << name << ");";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32($" << name << ");";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64($" << name << ");";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble($" << name << ");";
-        break;
-      default:
-        throw "compiler error: no PERL name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32($" << name << ");";
-    }
-    out << endl;
-
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_perl_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << "$xfer += $" << prefix << "->write($output);" << endl;
-}
-
-/**
- * Writes out a container
- */
-void t_perl_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    indent(out) << "$xfer += $output->writeMapBegin("
-                << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
-                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
-                << "scalar(keys %{$" << prefix << "}));" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "$xfer += $output->writeSetBegin("
-                << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
-                << "scalar(@{$" << prefix << "}));" << endl;
-
-  } else if (ttype->is_list()) {
-
-    indent(out) << "$xfer += $output->writeListBegin("
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", "
-                << "scalar(@{$" << prefix << "}));" << endl;
-  }
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    string kiter = tmp("kiter");
-    string viter = tmp("viter");
-    indent(out) << "while( my ($" << kiter << ",$" << viter << ") = each %{$" << prefix << "}) "
-                << endl;
-
-    scope_up(out);
-    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
-    scope_down(out);
-
-  } else if (ttype->is_set()) {
-    string iter = tmp("iter");
-    indent(out) << "foreach my $" << iter << " (@{$" << prefix << "})" << endl;
-    scope_up(out);
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-    scope_down(out);
-
-  } else if (ttype->is_list()) {
-    string iter = tmp("iter");
-    indent(out) << "foreach my $" << iter << " (@{$" << prefix << "}) " << endl;
-    scope_up(out);
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-    scope_down(out);
-  }
-
-  scope_down(out);
-
-  if (ttype->is_map()) {
-    indent(out) << "$xfer += $output->writeMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "$xfer += $output->writeSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "$xfer += $output->writeListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Serializes the members of a map.
- *
- */
-void t_perl_generator::generate_serialize_map_element(ofstream& out,
-                                                      t_map* tmap,
-                                                      string kiter,
-                                                      string viter) {
-  t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(out, &kfield);
-
-  t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(out, &vfield);
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_perl_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield);
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_perl_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield);
-}
-
-/**
- * Declares a field, which may include initialization as necessary.
- *
- * @param ttype The type
- */
-string t_perl_generator::declare_field(t_field* tfield, bool init, bool obj) {
-  string result = "my $" + tfield->get_name();
-  if (init) {
-    t_type* type = get_true_type(tfield->get_type());
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        break;
-      case t_base_type::TYPE_STRING:
-        result += " = ''";
-        break;
-      case t_base_type::TYPE_BOOL:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        result += " = 0.0";
-        break;
-      default:
-        throw "compiler error: no PERL initializer for base type "
-            + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      result += " = 0";
-    } else if (type->is_container()) {
-      result += " = []";
-    } else if (type->is_struct() || type->is_xception()) {
-      if (obj) {
-        result += " = new " + perl_namespace(type->get_program()) + type->get_name() + "()";
-      } else {
-        result += " = undef";
-      }
-    }
-  }
-  return result + ";";
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_perl_generator::function_signature(t_function* tfunction, string prefix) {
-
-  string str;
-
-  str = prefix + tfunction->get_name() + "{\n";
-  str += "  my $self = shift;\n";
-
-  // Need to create perl function arg inputs
-  const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    str += "  my $" + (*f_iter)->get_name() + " = shift;\n";
-  }
-
-  return str;
-}
-
-/**
- * Renders a field list
- */
-string t_perl_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    result += "$" + (*f_iter)->get_name();
-  }
-  return result;
-}
-
-/**
- * Converts the parse type to a C++ enum string for the given type.
- */
-string t_perl_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "TType::STRING";
-    case t_base_type::TYPE_BOOL:
-      return "TType::BOOL";
-    case t_base_type::TYPE_I8:
-      return "TType::BYTE";
-    case t_base_type::TYPE_I16:
-      return "TType::I16";
-    case t_base_type::TYPE_I32:
-      return "TType::I32";
-    case t_base_type::TYPE_I64:
-      return "TType::I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "TType::DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "TType::I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType::STRUCT";
-  } else if (type->is_map()) {
-    return "TType::MAP";
-  } else if (type->is_set()) {
-    return "TType::SET";
-  } else if (type->is_list()) {
-    return "TType::LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-THRIFT_REGISTER_GENERATOR(perl, "Perl", "")


[22/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc
new file mode 100644
index 0000000..7d4e4f0
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc
@@ -0,0 +1,4562 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include <ctype.h>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/* forward declarations */
+string initial_caps_to_underscores(string name);
+string underscores_to_initial_caps(string name);
+string to_upper_case(string name);
+string to_lower_case(string name);
+
+/**
+ * C code generator, using glib for C typing.
+ */
+class t_c_glib_generator : public t_oop_generator {
+public:
+  /* constructor */
+  t_c_glib_generator(t_program* program,
+                     const map<string, string>& parsed_options,
+                     const string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* set the output directory */
+    this->out_dir_base_ = "gen-c_glib";
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option c_glib:" + iter->first;
+    }
+
+    /* set the namespace */
+    this->nspace = program_->get_namespace("c_glib");
+
+    if (this->nspace.empty()) {
+      this->nspace = "";
+      this->nspace_u = "";
+      this->nspace_uc = "";
+      this->nspace_lc = "";
+    } else {
+      /* replace dots with underscores */
+      char* tmp = strdup(this->nspace.c_str());
+      for (unsigned int i = 0; i < strlen(tmp); i++) {
+        if (tmp[i] == '.') {
+          tmp[i] = '_';
+        }
+      }
+      this->nspace = string(tmp, strlen(tmp));
+      free(tmp);
+
+      /* clean up the namespace for C.
+       * An input of 'namespace foo' should result in:
+       *  - nspace = foo       - for thrift objects and typedefs
+       *  - nspace_u = Foo     - for internal GObject prefixes
+       *  - nspace_uc = FOO_   - for macro prefixes
+       *  - nspace_lc = foo_   - for filename and method prefixes
+       * The underscores are there since uc and lc strings are used as file and
+       * variable prefixes.
+       */
+      this->nspace_u = initial_caps_to_underscores(this->nspace);
+      this->nspace_uc = to_upper_case(this->nspace_u) + "_";
+      this->nspace_lc = to_lower_case(this->nspace_u) + "_";
+    }
+  }
+
+  /* initialization and destruction */
+  void init_generator();
+  void close_generator();
+
+  /* generation functions */
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_consts(vector<t_const*> consts);
+  void generate_struct(t_struct* tstruct);
+  void generate_service(t_service* tservice);
+  void generate_xception(t_struct* tstruct);
+
+private:
+  /* file streams */
+  ofstream f_types_;
+  ofstream f_types_impl_;
+  ofstream f_header_;
+  ofstream f_service_;
+
+  /* namespace variables */
+  string nspace;
+  string nspace_u;
+  string nspace_uc;
+  string nspace_lc;
+
+  /* helper functions */
+  bool is_complex_type(t_type* ttype);
+  bool is_numeric(t_type* ttype);
+  string type_name(t_type* ttype, bool in_typedef = false, bool is_const = false);
+  string property_type_name(t_type* ttype, bool in_typedef = false, bool is_const = false);
+  string base_type_name(t_type* type);
+  string type_to_enum(t_type* type);
+  string constant_literal(t_type* type, t_const_value* value);
+  string constant_value(string name, t_type* type, t_const_value* value);
+  string constant_value_with_storage(string name, t_type* type, t_const_value* value);
+  string function_signature(t_function* tfunction);
+  string argument_list(t_struct* tstruct);
+  string xception_list(t_struct* tstruct);
+  string declare_field(t_field* tfield,
+                       bool init = false,
+                       bool pointer = false,
+                       bool constant = false,
+                       bool reference = false);
+  void declare_local_variable(ofstream& out, t_type* ttype, string& base_name, bool for_hash_table);
+  void declore_local_variable_for_write(ofstream& out, t_type* ttype, string& base_name);
+
+  /* generation functions */
+  void generate_const_initializer(string name,
+                                  t_type* type,
+                                  t_const_value* value,
+                                  bool top_level = false);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_handler(t_service* tservice);
+  void generate_service_processor(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_object(t_struct* tstruct);
+  void generate_struct_writer(ofstream& out,
+                              t_struct* tstruct,
+                              string this_name,
+                              string this_get = "",
+                              bool is_function = true);
+  void generate_struct_reader(ofstream& out,
+                              t_struct* tstruct,
+                              string this_name,
+                              string this_get = "",
+                              bool is_function = true);
+
+  void generate_serialize_field(ofstream& out,
+                                t_field* tfield,
+                                string prefix,
+                                string suffix,
+                                int error_ret);
+  void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix, int error_ret);
+  void generate_serialize_container(ofstream& out, t_type* ttype, string prefix, int error_ret);
+  void generate_serialize_map_element(ofstream& out,
+                                      t_map* tmap,
+                                      string key,
+                                      string value,
+                                      int error_ret);
+  void generate_serialize_set_element(ofstream& out, t_set* tset, string element, int error_ret);
+  void generate_serialize_list_element(ofstream& out,
+                                       t_list* tlist,
+                                       string list,
+                                       string index,
+                                       int error_ret);
+
+  void generate_deserialize_field(ofstream& out,
+                                  t_field* tfield,
+                                  string prefix,
+                                  string suffix,
+                                  int error_ret,
+                                  bool allocate = true);
+  void generate_deserialize_struct(ofstream& out,
+                                   t_struct* tstruct,
+                                   string prefix,
+                                   int error_ret,
+                                   bool allocate = true);
+  void generate_deserialize_container(ofstream& out, t_type* ttype, string prefix, int error_ret);
+  void generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix, int error_ret);
+  void generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix, int error_ret);
+  void generate_deserialize_list_element(ofstream& out,
+                                         t_list* tlist,
+                                         string prefix,
+                                         string index,
+                                         int error_ret);
+
+  string generate_new_hash_from_type(t_type* key, t_type* value);
+  string generate_new_array_from_type(t_type* ttype);
+
+  string generate_free_func_from_type(t_type* ttype);
+  string generate_hash_func_from_type(t_type* ttype);
+  string generate_cmp_func_from_type(t_type* ttype);
+};
+
+/**
+ * Prepare for file generation by opening up the necessary file
+ * output streams.
+ */
+void t_c_glib_generator::init_generator() {
+  /* create output directory */
+  MKDIR(get_out_dir().c_str());
+
+  string program_name_u = initial_caps_to_underscores(program_name_);
+  string program_name_uc = to_upper_case(program_name_u);
+  string program_name_lc = to_lower_case(program_name_u);
+
+  /* create output files */
+  string f_types_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.h";
+  f_types_.open(f_types_name.c_str());
+  string f_types_impl_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.c";
+  f_types_impl_.open(f_types_impl_name.c_str());
+
+  /* add thrift boilerplate headers */
+  f_types_ << autogen_comment();
+  f_types_impl_ << autogen_comment();
+
+  /* include inclusion guard */
+  f_types_ << "#ifndef " << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << "#define "
+           << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << endl;
+
+  /* include base types */
+  f_types_ << "/* base includes */" << endl << "#include <glib-object.h>" << endl
+           << "#include <thrift/c_glib/thrift_struct.h>" << endl
+           << "#include <thrift/c_glib/protocol/thrift_protocol.h>" << endl;
+
+  /* include other thrift includes */
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    f_types_ << "/* other thrift includes */" << endl << "#include \"" << this->nspace_lc
+             << initial_caps_to_underscores(includes[i]->get_name()) << "_types.h\"" << endl;
+  }
+  f_types_ << endl;
+
+  /* include custom headers */
+  const vector<string>& c_includes = program_->get_c_includes();
+  f_types_ << "/* custom thrift includes */" << endl;
+  for (size_t i = 0; i < c_includes.size(); ++i) {
+    if (c_includes[i][0] == '<') {
+      f_types_ << "#include " << c_includes[i] << endl;
+    } else {
+      f_types_ << "#include \"" << c_includes[i] << "\"" << endl;
+    }
+  }
+  f_types_ << endl;
+
+  /* include math.h (for "INFINITY") in the implementation file, in case we
+     encounter a struct with a member of type double */
+  f_types_impl_ << endl << "#include <math.h>" << endl;
+
+  // include the types file
+  f_types_impl_ << endl << "#include \"" << this->nspace_lc << program_name_u << "_types.h\""
+                << endl << "#include <thrift/c_glib/thrift.h>" << endl << endl;
+
+  f_types_ << "/* begin types */" << endl << endl;
+}
+
+/**
+ *  Finish up generation and close all file streams.
+ */
+void t_c_glib_generator::close_generator() {
+  string program_name_uc = to_upper_case(initial_caps_to_underscores(program_name_));
+
+  /* end the header inclusion guard */
+  f_types_ << "#endif /* " << this->nspace_uc << program_name_uc << "_TYPES_H */" << endl;
+
+  /* close output file */
+  f_types_.close();
+  f_types_impl_.close();
+}
+
+/**
+ * Generates a Thrift typedef in C code.  For example:
+ *
+ * Thrift:
+ * typedef map<i32,i32> SomeMap
+ *
+ * C:
+ * typedef GHashTable * ThriftSomeMap;
+ */
+void t_c_glib_generator::generate_typedef(t_typedef* ttypedef) {
+  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << this->nspace
+           << ttypedef->get_symbolic() << ";" << endl << endl;
+}
+
+/**
+ * Generates a C enumeration.  For example:
+ *
+ * Thrift:
+ * enum MyEnum {
+ *   ONE = 1,
+ *   TWO
+ * }
+ *
+ * C:
+ * enum _ThriftMyEnum {
+ *   THRIFT_MY_ENUM_ONE = 1,
+ *   THRIFT_MY_ENUM_TWO
+ * };
+ * typedef enum _ThriftMyEnum ThriftMyEnum;
+ */
+void t_c_glib_generator::generate_enum(t_enum* tenum) {
+  string name = tenum->get_name();
+  string name_uc = to_upper_case(initial_caps_to_underscores(name));
+
+  f_types_ << indent() << "enum _" << this->nspace << name << " {" << endl;
+
+  indent_up();
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  bool first = true;
+
+  /* output each of the enumeration elements */
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_types_ << "," << endl;
+    }
+
+    f_types_ << indent() << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name();
+    f_types_ << " = " << (*c_iter)->get_value();
+  }
+
+  indent_down();
+  f_types_ << endl << "};" << endl << "typedef enum _" << this->nspace << name << " "
+           << this->nspace << name << ";" << endl << endl;
+
+  f_types_ << "/* return the name of the constant */" << endl;
+  f_types_ << "const char *" << endl;
+  f_types_ << "toString_" << name << "(int value); " << endl << endl;
+  ;
+  f_types_impl_ << "/* return the name of the constant */" << endl;
+  f_types_impl_ << "const char *" << endl;
+  f_types_impl_ << "toString_" << name << "(int value) " << endl;
+  f_types_impl_ << "{" << endl;
+  f_types_impl_ << "  static __thread char buf[16] = {0};" << endl;
+  f_types_impl_ << "  switch(value) {" << endl;
+  std::set<int> done;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    // Skipping duplicate value
+    if (done.find(value) == done.end()) {
+      done.insert(value);
+      f_types_impl_ << "  case " << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name()
+                    << ":"
+                    << "return \"" << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name()
+                    << "\";" << endl;
+    }
+  }
+  f_types_impl_ << "  default: g_snprintf(buf, 16, \"%d\", value); return buf;" << endl;
+  f_types_impl_ << "  }" << endl;
+  f_types_impl_ << "}" << endl << endl;
+}
+
+/**
+ * Generates Thrift constants in C code.
+ */
+void t_c_glib_generator::generate_consts(vector<t_const*> consts) {
+  f_types_ << "/* constants */" << endl;
+  f_types_impl_ << "/* constants */" << endl;
+
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    string name_uc = to_upper_case(name);
+    string name_lc = to_lower_case(name);
+    t_type* type = (*c_iter)->get_type();
+    t_const_value* value = (*c_iter)->get_value();
+
+    if (is_complex_type(type)) {
+      f_types_ << type_name(type) << indent() << this->nspace_lc << name_lc
+               << "_constant();" << endl;
+    }
+
+    f_types_ << indent() << "#define " << this->nspace_uc << name_uc << " "
+             << constant_value(name_lc, type, value) << endl;
+
+    generate_const_initializer(name_lc, type, value, true);
+  }
+
+  f_types_ << endl;
+  f_types_impl_ << endl;
+}
+
+/**
+ * Generate Thrift structs in C code, as GObjects.  Example:
+ *
+ * Thrift:
+ * struct Bonk
+ * {
+ *   1: string message,
+ *   2: i32 type
+ * }
+ *
+ * C GObject instance header:
+ * struct _ThriftBonk
+ * {
+ *   GObject parent;
+ *
+ *   gchar * message;
+ *   gint32 type;
+ * };
+ * typedef struct _ThriftBonk ThriftBonk
+ * // ... additional GObject boilerplate ...
+ */
+void t_c_glib_generator::generate_struct(t_struct* tstruct) {
+  f_types_ << "/* struct " << tstruct->get_name() << " */" << endl;
+  generate_object(tstruct);
+}
+
+/**
+ * Generate C code to represent Thrift services.  Creates a new GObject
+ * which can be used to access the service.
+ */
+void t_c_glib_generator::generate_service(t_service* tservice) {
+  string svcname_u = initial_caps_to_underscores(tservice->get_name());
+  string svcname_uc = this->nspace_uc + to_upper_case(svcname_u);
+  string filename = this->nspace_lc + to_lower_case(svcname_u);
+
+  // make output files
+  string f_header_name = get_out_dir() + filename + ".h";
+  f_header_.open(f_header_name.c_str());
+
+  string program_name_u = initial_caps_to_underscores(program_name_);
+  string program_name_lc = to_lower_case(program_name_u);
+
+  // add header file boilerplate
+  f_header_ << autogen_comment();
+
+  // add an inclusion guard
+  f_header_ << "#ifndef " << svcname_uc << "_H" << endl << "#define " << svcname_uc << "_H" << endl
+            << endl;
+
+  // add standard includes
+  f_header_ << "#include <thrift/c_glib/processor/thrift_dispatch_processor.h>" << endl << endl;
+  f_header_ << "#include \"" << this->nspace_lc << program_name_lc << "_types.h\"" << endl;
+
+  // if we are inheriting from another service, include its header
+  t_service* extends_service = tservice->get_extends();
+  if (extends_service != NULL) {
+    f_header_ << "#include \"" << this->nspace_lc
+              << to_lower_case(initial_caps_to_underscores(extends_service->get_name())) << ".h\""
+              << endl;
+  }
+  f_header_ << endl;
+
+  // create the service implementation
+  string f_service_name = get_out_dir() + filename + ".c";
+  f_service_.open(f_service_name.c_str());
+
+  // add the boilerplace header
+  f_service_ << autogen_comment();
+
+  // include the headers
+  f_service_ << "#include <string.h>" << endl << "#include <thrift/c_glib/thrift.h>" << endl
+             << "#include <thrift/c_glib/thrift_application_exception.h>" << endl << "#include \""
+             << filename << ".h\"" << endl << endl;
+
+  // generate the service-helper classes
+  generate_service_helpers(tservice);
+
+  // generate the client objects
+  generate_service_client(tservice);
+
+  // generate the server objects
+  generate_service_server(tservice);
+
+  // end the header inclusion guard
+  f_header_ << "#endif /* " << svcname_uc << "_H */" << endl;
+
+  // close the files
+  f_service_.close();
+  f_header_.close();
+}
+
+/**
+ *
+ */
+void t_c_glib_generator::generate_xception(t_struct* tstruct) {
+  string name = tstruct->get_name();
+  string name_u = initial_caps_to_underscores(name);
+  string name_lc = to_lower_case(name_u);
+  string name_uc = to_upper_case(name_u);
+
+  generate_object(tstruct);
+
+  f_types_ << "/* exception */" << endl
+           << "typedef enum" << endl
+           << "{" << endl;
+  indent_up();
+  f_types_ << indent() << this->nspace_uc << name_uc << "_ERROR_CODE" << endl;
+  indent_down();
+  f_types_ << "} " << this->nspace << name << "Error;" << endl
+           << endl
+           << "GQuark " << this->nspace_lc << name_lc
+           << "_error_quark (void);" << endl
+           << "#define " << this->nspace_uc << name_uc << "_ERROR ("
+           << this->nspace_lc << name_lc << "_error_quark())" << endl
+           << endl
+           << endl;
+
+  f_types_impl_ << "/* define the GError domain for exceptions */" << endl << "#define "
+                << this->nspace_uc << name_uc << "_ERROR_DOMAIN \"" << this->nspace_lc << name_lc
+                << "_error_quark\"" << endl << "GQuark" << endl << this->nspace_lc << name_lc
+                << "_error_quark (void)" << endl << "{" << endl
+                << "  return g_quark_from_static_string (" << this->nspace_uc << name_uc
+                << "_ERROR_DOMAIN);" << endl << "}" << endl << endl;
+}
+
+/********************
+ * HELPER FUNCTIONS *
+ ********************/
+
+/**
+ * Returns true if ttype is not a primitive.
+ */
+bool t_c_glib_generator::is_complex_type(t_type* ttype) {
+  ttype = get_true_type(ttype);
+
+  return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
+}
+
+bool t_c_glib_generator::is_numeric(t_type* ttype) {
+  return ttype->is_enum() || (ttype->is_base_type() && !ttype->is_string());
+}
+
+/**
+ * Maps a Thrift t_type to a C type.
+ */
+string t_c_glib_generator::type_name(t_type* ttype, bool in_typedef, bool is_const) {
+  if (ttype->is_base_type()) {
+    string bname = base_type_name(ttype);
+
+    if (is_const) {
+      return "const " + bname;
+    } else {
+      return bname;
+    }
+  }
+
+  if (ttype->is_container()) {
+    string cname;
+
+    t_container* tcontainer = (t_container*)ttype;
+    if (tcontainer->has_cpp_name()) {
+      cname = tcontainer->get_cpp_name();
+    } else if (ttype->is_map()) {
+      cname = "GHashTable";
+    } else if (ttype->is_set()) {
+      // since a set requires unique elements, use a GHashTable, and
+      // populate the keys and values with the same data, using keys for
+      // the actual writes and reads.
+      // TODO: discuss whether or not to implement TSet, THashSet or GHashSet
+      cname = "GHashTable";
+    } else if (ttype->is_list()) {
+      t_type* etype = ((t_list*)ttype)->get_elem_type();
+      if (etype->is_void()) {
+        throw std::runtime_error("compiler error: list element type cannot be void");
+      }
+      // TODO: investigate other implementations besides GPtrArray
+      cname = is_numeric(etype) ? "GArray" : "GPtrArray";
+    }
+
+    /* Omit the dereference operator if we are aliasing this type within a
+       typedef, to allow the type to be used more naturally in client code;
+       otherwise, include it */
+    if (!in_typedef) {
+      cname += " *";
+    }
+
+    if (is_const) {
+      return "const " + cname;
+    } else {
+      return cname;
+    }
+  }
+
+  // check for a namespace
+  string pname = this->nspace + ttype->get_name();
+
+  if (is_complex_type(ttype)) {
+    pname += " *";
+  }
+
+  if (is_const) {
+    return "const " + pname;
+  } else {
+    return pname;
+  }
+}
+
+/**
+ * Maps a Thrift primitive to the type needed to hold its value when used as an
+ * object property.
+ *
+ * This method is needed because all integer properties of width less than 64
+ * bits map to the same type, gint, as opposed to their width-specific type
+ * (gint8, gint16 or gint32).
+ */
+string t_c_glib_generator::property_type_name(t_type* ttype, bool in_typedef, bool is_const) {
+  string result;
+
+  if (ttype->is_base_type()) {
+    switch (((t_base_type*)ttype)->get_base()) {
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      if (is_const) {
+        result = "const gint";
+      } else {
+        result = "gint";
+      }
+      break;
+
+    default:
+      result = type_name(ttype, in_typedef, is_const);
+    }
+  } else {
+    result = type_name(ttype, in_typedef, is_const);
+  }
+
+  return result;
+}
+
+/**
+ * Maps a Thrift primitive to a C primitive.
+ */
+string t_c_glib_generator::base_type_name(t_type* type) {
+  if (type->is_enum()) {
+    return type_name(type);
+  }
+  if (!type->is_base_type()) {
+    throw std::invalid_argument("Only base types are suppported.");
+  }
+  t_base_type* base_type = reinterpret_cast<t_base_type*>(type);
+  t_base_type::t_base tbase = base_type->get_base();
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (base_type->is_binary()) {
+      return "GByteArray *";
+    } else {
+      return "gchar *";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "gboolean";
+  case t_base_type::TYPE_I8:
+    return "gint8";
+  case t_base_type::TYPE_I16:
+    return "gint16";
+  case t_base_type::TYPE_I32:
+    return "gint32";
+  case t_base_type::TYPE_I64:
+    return "gint64";
+  case t_base_type::TYPE_DOUBLE:
+    return "gdouble";
+  default:
+    throw std::logic_error("compiler error: no C base type name for base type "
+                           + t_base_type::t_base_name(tbase));
+  }
+}
+
+/**
+ * Returns a member of the ThriftType C enumeration in thrift_protocol.h
+ * for a Thrift type.
+ */
+string t_c_glib_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "T_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "T_BOOL";
+    case t_base_type::TYPE_I8:
+      return "T_BYTE";
+    case t_base_type::TYPE_I16:
+      return "T_I16";
+    case t_base_type::TYPE_I32:
+      return "T_I32";
+    case t_base_type::TYPE_I64:
+      return "T_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "T_DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "T_I32";
+  } else if (type->is_struct()) {
+    return "T_STRUCT";
+  } else if (type->is_xception()) {
+    return "T_STRUCT";
+  } else if (type->is_map()) {
+    return "T_MAP";
+  } else if (type->is_set()) {
+    return "T_SET";
+  } else if (type->is_list()) {
+    return "T_LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Returns a Thrift constant formatted as a literal for inclusion in C code.
+ */
+string t_c_glib_generator::constant_literal(t_type* type, t_const_value* value) {
+  ostringstream render;
+
+  if (type->is_base_type()) {
+    /* primitives */
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << "\"" + value->get_string() + "\"";
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() != 0) ? "TRUE" : "FALSE");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      render << value->get_double();
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else {
+    t_const_value::t_const_value_type value_type = value->get_type();
+
+    switch (value_type) {
+    case t_const_value::CV_IDENTIFIER:
+      render << value->get_integer();
+      break;
+    case t_const_value::CV_LIST:
+      render << "{ ";
+      {
+        t_type* elem_type = ((t_list*)type)->get_elem_type();
+        const vector<t_const_value*>& list = value->get_list();
+        vector<t_const_value*>::const_iterator list_iter;
+
+        if (list.size() > 0) {
+          list_iter = list.begin();
+          render << constant_literal(elem_type, *list_iter);
+
+          while (++list_iter != list.end()) {
+            render << ", " << constant_literal(elem_type, *list_iter);
+          }
+        }
+      }
+      render << " }";
+      break;
+    case t_const_value::CV_MAP:
+    default:
+      render << "NULL /* not supported */";
+    }
+  }
+
+  return render.str();
+}
+
+/**
+ * Returns C code that represents a Thrift constant.
+ */
+string t_c_glib_generator::constant_value(string name, t_type* type, t_const_value* value) {
+  ostringstream render;
+
+  if (type->is_base_type()) {
+    /* primitives */
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << "g_strdup (\"" + value->get_string() + "\")";
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() != 0) ? 1 : 0);
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << "G_GINT64_CONSTANT (" << value->get_integer() << ")";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << "(" << type_name(type) << ")" << value->get_integer();
+  } else if (is_complex_type(type)) {
+    render << "(" << this->nspace_lc << to_lower_case(name) << "_constant())";
+  } else {
+    render << "NULL /* not supported */";
+  }
+
+  return render.str();
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_c_glib_generator::function_signature(t_function* tfunction) {
+  t_type* ttype = tfunction->get_returntype();
+  t_struct* arglist = tfunction->get_arglist();
+  t_struct* xlist = tfunction->get_xceptions();
+  string fname = initial_caps_to_underscores(tfunction->get_name());
+
+  bool has_return = !ttype->is_void();
+  bool has_args = arglist->get_members().size() == 0;
+  bool has_xceptions = xlist->get_members().size() == 0;
+  return "gboolean " + this->nspace_lc + fname + " (" + this->nspace + service_name_ + "If * iface"
+         + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+         + (has_args ? "" : (", " + argument_list(arglist)))
+         + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError ** error)";
+}
+
+/**
+ * Renders a field list
+ *
+ * @param tstruct The struct definition
+ * @return Comma sepearated list of all field names in that struct
+ */
+string t_c_glib_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += type_name((*f_iter)->get_type(), false, true) + " " + (*f_iter)->get_name();
+  }
+  return result;
+}
+
+/**
+ * Renders mutable exception lists
+ *
+ * @param tstruct The struct definition
+ * @return Comma sepearated list of all field names in that struct
+ */
+string t_c_glib_generator::xception_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += type_name((*f_iter)->get_type(), false, false) + "* " + (*f_iter)->get_name();
+  }
+  return result;
+}
+
+/**
+ * Declares a field, including any necessary initialization.
+ */
+string t_c_glib_generator::declare_field(t_field* tfield,
+                                         bool init,
+                                         bool pointer,
+                                         bool constant,
+                                         bool reference) {
+  string result = "";
+  if (constant) {
+    result += "const ";
+  }
+  result += type_name(tfield->get_type());
+  if (pointer) {
+    result += "*";
+  }
+  if (reference) {
+    result += "*";
+  }
+  result += " " + tfield->get_name();
+  if (init) {
+    t_type* type = get_true_type(tfield->get_type());
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        break;
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+        result += " = 0";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = (gdouble) 0";
+        break;
+      case t_base_type::TYPE_STRING:
+        result += " = NULL";
+        break;
+      default:
+        throw "compiler error: no C intializer for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      result += " = (" + type_name(type) + ") 0";
+    } else if (type->is_struct() || type->is_container()) {
+      result += " = NULL";
+    }
+  }
+
+  if (!reference) {
+    result += ";";
+  }
+
+  return result;
+}
+
+string t_c_glib_generator::constant_value_with_storage(string fname,
+                                                       t_type* etype,
+                                                       t_const_value* value) {
+  ostringstream render;
+  if (is_numeric(etype)) {
+    render << "    " << type_name(etype) << " *" << fname << " = "
+           << "g_new (" << base_type_name(etype) << ", 1);" << endl
+           << "    *" << fname << " = " << constant_value(fname, (t_type*)etype, value) << ";"
+           << endl;
+  } else {
+    render << "    " << type_name(etype) << " " << fname << " = "
+           << constant_value(fname, (t_type*)etype, value) << ";" << endl;
+  }
+  return render.str();
+}
+
+/**
+ * Generates C code that initializes complex constants.
+ */
+void t_c_glib_generator::generate_const_initializer(string name,
+                                                    t_type* type,
+                                                    t_const_value* value,
+                                                    bool top_level) {
+  string name_u = initial_caps_to_underscores(name);
+  string name_lc = to_lower_case(name_u);
+  string type_u = initial_caps_to_underscores(type->get_name());
+  string type_uc = to_upper_case(type_u);
+  string maybe_static = top_level ? "" : "static ";
+
+  if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    ostringstream initializers;
+
+    // initialize any constants that may be referenced by this initializer
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      string field_name = "";
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+          field_name = (*f_iter)->get_name();
+          break;
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field "
+          + v_iter->first->get_string();
+      }
+      field_name = tmp(field_name);
+
+      generate_const_initializer(name + "_constant_" + field_name,
+                                 field_type,
+                                 v_iter->second);
+      initializers << "    constant->" << v_iter->first->get_string() << " = "
+                   << constant_value(name + "_constant_" + field_name,
+                                     field_type,
+                                     v_iter->second) << ";" << endl
+                   << "    constant->__isset_" << v_iter->first->get_string()
+                   << " = TRUE;" << endl;
+    }
+
+    // implement the initializer
+    f_types_impl_ << maybe_static << this->nspace << type->get_name() << " *"
+                  << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static " << this->nspace << type->get_name()
+                  << " *constant = NULL;" << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "constant = g_object_new (" << this->nspace_uc
+                  << "TYPE_" << type_uc << ", NULL);" << endl
+                  << initializers.str();
+    scope_down(f_types_impl_);
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      string field_name = "";
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+          field_name = (*f_iter)->get_name();
+          break;
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field "
+          + v_iter->first->get_string();
+      }
+      field_name = tmp(field_name);
+    }
+
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  } else if (type->is_list()) {
+    string list_type = "GPtrArray *";
+    string free_func
+        = generate_free_func_from_type(reinterpret_cast<t_list*>(type)->get_elem_type());
+    string list_initializer = "g_ptr_array_new_with_free_func (" + free_func + ");";
+    string list_appender = "g_ptr_array_add";
+    bool list_variable = false;
+
+    t_type* etype = ((t_list*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    ostringstream initializers;
+    ostringstream appenders;
+
+    list_initializer = generate_new_array_from_type(etype);
+    if (etype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)etype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot determine array type";
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+      case t_base_type::TYPE_DOUBLE:
+        list_type = "GArray *";
+        list_appender = "g_array_append_val";
+        list_variable = true;
+        break;
+      case t_base_type::TYPE_STRING:
+        break;
+      default:
+        throw "compiler error: no array info for type";
+      }
+    } else if (etype->is_enum()) {
+      list_type = "GArray *";
+      list_appender = "g_array_append_val";
+      list_variable = true;
+    }
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string fname = tmp(name);
+
+      generate_const_initializer(fname, etype, (*v_iter));
+      if (list_variable) {
+        initializers << "    " << type_name(etype) << " " << fname << " = "
+                     << constant_value(fname, (t_type*)etype, (*v_iter)) << ";"
+                     << endl;
+        appenders << "    " << list_appender << "(constant, " << fname << ");"
+                  << endl;
+      } else {
+        appenders << "    " << list_appender << "(constant, "
+                  << constant_value(fname, (t_type*)etype, (*v_iter)) << ");"
+                  << endl;
+      }
+    }
+
+    f_types_impl_ << maybe_static << list_type << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static " << list_type << " constant = NULL;"
+                  << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    if (!initializers.str().empty()) {
+      f_types_impl_ << initializers.str()
+                    << endl;
+    }
+    f_types_impl_ << indent() << "constant = " << list_initializer << endl
+                  << appenders.str();
+    scope_down(f_types_impl_);
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    ostringstream initializers;
+    ostringstream appenders;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string fname = tmp(name);
+      string ptr = is_numeric(etype) ? "*" : "";
+      generate_const_initializer(fname, etype, (*v_iter));
+      initializers << constant_value_with_storage(fname, (t_type*)etype, *v_iter);
+      appenders << "    g_hash_table_insert (constant, " << fname << ", 0);" << endl;
+    }
+
+    f_types_impl_ << maybe_static << "GHashTable *" << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << initializers.str() << endl
+                  << indent() << "constant = " << generate_new_hash_from_type(etype, NULL) << endl
+                  << appenders.str();
+    scope_down(f_types_impl_);
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    ostringstream initializers;
+    ostringstream appenders;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string fname = tmp(name);
+      string kname = fname + "key";
+      string vname = fname + "val";
+      generate_const_initializer(kname, ktype, v_iter->first);
+      generate_const_initializer(vname, vtype, v_iter->second);
+
+      initializers << constant_value_with_storage(kname, (t_type*)ktype, v_iter->first);
+      initializers << constant_value_with_storage(vname, (t_type*)vtype, v_iter->second);
+      appenders << "    g_hash_table_insert (constant, " << kname << ", " << vname << ");" << endl;
+    }
+
+    f_types_impl_ << maybe_static << "GHashTable *" << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << initializers.str() << endl
+                  << indent() << "constant = " << generate_new_hash_from_type(ktype, vtype) << endl
+                  << appenders.str();
+    scope_down(f_types_impl_);
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  }
+}
+
+/**
+ * Generates helper classes for a service, consisting of a ThriftStruct subclass
+ * for the arguments to and the result from each method.
+ *
+ * @param tservice The service for which to generate helper classes
+ */
+void t_c_glib_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator function_iter;
+
+  // Iterate through the service's methods
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string function_name = (*function_iter)->get_name();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    string arg_list_name_orig = arg_list->get_name();
+
+    // Generate the arguments class
+    arg_list->set_name(tservice->get_name() + underscores_to_initial_caps(function_name) + "Args");
+    generate_struct(arg_list);
+
+    arg_list->set_name(arg_list_name_orig);
+
+    // Generate the result class
+    if (!(*function_iter)->is_oneway()) {
+      t_struct result(program_,
+                      tservice->get_name() + underscores_to_initial_caps(function_name) + "Result");
+      t_field success((*function_iter)->get_returntype(), "success", 0);
+      success.set_req(t_field::T_OPTIONAL);
+      if (!(*function_iter)->get_returntype()->is_void()) {
+        result.append(&success);
+      }
+
+      t_struct* xs = (*function_iter)->get_xceptions();
+      const vector<t_field*>& fields = xs->get_members();
+      vector<t_field*>::const_iterator field_iter;
+      for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) {
+        (*field_iter)->set_req(t_field::T_OPTIONAL);
+        result.append(*field_iter);
+      }
+
+      generate_struct(&result);
+    }
+  }
+}
+
+/**
+ * Generates C code that represents a Thrift service client.
+ */
+void t_c_glib_generator::generate_service_client(t_service* tservice) {
+  /* get some C friendly service names */
+  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
+  string service_name_uc = to_upper_case(service_name_lc);
+
+  string parent_service_name;
+  string parent_service_name_lc;
+  string parent_service_name_uc;
+
+  string parent_class_name = "GObject";
+  string parent_type_name = "G_TYPE_OBJECT";
+
+  // The service this service extends, or NULL if it extends no
+  // service
+  t_service* extends_service = tservice->get_extends();
+  if (extends_service) {
+    // The name of the parent service
+    parent_service_name = extends_service->get_name();
+    parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
+    parent_service_name_uc = to_upper_case(parent_service_name_lc);
+
+    // The names of the client class' parent class and type
+    parent_class_name = this->nspace + parent_service_name + "Client";
+    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_CLIENT";
+  }
+
+  // The base service (the topmost in the "extends" hierarchy), on
+  // whose client class the "input_protocol" and "output_protocol"
+  // properties are defined
+  t_service* base_service = tservice;
+  while (base_service->get_extends()) {
+    base_service = base_service->get_extends();
+  }
+
+  string base_service_name = base_service->get_name();
+  string base_service_name_lc = to_lower_case(initial_caps_to_underscores(base_service_name));
+  string base_service_name_uc = to_upper_case(base_service_name_lc);
+
+  // Generate the client interface dummy object in the header.
+  f_header_ << "/* " << service_name_ << " service interface */" << endl << "typedef struct _"
+            << this->nspace << service_name_ << "If " << this->nspace << service_name_ << "If; "
+            << " /* dummy object */" << endl << endl;
+
+  // Generate the client interface object in the header.
+  f_header_ << "struct _" << this->nspace << service_name_ << "IfInterface" << endl << "{" << endl
+            << "  GTypeInterface parent;" << endl << endl;
+
+  /* write out the functions for this interface */
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = initial_caps_to_underscores((*f_iter)->get_name());
+    t_type* ttype = (*f_iter)->get_returntype();
+    t_struct* arglist = (*f_iter)->get_arglist();
+    t_struct* xlist = (*f_iter)->get_xceptions();
+    bool has_return = !ttype->is_void();
+    bool has_args = arglist->get_members().size() == 0;
+    bool has_xceptions = xlist->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arglist)))
+                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
+
+    indent(f_header_) << "gboolean (*" << funname << ") " << params << ";" << endl;
+  }
+  indent_down();
+
+  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "IfInterface "
+            << this->nspace << service_name_ << "IfInterface;" << endl << endl;
+
+  // generate all the interface boilerplate
+  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_if_get_type (void);" << endl
+            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF "
+            << "(" << this->nspace_lc << service_name_lc << "_if_get_type())" << endl << "#define "
+            << this->nspace_uc << service_name_uc << "_IF(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_IF, " << this->nspace << service_name_ << "If))" << endl
+            << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_IF(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_IF))" << endl << "#define " << this->nspace_uc
+            << service_name_uc << "_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), "
+            << this->nspace_uc << "TYPE_" << service_name_uc << "_IF, " << this->nspace
+            << service_name_ << "IfInterface))" << endl << endl;
+
+  // write out all the interface function prototypes
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = initial_caps_to_underscores((*f_iter)->get_name());
+    t_type* ttype = (*f_iter)->get_returntype();
+    t_struct* arglist = (*f_iter)->get_arglist();
+    t_struct* xlist = (*f_iter)->get_xceptions();
+    bool has_return = !ttype->is_void();
+    bool has_args = arglist->get_members().size() == 0;
+    bool has_xceptions = xlist->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arglist)))
+                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
+
+    f_header_ << "gboolean " << this->nspace_lc << service_name_lc << "_if_" << funname << " "
+              << params << ";" << endl;
+  }
+  f_header_ << endl;
+
+  // Generate the client object instance definition in the header.
+  f_header_ << "/* " << service_name_ << " service client */" << endl << "struct _" << this->nspace
+            << service_name_ << "Client" << endl << "{" << endl << "  " << parent_class_name
+            << " parent;" << endl;
+  if (!extends_service) {
+    // Define "input_protocol" and "output_protocol" properties only
+    // for base services; child service-client classes will inherit
+    // these
+    f_header_ << endl << "  ThriftProtocol *input_protocol;" << endl
+              << "  ThriftProtocol *output_protocol;" << endl;
+  }
+  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "Client "
+            << this->nspace << service_name_ << "Client;" << endl << endl;
+
+  // Generate the class definition in the header.
+  f_header_ << "struct _" << this->nspace << service_name_ << "ClientClass" << endl << "{" << endl
+            << "  " << parent_class_name << "Class parent;" << endl << "};" << endl
+            << "typedef struct _" << this->nspace << service_name_ << "ClientClass " << this->nspace
+            << service_name_ << "ClientClass;" << endl << endl;
+
+  // Create all the GObject boilerplate
+  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_client_get_type (void);" << endl
+            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT "
+            << "(" << this->nspace_lc << service_name_lc << "_client_get_type())" << endl
+            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "Client))" << endl
+            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" << endl << "#define "
+            << this->nspace_uc << service_name_uc << "_IS_CLIENT(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_CLIENT))" << endl << "#define " << this->nspace_uc
+            << service_name_uc << "_IS_CLIENT_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_CLIENT))" << endl << "#define " << this->nspace_uc << service_name_uc
+            << "_CLIENT_GET_CLASS(obj) "
+            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))"
+            << endl << endl;
+
+  /* write out the function prototypes */
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = to_lower_case(initial_caps_to_underscores((*f_iter)->get_name()));
+
+    t_function service_function((*f_iter)->get_returntype(),
+                                service_name_lc + string("_client_") + funname,
+                                (*f_iter)->get_arglist(),
+                                (*f_iter)->get_xceptions());
+    indent(f_header_) << function_signature(&service_function) << ";" << endl;
+
+    t_function send_function(g_type_void,
+                             service_name_lc + string("_client_send_") + funname,
+                             (*f_iter)->get_arglist());
+    indent(f_header_) << function_signature(&send_function) << ";" << endl;
+
+    // implement recv if not a oneway service
+    if (!(*f_iter)->is_oneway()) {
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               service_name_lc + string("_client_recv_") + funname,
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      indent(f_header_) << function_signature(&recv_function) << ";" << endl;
+    }
+  }
+
+  /* write out the get/set function prototypes */
+  f_header_ << "void " + service_name_lc + "_client_set_property (GObject *object, guint "
+                                           "property_id, const GValue *value, GParamSpec *pspec);"
+            << endl;
+  f_header_ << "void " + service_name_lc + "_client_get_property (GObject *object, guint "
+                                           "property_id, GValue *value, GParamSpec *pspec);"
+            << endl;
+
+  f_header_ << endl;
+  // end of header code
+
+  // Generate interface method implementations
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = initial_caps_to_underscores((*f_iter)->get_name());
+    t_type* ttype = (*f_iter)->get_returntype();
+    t_struct* arglist = (*f_iter)->get_arglist();
+    t_struct* xlist = (*f_iter)->get_xceptions();
+    bool has_return = !ttype->is_void();
+    bool has_args = arglist->get_members().size() == 0;
+    bool has_xceptions = xlist->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arglist)))
+                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
+
+    string params_without_type = string("iface, ") + (has_return ? "_return, " : "");
+
+    const vector<t_field*>& fields = arglist->get_members();
+    vector<t_field*>::const_iterator f_iter_field;
+    for (f_iter_field = fields.begin(); f_iter_field != fields.end(); ++f_iter_field) {
+      params_without_type += (*f_iter_field)->get_name();
+      params_without_type += ", ";
+    }
+
+    const vector<t_field*>& xceptions = xlist->get_members();
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      params_without_type += (*x_iter)->get_name();
+      params_without_type += ", ";
+    }
+
+    f_service_ << "gboolean" << endl << this->nspace_lc << service_name_lc << "_if_" << funname
+               << " " << params << endl << "{" << endl << "  return " << this->nspace_uc
+               << service_name_uc << "_IF_GET_INTERFACE (iface)->" << funname << " ("
+               << params_without_type << "error);" << endl << "}" << endl << endl;
+  }
+
+  // Generate interface boilerplate
+  f_service_ << "GType" << endl << this->nspace_lc << service_name_lc << "_if_get_type (void)"
+             << endl << "{" << endl << "  static GType type = 0;" << endl << "  if (type == 0)"
+             << endl << "  {" << endl << "    static const GTypeInfo type_info =" << endl << "    {"
+             << endl << "      sizeof (" << this->nspace << service_name_ << "IfInterface)," << endl
+             << "      NULL,  /* base_init */" << endl << "      NULL,  /* base_finalize */" << endl
+             << "      NULL,  /* class_init */" << endl << "      NULL,  /* class_finalize */"
+             << endl << "      NULL,  /* class_data */" << endl
+             << "      0,     /* instance_size */" << endl << "      0,     /* n_preallocs */"
+             << endl << "      NULL,  /* instance_init */" << endl
+             << "      NULL   /* value_table */" << endl << "    };" << endl
+             << "    type = g_type_register_static (G_TYPE_INTERFACE," << endl
+             << "                                   \"" << this->nspace << service_name_ << "If\","
+             << endl << "                                   &type_info, 0);" << endl << "  }"
+             << endl << "  return type;" << endl << "}" << endl << endl;
+
+  // Generate client boilerplate
+  f_service_ << "static void " << endl << this->nspace_lc << service_name_lc
+             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
+             << endl << endl << "G_DEFINE_TYPE_WITH_CODE (" << this->nspace << service_name_
+             << "Client, " << this->nspace_lc << service_name_lc << "_client," << endl
+             << "                         " << parent_type_name << ", " << endl
+             << "                         G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
+             << service_name_uc << "_IF," << endl
+             << "                                                " << this->nspace_lc
+             << service_name_lc << "_if_interface_init))" << endl << endl;
+
+  // Generate property-related code only for base services---child
+  // service-client classes have only properties inherited from their
+  // parent class
+  if (!extends_service) {
+    // Generate client properties
+    f_service_ << "enum _" << this->nspace << service_name_ << "ClientProperties" << endl << "{"
+               << endl << "  PROP_0," << endl << "  PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_INPUT_PROTOCOL," << endl << "  PROP_" << this->nspace_uc
+               << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL" << endl << "};" << endl << endl;
+
+    // generate property setter
+    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_set_property ("
+               << "GObject *object, guint property_id, const GValue *value, "
+               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace
+               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc
+               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl
+               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_"
+               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl
+               << "      client->input_protocol = g_value_get_object (value);" << endl
+               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_OUTPUT_PROTOCOL:" << endl
+               << "      client->output_protocol = g_value_get_object (value);" << endl
+               << "      break;" << endl << "  }" << endl << "}" << endl << endl;
+
+    // generate property getter
+    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_get_property ("
+               << "GObject *object, guint property_id, GValue *value, "
+               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace
+               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc
+               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl
+               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_"
+               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl
+               << "      g_value_set_object (value, client->input_protocol);" << endl
+               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_OUTPUT_PROTOCOL:" << endl
+               << "      g_value_set_object (value, client->output_protocol);" << endl
+               << "      break;" << endl << "  }" << endl << "}" << endl << endl;
+  }
+
+  // Generate client method implementations
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string name = (*f_iter)->get_name();
+    string funname = initial_caps_to_underscores(name);
+
+    // Get the struct of function call params and exceptions
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    // Function for sending
+    t_function send_function(g_type_void,
+                             service_name_lc + string("_client_send_") + funname,
+                             (*f_iter)->get_arglist());
+
+    // Open the send function
+    indent(f_service_) << function_signature(&send_function) << endl;
+    scope_up(f_service_);
+
+    string reqType = (*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL";
+
+    // Serialize the request
+    f_service_ << indent() << "gint32 cseqid = 0;" << endl << indent()
+               << "ThriftProtocol * protocol = " << this->nspace_uc << base_service_name_uc
+               << "_CLIENT (iface)->output_protocol;" << endl << endl << indent()
+               << "if (thrift_protocol_write_message_begin (protocol, \"" << name << "\", "
+               << reqType << ", cseqid, error) < 0)" << endl << indent() << "  return FALSE;"
+               << endl << endl;
+
+    generate_struct_writer(f_service_, arg_struct, "", "", false);
+
+    f_service_ << indent() << "if (thrift_protocol_write_message_end (protocol, error) < 0)" << endl
+               << indent() << "  return FALSE;" << endl << indent()
+               << "if (!thrift_transport_flush (protocol->transport, error))" << endl << indent()
+               << "  return FALSE;" << endl << indent()
+               << "if (!thrift_transport_write_end (protocol->transport, error))" << endl
+               << indent() << "  return FALSE;" << endl << endl << indent() << "return TRUE;"
+               << endl;
+
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // Generate recv function only if not an async function
+    if (!(*f_iter)->is_oneway()) {
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               service_name_lc + string("_client_recv_") + funname,
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      // Open function
+      indent(f_service_) << function_signature(&recv_function) << endl;
+      scope_up(f_service_);
+
+      f_service_ << indent() << "gint32 rseqid;" << endl
+                 << indent() << "gchar * fname = NULL;" << endl
+                 << indent() << "ThriftMessageType mtype;" << endl
+                 << indent() << "ThriftProtocol * protocol = "
+                 << this->nspace_uc << base_service_name_uc
+                 << "_CLIENT (iface)->input_protocol;" << endl
+                 << indent() << "ThriftApplicationException *xception;" << endl
+                 << endl
+                 << indent() << "if (thrift_protocol_read_message_begin "
+                    "(protocol, &fname, &mtype, &rseqid, error) < 0) {" << endl;
+      indent_up();
+      f_service_ << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "}" << endl
+                 << endl
+                 << indent() << "if (mtype == T_EXCEPTION) {" << endl;
+      indent_up();
+      f_service_ << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "xception = g_object_new "
+                    "(THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);" << endl
+                 << indent() << "thrift_struct_read (THRIFT_STRUCT (xception), "
+                    "protocol, NULL);" << endl
+                 << indent() << "thrift_protocol_read_message_end "
+                    "(protocol, NULL);" << endl
+                 << indent() << "thrift_transport_read_end "
+                    "(protocol->transport, NULL);" << endl
+                 << indent() << "g_set_error (error, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR,xception->type, "
+                    "\"application error: %s\", xception->message);" << endl
+                 << indent() << "g_object_unref (xception);" << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "} else if (mtype != T_REPLY) {" << endl;
+      indent_up();
+      f_service_ << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "thrift_protocol_skip (protocol, T_STRUCT, "
+                    "NULL);" << endl
+                 << indent() << "thrift_protocol_read_message_end (protocol, "
+                    "NULL);" << endl
+                 << indent() << "thrift_transport_read_end ("
+                    "protocol->transport, NULL);" << endl
+                 << indent() << "g_set_error (error, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, "
+                    "\"invalid message type %d, expected T_REPLY\", mtype);"
+                 << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "} else if (strncmp (fname, \"" << name
+                 << "\", " << name.length() << ") != 0) {" << endl;
+      indent_up();
+      f_service_ << indent() << "thrift_protocol_skip (protocol, T_STRUCT, "
+                    "NULL);" << endl
+                 << indent() << "thrift_protocol_read_message_end (protocol,"
+                    "error);" << endl
+                 << indent() << "thrift_transport_read_end ("
+                    "protocol->transport, error);" << endl
+                 << indent() << "g_set_error (error, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, "
+                    "\"wrong method name %s, expected " << name
+                    << "\", fname);" << endl
+                 << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "}" << endl
+                 << indent() << "if (fname) g_free (fname);" << endl
+                 << endl;
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+
+      {
+        t_struct result(program_, tservice->get_name() + "_" + (*f_iter)->get_name() + "_result");
+        t_field success((*f_iter)->get_returntype(), "*_return", 0);
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          result.append(&success);
+        }
+
+        // add readers for exceptions, dereferencing the pointer.
+        for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) {
+          t_field* xception = new t_field((*x_iter)->get_type(),
+                                          "*" + (*x_iter)->get_name(),
+                                          (*x_iter)->get_key());
+          result.append(xception);
+        }
+
+        generate_struct_reader(f_service_, &result, "", "", false);
+      }
+
+      f_service_ << indent() << "if (thrift_protocol_read_message_end (protocol, error) < 0)"
+                 << endl << indent() << "  return FALSE;" << endl << endl << indent()
+                 << "if (!thrift_transport_read_end (protocol->transport, error))" << endl
+                 << indent() << "  return FALSE;" << endl << endl;
+
+      // copy over any throw exceptions and return failure
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) {
+        f_service_ << indent() << "if (*" << (*x_iter)->get_name() << " != NULL)" << endl
+                   << indent() << "{" << endl << indent() << "    g_set_error (error, "
+                   << this->nspace_uc
+                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name()))
+                   << "_ERROR, " << this->nspace_uc
+                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name()))
+                   << "_ERROR_CODE, \"" << (*x_iter)->get_type()->get_name() << "\");" << endl
+                   << indent() << "    return FALSE;" << endl << indent() << "}" << endl;
+      }
+      // Close function
+      indent(f_service_) << "return TRUE;" << endl;
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+
+    // Open function
+    t_function service_function((*f_iter)->get_returntype(),
+                                service_name_lc + string("_client_") + funname,
+                                (*f_iter)->get_arglist(),
+                                (*f_iter)->get_xceptions());
+    indent(f_service_) << function_signature(&service_function) << endl;
+    scope_up(f_service_);
+
+    // wrap each function
+    f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_send_"
+               << funname << " (iface";
+
+    // Declare the function arguments
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", " << (*fld_iter)->get_name();
+    }
+    f_service_ << ", error))" << endl << indent() << "  return FALSE;" << endl;
+
+    // if not oneway, implement recv
+    if (!(*f_iter)->is_oneway()) {
+      string ret = (*f_iter)->get_returntype()->is_void() ? "" : "_return, ";
+
+      const vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        ret += (*x_iter)->get_name();
+        ret += ", ";
+      }
+
+      f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_recv_"
+                 << funname << " (iface, " << ret << "error))" << endl << indent()
+                 << "  return FALSE;" << endl;
+    }
+
+    // return TRUE which means all functions were called OK
+    indent(f_service_) << "return TRUE;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // create the interface initializer
+  f_service_ << "static void" << endl
+             << this->nspace_lc << service_name_lc << "_if_interface_init ("
+             << this->nspace << service_name_ << "IfInterface *iface)" << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      /* make the function name C friendly */
+      string funname = initial_caps_to_underscores((*f_iter)->get_name());
+
+      f_service_ << indent() << "iface->" << funname << " = " << this->nspace_lc
+                 << service_name_lc << "_client_" << funname << ";" << endl;
+    }
+  }
+  else {
+    f_service_ << indent() << "THRIFT_UNUSED_VAR (iface);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // create the client instance initializer
+  f_service_ << "static void" << endl
+             << this->nspace_lc << service_name_lc << "_client_init ("
+             << this->nspace << service_name_ << "Client *client)" << endl;
+  scope_up(f_service_);
+  if (!extends_service) {
+    f_service_ << indent() << "client->input_protocol = NULL;" << endl
+               << indent() << "client->output_protocol = NULL;" << endl;
+  }
+  else {
+    f_service_ << indent() << "THRIFT_UNUSED_VAR (client);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // create the client class initializer
+  f_service_ << "static void" << endl << this->nspace_lc << service_name_lc
+             << "_client_class_init (" << this->nspace << service_name_ << "ClientClass *cls)"
+             << endl << "{" << endl;
+  if (!extends_service) {
+    f_service_ << "  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl
+               << "  GParamSpec *param_spec;" << endl << endl
+               << "  gobject_class->set_property = " << this->nspace_lc << service_name_lc
+               << "_client_set_property;" << endl
+               << "  gobject_class->get_property = " << this->nspace_lc << service_name_lc
+               << "_client_get_property;" << endl << endl
+               << "  param_spec = g_param_spec_object (\"input_protocol\"," << endl
+               << "                                    \"input protocol (construct)\"," << endl
+               << "                                    \"Set the client input protocol\"," << endl
+               << "                                    THRIFT_TYPE_PROTOCOL," << endl
+               << "                                    G_PARAM_READWRITE);" << endl
+               << "  g_object_class_install_property (gobject_class," << endl
+               << "                                   PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_INPUT_PROTOCOL, param_spec);" << endl << endl
+               << "  param_spec = g_param_spec_object (\"output_protocol\"," << endl
+               << "                                    \"output protocol (construct)\"," << endl
+               << "                                    \"Set the client output protocol\"," << endl
+               << "                                    THRIFT_TYPE_PROTOCOL," << endl
+               << "                                    G_PARAM_READWRITE);" << endl
+               << "  g_object_class_install_property (gobject_class," << endl
+               << "                                   PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_OUTPUT_PROTOCOL, param_spec);" << endl;
+  }
+  else {
+    f_service_ << "  THRIFT_UNUSED_VAR (cls);" << endl;
+  }
+  f_service_ << "}" << endl << endl;
+}
+
+/**
+ * Generates C code that represents a Thrift service handler.
+ *
+ * @param tservice The service for which to generate a handler.
+ */
+void t_c_glib_generator::generate_service_handler(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator function_iter;
+
+  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
+  string service_name_uc = to_upper_case(service_name_lc);
+
+  string class_name = this->nspace + service_name_ + "Handler";
+  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string class_name_uc = to_upper_case(class_name_lc);
+
+  string parent_class_name;
+  string parent_type_name;
+
+  string args_indent;
+
+  // The service this service extends, or NULL if it extends no service
+  t_service* extends_service = tservice->get_extends();
+
+  // Determine the name of our parent service (if any) and the handler class'
+  // parent class name and type
+  if (extends_service) {
+    string parent_service_name = extends_service->get_name();
+    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
+    string parent_service_name_uc = to_upper_case(parent_service_name_lc);
+
+    parent_class_name = this->nspace + parent_service_name + "Handler";
+    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_HANDLER";
+  } else {
+    parent_class_name = "GObject";
+    parent_type_name = "G_TYPE_OBJECT";
+  }
+
+  // Generate the handler class' definition in the header file
+
+  // Generate the handler instance definition
+  f_header_ << "/* " << service_name_ << " handler (abstract base class) */" << endl << "struct _"
+            << class_name << endl << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << " parent;" << endl;
+  indent_down();
+  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl
+            << endl;
+
+  // Generate the handler class definition, including its class members
+  // (methods)
+  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl;
+
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string method_name = initial_caps_to_underscores((*function_iter)->get_name());
+    t_type* return_type = (*function_iter)->get_returntype();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    t_struct* x_list = (*function_iter)->get_xceptions();
+    bool has_return = !return_type->is_void();
+    bool has_args = arg_list->get_members().size() == 0;
+    bool has_xceptions = x_list->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(return_type) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arg_list)))
+                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
+
+    indent(f_header_) << "gboolean (*" << method_name << ") " << params << ";" << endl;
+  }
+  indent_down();
+
+  f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name
+            << "Class;" << endl << endl;
+
+  // Generate the remaining header boilerplate
+  f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define "
+            << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER "
+            << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc
+            << "(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER, " << class_name << "))" << endl << "#define "
+            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER))" << endl << "#define " << class_name_uc
+            << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << "#define "
+            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_HANDLER))" << endl << "#define " << this->nspace_uc << service_name_uc
+            << "_HANDLER_GET_CLASS(obj) "
+            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << endl;
+
+  // Generate the handler class' method definitions
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string method_name = initial_caps_to_underscores((*function_iter)->get_name());
+    t_type* return_type = (*function_iter)->get_returntype();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    t_struct* x_list = (*function_iter)->get_xceptions();
+    bool has_return = !return_type->is_void();
+    bool has_args = arg_list->get_members().size() == 0;
+    bool has_xceptions = x_list->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(return_type) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arg_list)))
+                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
+
+    f_header_ << "gboolean " << class_name_lc << "_" << method_name << " " << params << ";" << endl;
+  }
+  f_header_ << endl;
+
+  // Generate the handler's implementation in the implementation file
+
+  // Generate the implementation boilerplate
+  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc
+             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
+             << endl << endl;
+
+  args_indent = string(25, ' ');
+  f_service_ << "G_DEFINE_TYPE_WITH_CODE (" << class_name << ", " << endl << args_indent
+             << class_name_lc << "," << endl << args_indent << parent_type_name << "," << endl
+             << args_indent << "G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
+             << service_name_uc << "_IF," << endl;
+  args_indent += string(23, ' ');
+  f_service_ << args_indent << class_name_lc << "_" << service_name_lc << "_if_interface_init))"
+             << endl << endl;
+
+  // Generate the handler method implementations
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string function_name = (*function_iter)->get_name();
+    string method_name = initial_caps_to_underscores(function_name);
+    t_type* return_type = (*function_iter)->get_returntype();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    t_struct* x_list = (*function_iter)->get_xceptions();
+
+    const vector<t_field*>& args = arg_list->get_members();
+    const vector<t_field*>& xceptions = x_list->get_members();
+
+    vector<t_field*>::const_iterator field_iter;
+
+    t_function implementing_function(return_type,
+                                     service_name_lc + "_handler_" + method_name,
+                                     arg_list,
+                                     x_list,
+                                     (*function_iter)->is_oneway());
+
+    indent(f_service_) << function_signature(&implementing_function) << endl;
+    scope_up(f_service_);
+    f_service_ << indent() << "g_return_val_if_fail (" << this->nspace_uc << "IS_"
+               << service_name_uc << "_HANDLER (iface), FALSE);" << endl << endl << indent()
+               << "return " << class_name_uc << "_GET_CLASS (iface)"
+               << "->" << method_name << " (iface, ";
+
+    if (!return_type->is_void()) {
+      f_service_ << "_return, ";
+    }
+    for (field_iter = args.begin(); field_iter != args.end(); ++field_iter) {
+      f_service_ << (*field_iter)->get_name() << ", ";
+    }
+    for (field_iter = xceptions.begin(); field_iter != xceptions.end(); ++field_iter) {
+      f_service_ << (*field_iter)->get_name() << ", ";
+    }
+    f_service_ << "error);" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // Generate the handler interface initializer
+  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc
+             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)"
+             << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+      string method_name = initial_caps_to_underscores((*function_iter)->get_name());
+
+      f_service_ << indent() << "iface->" << method_name << " = " << class_name_lc << "_"
+                 << method_name << ";" << endl;
+    }
+  }
+  else {
+    f_service_ << "THRIFT_UNUSED_VAR (iface);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the handler instance initializer
+  f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)"
+             << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "THRIFT_UNUSED_VAR (self);" << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the handler class initializer
+  f_service_ << "static void" << endl
+             << class_name_lc << "_class_init (" << class_name << "Class *cls)"
+             << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    for (function_iter = functions.begin();
+         function_iter != functions.end();
+         ++function_iter) {
+      string function_name = (*function_iter)->get_name();
+      string method_name = initial_caps_to_underscores(function_name);
+
+      // All methods are pure virtual and must be implemented by subclasses
+      f_service_ << indent() << "cls->" << method_name << " = NULL;" << endl;
+    }
+  }
+  else {
+    f_service_ << indent() << "THRIFT_UNUSED_VAR (cls);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+}
+
+/**
+ * Generates C code that represents a Thrift service processor.
+ *
+ * @param tservice The service for which to generate a processor
+ */
+void t_c_glib_generator::generate_service_processor(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator function_iter;
+
+  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
+  string service_name_uc = to_upper_case(service_name_lc);
+
+  string class_name = this->nspace + service_name_ + "Processor";
+  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string class_name_uc = to_upper_case(class_name_lc);
+
+  string parent_class_name;
+  string parent_type_name;
+
+  string handler_class_name = this->nspace + service_name_ + "Handler";
+  string handler_class_name_lc = initial_caps_to_underscores(handler_class_name);
+
+  string process_function_type_name = class_name + "ProcessFunction";
+  string process_function_def_type_name =
+    class_name_lc + "_process_function_def";
+
+  string function_name;
+  string args_indent;
+
+  // The service this service extends, or NULL if it extends no service
+  t_service* extends_service = tservice->get_extends();
+
+  // Determine the name of our parent service (if any) and the
+  // processor class' parent class name and type
+  if (extends_service) {
+    string parent_service_name = extends_service->get_name();
+    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
+    string parent_service_name_uc = to_upper_case(parent_service_name_lc);
+
+    parent_class_name = this->nspace + parent_service_name + "Processor";
+    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_PROCESSOR";
+  } else {
+    parent_class_name = "ThriftDispatchProcessor";
+    parent_type_name = "THRIFT_TYPE_DISPATCH_PROCESSOR";
+  }
+
+  // Generate the processor class' definition in the header file
+
+  // Generate the processor instance definition
+  f_header_ << "/* " << service_name_ << " processor */" << endl << "struct _" << class_name << endl
+            << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << " parent;" << endl << endl << indent()
+            << "/* protected */" << endl << indent()
+            << this->nspace + service_name_ + "Handler *handler;" << endl << indent()
+            << "GHashTable *process_map;" << endl;
+  indent_down();
+  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl
+            << endl;
+
+  // Generate the processor class definition
+  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl << indent()
+            << "/* protected */

<TRUNCATED>

[25/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_base_type.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_base_type.h b/compiler/cpp/src/parse/t_base_type.h
deleted file mode 100644
index 11d73e0..0000000
--- a/compiler/cpp/src/parse/t_base_type.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_BASE_TYPE_H
-#define T_BASE_TYPE_H
-
-#include <cstdlib>
-#include "t_type.h"
-
-/**
- * A thrift base type, which must be one of the defined enumerated types inside
- * this definition.
- *
- */
-class t_base_type : public t_type {
-public:
-  /**
-   * Enumeration of thrift base types
-   */
-  enum t_base {
-    TYPE_VOID,
-    TYPE_STRING,
-    TYPE_BOOL,
-    TYPE_I8,
-    TYPE_I16,
-    TYPE_I32,
-    TYPE_I64,
-    TYPE_DOUBLE
-  };
-
-  t_base_type(std::string name, t_base base)
-    : t_type(name), base_(base), string_list_(false), binary_(false), string_enum_(false) {}
-
-  t_base get_base() const { return base_; }
-
-  bool is_void() const { return base_ == TYPE_VOID; }
-
-  bool is_string() const { return base_ == TYPE_STRING; }
-
-  bool is_bool() const { return base_ == TYPE_BOOL; }
-
-  void set_string_list(bool val) { string_list_ = val; }
-
-  bool is_string_list() const { return (base_ == TYPE_STRING) && string_list_; }
-
-  void set_binary(bool val) { binary_ = val; }
-
-  bool is_binary() const { return (base_ == TYPE_STRING) && binary_; }
-
-  void set_string_enum(bool val) { string_enum_ = val; }
-
-  bool is_string_enum() const { return base_ == TYPE_STRING && string_enum_; }
-
-  void add_string_enum_val(std::string val) { string_enum_vals_.push_back(val); }
-
-  const std::vector<std::string>& get_string_enum_vals() const { return string_enum_vals_; }
-
-  bool is_base_type() const { return true; }
-
-  static std::string t_base_name(t_base tbase) {
-    switch (tbase) {
-    case TYPE_VOID:
-      return "void";
-      break;
-    case TYPE_STRING:
-      return "string";
-      break;
-    case TYPE_BOOL:
-      return "bool";
-      break;
-    case TYPE_I8:
-      return "i8";
-      break;
-    case TYPE_I16:
-      return "i16";
-      break;
-    case TYPE_I32:
-      return "i32";
-      break;
-    case TYPE_I64:
-      return "i64";
-      break;
-    case TYPE_DOUBLE:
-      return "double";
-      break;
-    default:
-      return "(unknown)";
-      break;
-    }
-  }
-
-private:
-  t_base base_;
-
-  bool string_list_;
-  bool binary_;
-  bool string_enum_;
-  std::vector<std::string> string_enum_vals_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_const.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_const.h b/compiler/cpp/src/parse/t_const.h
deleted file mode 100644
index 0f64bb1..0000000
--- a/compiler/cpp/src/parse/t_const.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_CONST_H
-#define T_CONST_H
-
-#include "t_type.h"
-#include "t_const_value.h"
-
-/**
- * A const is a constant value defined across languages that has a type and
- * a value. The trick here is that the declared type might not match the type
- * of the value object, since that is not determined until after parsing the
- * whole thing out.
- *
- */
-class t_const : public t_doc {
-public:
-  t_const(t_type* type, std::string name, t_const_value* value)
-    : type_(type), name_(name), value_(value) {}
-
-  t_type* get_type() const { return type_; }
-
-  std::string get_name() const { return name_; }
-
-  t_const_value* get_value() const { return value_; }
-
-private:
-  t_type* type_;
-  std::string name_;
-  t_const_value* value_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_const_value.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_const_value.h b/compiler/cpp/src/parse/t_const_value.h
deleted file mode 100644
index 15366ad..0000000
--- a/compiler/cpp/src/parse/t_const_value.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_CONST_VALUE_H
-#define T_CONST_VALUE_H
-
-#include "t_enum.h"
-#include <stdint.h>
-#include <map>
-#include <vector>
-#include <string>
-
-namespace plugin_output {
-template <typename From, typename To>
-void convert(From*, To&);
-}
-
-/**
- * A const value is something parsed that could be a map, set, list, struct
- * or whatever.
- *
- */
-class t_const_value {
-public:
-  enum t_const_value_type { CV_INTEGER, CV_DOUBLE, CV_STRING, CV_MAP, CV_LIST, CV_IDENTIFIER };
-
-  t_const_value() {}
-
-  t_const_value(int64_t val) { set_integer(val); }
-
-  t_const_value(std::string val) { set_string(val); }
-
-  void set_string(std::string val) {
-    valType_ = CV_STRING;
-    stringVal_ = val;
-  }
-
-  std::string get_string() const { return stringVal_; }
-
-  void set_integer(int64_t val) {
-    valType_ = CV_INTEGER;
-    intVal_ = val;
-  }
-
-  int64_t get_integer() const {
-    if (valType_ == CV_IDENTIFIER) {
-      if (enum_ == NULL) {
-        throw "have identifier \"" + get_identifier() + "\", but unset enum on line!";
-      }
-      std::string identifier = get_identifier();
-      std::string::size_type dot = identifier.rfind('.');
-      if (dot != std::string::npos) {
-        identifier = identifier.substr(dot + 1);
-      }
-      t_enum_value* val = enum_->get_constant_by_name(identifier);
-      if (val == NULL) {
-        throw "Unable to find enum value \"" + identifier + "\" in enum \"" + enum_->get_name()
-            + "\"";
-      }
-      return val->get_value();
-    } else {
-      return intVal_;
-    }
-  }
-
-  void set_double(double val) {
-    valType_ = CV_DOUBLE;
-    doubleVal_ = val;
-  }
-
-  double get_double() const { return doubleVal_; }
-
-  void set_map() { valType_ = CV_MAP; }
-
-  void add_map(t_const_value* key, t_const_value* val) { mapVal_[key] = val; }
-
-  const std::map<t_const_value*, t_const_value*>& get_map() const { return mapVal_; }
-
-  void set_list() { valType_ = CV_LIST; }
-
-  void add_list(t_const_value* val) { listVal_.push_back(val); }
-
-  const std::vector<t_const_value*>& get_list() const { return listVal_; }
-
-  void set_identifier(std::string val) {
-    valType_ = CV_IDENTIFIER;
-    identifierVal_ = val;
-  }
-
-  std::string get_identifier() const { return identifierVal_; }
-
-  std::string get_identifier_name() const {
-    std::string ret = get_identifier();
-    size_t s = ret.find('.');
-    if (s == std::string::npos) {
-      throw "error: identifier " + ret + " is unqualified!";
-    }
-    ret = ret.substr(s + 1);
-    s = ret.find('.');
-    if (s != std::string::npos) {
-      ret = ret.substr(s + 1);
-    }
-    return ret;
-  }
-
-  std::string get_identifier_with_parent() const {
-    std::string ret = get_identifier();
-    size_t s = ret.find('.');
-    if (s == std::string::npos) {
-      throw "error: identifier " + ret + " is unqualified!";
-    }
-    size_t s2 = ret.find('.', s + 1);
-    if (s2 != std::string::npos) {
-      ret = ret.substr(s + 1);
-    }
-    return ret;
-  }
-
-  void set_enum(t_enum* tenum) { enum_ = tenum; }
-
-  t_const_value_type get_type() const { return valType_; }
-
-private:
-  std::map<t_const_value*, t_const_value*> mapVal_;
-  std::vector<t_const_value*> listVal_;
-  std::string stringVal_;
-  int64_t intVal_;
-  double doubleVal_;
-  std::string identifierVal_;
-  t_enum* enum_;
-
-  t_const_value_type valType_;
-
-  // to read enum_
-  template <typename From, typename To>
-  friend void plugin_output::convert(From*, To&);
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_container.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_container.h b/compiler/cpp/src/parse/t_container.h
deleted file mode 100644
index 2cdcf7e..0000000
--- a/compiler/cpp/src/parse/t_container.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_CONTAINER_H
-#define T_CONTAINER_H
-
-#include "t_type.h"
-
-class t_container : public t_type {
-public:
-  t_container() : cpp_name_(), has_cpp_name_(false) {}
-
-  virtual ~t_container() {}
-
-  void set_cpp_name(std::string cpp_name) {
-    cpp_name_ = cpp_name;
-    has_cpp_name_ = true;
-  }
-
-  bool has_cpp_name() const { return has_cpp_name_; }
-
-  std::string get_cpp_name() const { return cpp_name_; }
-
-  bool is_container() const { return true; }
-
-private:
-  std::string cpp_name_;
-  bool has_cpp_name_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_doc.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_doc.h b/compiler/cpp/src/parse/t_doc.h
deleted file mode 100644
index 621513a..0000000
--- a/compiler/cpp/src/parse/t_doc.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_DOC_H
-#define T_DOC_H
-
-#include "globals.h"
-#include "logging.h"
-
-/**
- * Documentation stubs
- *
- */
-class t_doc {
-
-public:
-  t_doc() : has_doc_(false) {}
-  virtual ~t_doc() {}
-
-  void set_doc(const std::string& doc) {
-    doc_ = doc;
-    has_doc_ = true;
-    if ((g_program_doctext_lineno == g_doctext_lineno)
-        && (g_program_doctext_status == STILL_CANDIDATE)) {
-      g_program_doctext_status = ALREADY_PROCESSED;
-      pdebug("%s", "program doctext set to ALREADY_PROCESSED");
-    }
-  }
-
-  const std::string& get_doc() const { return doc_; }
-
-  bool has_doc() { return has_doc_; }
-
-private:
-  std::string doc_;
-  bool has_doc_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_enum.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_enum.h b/compiler/cpp/src/parse/t_enum.h
deleted file mode 100644
index 268f89f..0000000
--- a/compiler/cpp/src/parse/t_enum.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_ENUM_H
-#define T_ENUM_H
-
-#include <vector>
-
-#include "t_enum_value.h"
-#include "t_type.h"
-
-/**
- * An enumerated type. A list of constant objects with a name for the type.
- *
- */
-class t_enum : public t_type {
-public:
-  t_enum(t_program* program) : t_type(program) {}
-
-  void set_name(const std::string& name) { name_ = name; }
-
-  void append(t_enum_value* constant) { constants_.push_back(constant); }
-
-  const std::vector<t_enum_value*>& get_constants() const { return constants_; }
-
-  t_enum_value* get_constant_by_name(const std::string& name) {
-    const std::vector<t_enum_value*>& enum_values = get_constants();
-    std::vector<t_enum_value*>::const_iterator c_iter;
-    for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
-      if ((*c_iter)->get_name() == name) {
-        return *c_iter;
-      }
-    }
-    return NULL;
-  }
-
-  t_enum_value* get_constant_by_value(int64_t value) {
-    const std::vector<t_enum_value*>& enum_values = get_constants();
-    std::vector<t_enum_value*>::const_iterator c_iter;
-    for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
-      if ((*c_iter)->get_value() == value) {
-        return *c_iter;
-      }
-    }
-    return NULL;
-  }
-
-  t_enum_value* get_min_value() {
-    const std::vector<t_enum_value*>& enum_values = get_constants();
-    std::vector<t_enum_value*>::const_iterator c_iter;
-    t_enum_value* min_value;
-    if (enum_values.size() == 0) {
-      min_value = NULL;
-    } else {
-      int min_value_value;
-      min_value = enum_values.front();
-      min_value_value = min_value->get_value();
-      for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
-        if ((*c_iter)->get_value() < min_value_value) {
-          min_value = (*c_iter);
-          min_value_value = min_value->get_value();
-        }
-      }
-    }
-    return min_value;
-  }
-
-  t_enum_value* get_max_value() {
-    const std::vector<t_enum_value*>& enum_values = get_constants();
-    std::vector<t_enum_value*>::const_iterator c_iter;
-    t_enum_value* max_value;
-    if (enum_values.size() == 0) {
-      max_value = NULL;
-    } else {
-      int max_value_value;
-      max_value = enum_values.back();
-      max_value_value = max_value->get_value();
-      for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
-        if ((*c_iter)->get_value() > max_value_value) {
-          max_value = (*c_iter);
-          max_value_value = max_value->get_value();
-        }
-      }
-    }
-    return max_value;
-  }
-
-  bool is_enum() const { return true; }
-
-private:
-  std::vector<t_enum_value*> constants_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_enum_value.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_enum_value.h b/compiler/cpp/src/parse/t_enum_value.h
deleted file mode 100644
index 296029b..0000000
--- a/compiler/cpp/src/parse/t_enum_value.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_ENUM_VALUE_H
-#define T_ENUM_VALUE_H
-
-#include <map>
-#include <string>
-#include "t_doc.h"
-
-/**
- * A constant. These are used inside of enum definitions. Constants are just
- * symbol identifiers that may or may not have an explicit value associated
- * with them.
- *
- */
-class t_enum_value : public t_doc {
-public:
-  t_enum_value(std::string name, int value) : name_(name), value_(value) {}
-
-  ~t_enum_value() {}
-
-  const std::string& get_name() const { return name_; }
-
-  int get_value() const { return value_; }
-
-  std::map<std::string, std::string> annotations_;
-
-private:
-  std::string name_;
-  int value_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_field.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h
deleted file mode 100644
index 8b459a3..0000000
--- a/compiler/cpp/src/parse/t_field.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_FIELD_H
-#define T_FIELD_H
-
-#include <map>
-#include <string>
-#include <sstream>
-
-#include "t_doc.h"
-#include "t_type.h"
-
-// Forward declare for xsd_attrs
-class t_struct;
-
-/**
- * Class to represent a field in a thrift structure. A field has a data type,
- * a symbolic name, and a numeric identifier.
- *
- */
-class t_field : public t_doc {
-public:
-  t_field(t_type* type, std::string name)
-    : type_(type),
-      name_(name),
-      key_(0),
-      value_(NULL),
-      xsd_optional_(false),
-      xsd_nillable_(false),
-      xsd_attrs_(NULL),
-      reference_(false) {}
-
-  t_field(t_type* type, std::string name, int32_t key)
-    : type_(type),
-      name_(name),
-      key_(key),
-      req_(T_OPT_IN_REQ_OUT),
-      value_(NULL),
-      xsd_optional_(false),
-      xsd_nillable_(false),
-      xsd_attrs_(NULL),
-      reference_(false) {}
-
-  ~t_field() {}
-
-  t_type* get_type() { return type_; }
-
-  const t_type* get_type() const { return type_; }
-
-  const std::string& get_name() const { return name_; }
-
-  int32_t get_key() const { return key_; }
-
-  enum e_req { T_REQUIRED, T_OPTIONAL, T_OPT_IN_REQ_OUT };
-
-  void set_req(e_req req) { req_ = req; }
-
-  e_req get_req() const { return req_; }
-
-  void set_value(t_const_value* value) { value_ = value; }
-
-  t_const_value* get_value() { return value_; }
-
-  const t_const_value* get_value() const { return value_; }
-
-  void set_xsd_optional(bool xsd_optional) { xsd_optional_ = xsd_optional; }
-
-  bool get_xsd_optional() const { return xsd_optional_; }
-
-  void set_xsd_nillable(bool xsd_nillable) { xsd_nillable_ = xsd_nillable; }
-
-  bool get_xsd_nillable() const { return xsd_nillable_; }
-
-  void set_xsd_attrs(t_struct* xsd_attrs) { xsd_attrs_ = xsd_attrs; }
-
-  t_struct* get_xsd_attrs() { return xsd_attrs_; }
-
-  /**
-   * Comparator to sort fields in ascending order by key.
-   * Make this a functor instead of a function to help GCC inline it.
-   * The arguments are (const) references to const pointers to const t_fields.
-   */
-  struct key_compare {
-    bool operator()(t_field const* const& a, t_field const* const& b) {
-      return a->get_key() < b->get_key();
-    }
-  };
-
-  std::map<std::string, std::string> annotations_;
-
-  bool get_reference() { return reference_; }
-
-  void set_reference(bool reference) { reference_ = reference; }
-
-private:
-  t_type* type_;
-  std::string name_;
-  int32_t key_;
-  e_req req_;
-  t_const_value* value_;
-
-  bool xsd_optional_;
-  bool xsd_nillable_;
-  t_struct* xsd_attrs_;
-  bool reference_;
-};
-
-/**
- * A simple struct for the parser to use to store a field ID, and whether or
- * not it was specified by the user or automatically chosen.
- */
-struct t_field_id {
-  int32_t value;
-  bool auto_assigned;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_function.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_function.h b/compiler/cpp/src/parse/t_function.h
deleted file mode 100644
index 96886f3..0000000
--- a/compiler/cpp/src/parse/t_function.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_FUNCTION_H
-#define T_FUNCTION_H
-
-#include <string>
-#include "t_type.h"
-#include "t_struct.h"
-#include "t_doc.h"
-
-/**
- * Representation of a function. Key parts are return type, function name,
- * optional modifiers, and an argument list, which is implemented as a thrift
- * struct.
- *
- */
-class t_function : public t_doc {
-public:
-  t_function(t_type* returntype, std::string name, t_struct* arglist, bool oneway = false)
-    : returntype_(returntype), name_(name), arglist_(arglist), oneway_(oneway) {
-    xceptions_ = new t_struct(NULL);
-    if (oneway_ && (!returntype_->is_void())) {
-      pwarning(1, "Oneway methods should return void.\n");
-    }
-  }
-
-  t_function(t_type* returntype,
-             std::string name,
-             t_struct* arglist,
-             t_struct* xceptions,
-             bool oneway = false)
-    : returntype_(returntype),
-      name_(name),
-      arglist_(arglist),
-      xceptions_(xceptions),
-      oneway_(oneway) {
-    if (oneway_ && !xceptions_->get_members().empty()) {
-      throw std::string("Oneway methods can't throw exceptions.");
-    }
-    if (oneway_ && (!returntype_->is_void())) {
-      pwarning(1, "Oneway methods should return void.\n");
-    }
-  }
-
-  ~t_function() {}
-
-  t_type* get_returntype() const { return returntype_; }
-
-  const std::string& get_name() const { return name_; }
-
-  t_struct* get_arglist() const { return arglist_; }
-
-  t_struct* get_xceptions() const { return xceptions_; }
-
-  bool is_oneway() const { return oneway_; }
-
-  std::map<std::string, std::string> annotations_;
-
-private:
-  t_type* returntype_;
-  std::string name_;
-  t_struct* arglist_;
-  t_struct* xceptions_;
-  bool oneway_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_list.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_list.h b/compiler/cpp/src/parse/t_list.h
deleted file mode 100644
index ac0d981..0000000
--- a/compiler/cpp/src/parse/t_list.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_LIST_H
-#define T_LIST_H
-
-#include "t_container.h"
-
-/**
- * A list is a lightweight container type that just wraps another data type.
- *
- */
-class t_list : public t_container {
-public:
-  t_list(t_type* elem_type) : elem_type_(elem_type) {}
-
-  t_type* get_elem_type() const { return elem_type_; }
-
-  bool is_list() const { return true; }
-
-private:
-  t_type* elem_type_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_map.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_map.h b/compiler/cpp/src/parse/t_map.h
deleted file mode 100644
index 269aeab..0000000
--- a/compiler/cpp/src/parse/t_map.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_MAP_H
-#define T_MAP_H
-
-#include "t_container.h"
-
-/**
- * A map is a lightweight container type that just wraps another two data
- * types.
- *
- */
-class t_map : public t_container {
-public:
-  t_map(t_type* key_type, t_type* val_type) : key_type_(key_type), val_type_(val_type) {}
-
-  t_type* get_key_type() const { return key_type_; }
-
-  t_type* get_val_type() const { return val_type_; }
-
-  bool is_map() const { return true; }
-
-private:
-  t_type* key_type_;
-  t_type* val_type_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_program.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h
deleted file mode 100644
index 563e9e0..0000000
--- a/compiler/cpp/src/parse/t_program.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PROGRAM_H
-#define T_PROGRAM_H
-
-#include <map>
-#include <string>
-#include <vector>
-
-// For program_name()
-#include "main.h"
-
-#include "t_doc.h"
-#include "t_scope.h"
-#include "t_base_type.h"
-#include "t_typedef.h"
-#include "t_enum.h"
-#include "t_const.h"
-#include "t_struct.h"
-#include "t_service.h"
-#include "t_list.h"
-#include "t_map.h"
-#include "t_set.h"
-#include "generate/t_generator_registry.h"
-//#include "t_doc.h"
-
-/**
- * Top level class representing an entire thrift program. A program consists
- * fundamentally of the following:
- *
- *   Typedefs
- *   Enumerations
- *   Constants
- *   Structs
- *   Exceptions
- *   Services
- *
- * The program module also contains the definitions of the base types.
- *
- */
-class t_program : public t_doc {
-public:
-  t_program(std::string path, std::string name)
-    : path_(path), name_(name), out_path_("./"), out_path_is_absolute_(false), scope_(new t_scope) {}
-
-  t_program(std::string path) : path_(path), out_path_("./"), out_path_is_absolute_(false) {
-    name_ = program_name(path);
-    scope_ = new t_scope();
-  }
-
-  ~t_program() {
-    if (scope_) {
-      delete scope_;
-      scope_ = NULL;
-    }
-  }
-
-  // Path accessor
-  const std::string& get_path() const { return path_; }
-
-  // Output path accessor
-  const std::string& get_out_path() const { return out_path_; }
-
-  // Create gen-* dir accessor
-  bool is_out_path_absolute() const { return out_path_is_absolute_; }
-
-  // Name accessor
-  const std::string& get_name() const { return name_; }
-
-  // Namespace
-  const std::string& get_namespace() const { return namespace_; }
-
-  // Include prefix accessor
-  const std::string& get_include_prefix() const { return include_prefix_; }
-
-  // Accessors for program elements
-  const std::vector<t_typedef*>& get_typedefs() const { return typedefs_; }
-  const std::vector<t_enum*>& get_enums() const { return enums_; }
-  const std::vector<t_const*>& get_consts() const { return consts_; }
-  const std::vector<t_struct*>& get_structs() const { return structs_; }
-  const std::vector<t_struct*>& get_xceptions() const { return xceptions_; }
-  const std::vector<t_struct*>& get_objects() const { return objects_; }
-  const std::vector<t_service*>& get_services() const { return services_; }
-  const std::map<std::string, std::string>& get_namespaces() const { return namespaces_; }
-
-  // Program elements
-  void add_typedef(t_typedef* td) { typedefs_.push_back(td); }
-  void add_enum(t_enum* te) { enums_.push_back(te); }
-  void add_const(t_const* tc) { consts_.push_back(tc); }
-  void add_struct(t_struct* ts) {
-    objects_.push_back(ts);
-    structs_.push_back(ts);
-  }
-  void add_xception(t_struct* tx) {
-    objects_.push_back(tx);
-    xceptions_.push_back(tx);
-  }
-  void add_service(t_service* ts) { services_.push_back(ts); }
-
-  // Programs to include
-  const std::vector<t_program*>& get_includes() const { return includes_; }
-
-  void set_out_path(std::string out_path, bool out_path_is_absolute) {
-    out_path_ = out_path;
-    out_path_is_absolute_ = out_path_is_absolute;
-    // Ensure that it ends with a trailing '/' (or '\' for windows machines)
-    char c = out_path_.at(out_path_.size() - 1);
-    if (!(c == '/' || c == '\\')) {
-      out_path_.push_back('/');
-    }
-  }
-
-  // Typename collision detection
-  /**
-   * Search for typename collisions
-   * @param t    the type to test for collisions
-   * @return     true if a certain collision was found, otherwise false
-   */
-  bool is_unique_typename(t_type* t) {
-    int occurrences = program_typename_count(this, t);
-    for (std::vector<t_program*>::iterator it = includes_.begin(); it != includes_.end(); ++it) {
-      occurrences += program_typename_count(*it, t);
-    }
-    return 0 == occurrences;
-  }
-
-  /**
-   * Search all type collections for duplicate typenames
-   * @param prog the program to search
-   * @param t    the type to test for collisions
-   * @return     the number of certain typename collisions
-   */
-  int program_typename_count(t_program* prog, t_type* t) {
-    int occurrences = 0;
-    occurrences += collection_typename_count(prog, prog->typedefs_, t);
-    occurrences += collection_typename_count(prog, prog->enums_, t);
-    occurrences += collection_typename_count(prog, prog->objects_, t);
-    occurrences += collection_typename_count(prog, prog->services_, t);
-    return occurrences;
-  }
-
-  /**
-   * Search a type collection for duplicate typenames
-   * @param prog            the program to search
-   * @param type_collection the type collection to search
-   * @param t               the type to test for collisions
-   * @return                the number of certain typename collisions
-   */
-  template <class T>
-  int collection_typename_count(t_program* prog, T type_collection, t_type* t) {
-    int occurrences = 0;
-    for (typename T::iterator it = type_collection.begin(); it != type_collection.end(); ++it)
-      if (t != *it && 0 == t->get_name().compare((*it)->get_name()) && is_common_namespace(prog, t))
-        ++occurrences;
-    return occurrences;
-  }
-
-  /**
-   * Determine whether identical typenames will collide based on namespaces.
-   *
-   * Because we do not know which languages the user will generate code for,
-   * collisions within programs (IDL files) having namespace declarations can be
-   * difficult to determine. Only guaranteed collisions return true (cause an error).
-   * Possible collisions involving explicit namespace declarations produce a warning.
-   * Other possible collisions go unreported.
-   * @param prog the program containing the preexisting typename
-   * @param t    the type containing the typename match
-   * @return     true if a collision within namespaces is found, otherwise false
-   */
-  bool is_common_namespace(t_program* prog, t_type* t) {
-    // Case 1: Typenames are in the same program [collision]
-    if (prog == t->get_program()) {
-      pwarning(1,
-               "Duplicate typename %s found in %s",
-               t->get_name().c_str(),
-               t->get_program()->get_name().c_str());
-      return true;
-    }
-
-    // Case 2: Both programs have identical namespace scope/name declarations [collision]
-    bool match = true;
-    for (std::map<std::string, std::string>::iterator it = prog->namespaces_.begin();
-         it != prog->namespaces_.end();
-         ++it) {
-      if (0 == it->second.compare(t->get_program()->get_namespace(it->first))) {
-        pwarning(1,
-                 "Duplicate typename %s found in %s,%s,%s and %s,%s,%s [file,scope,ns]",
-                 t->get_name().c_str(),
-                 t->get_program()->get_name().c_str(),
-                 it->first.c_str(),
-                 it->second.c_str(),
-                 prog->get_name().c_str(),
-                 it->first.c_str(),
-                 it->second.c_str());
-      } else {
-        match = false;
-      }
-    }
-    for (std::map<std::string, std::string>::iterator it = t->get_program()->namespaces_.begin();
-         it != t->get_program()->namespaces_.end();
-         ++it) {
-      if (0 == it->second.compare(prog->get_namespace(it->first))) {
-        pwarning(1,
-                 "Duplicate typename %s found in %s,%s,%s and %s,%s,%s [file,scope,ns]",
-                 t->get_name().c_str(),
-                 t->get_program()->get_name().c_str(),
-                 it->first.c_str(),
-                 it->second.c_str(),
-                 prog->get_name().c_str(),
-                 it->first.c_str(),
-                 it->second.c_str());
-      } else {
-        match = false;
-      }
-    }
-    if (0 == prog->namespaces_.size() && 0 == t->get_program()->namespaces_.size()) {
-      pwarning(1,
-               "Duplicate typename %s found in %s and %s",
-               t->get_name().c_str(),
-               t->get_program()->get_name().c_str(),
-               prog->get_name().c_str());
-    }
-    return match;
-  }
-
-  // Scoping and namespacing
-  void set_namespace(std::string name) { namespace_ = name; }
-
-  // Scope accessor
-  t_scope* scope() const { return scope_; }
-
-  // Includes
-
-  void add_include(t_program* program) {
-    includes_.push_back(program);
-  }
-
-  void add_include(std::string path, std::string include_site) {
-    t_program* program = new t_program(path);
-
-    // include prefix for this program is the site at which it was included
-    // (minus the filename)
-    std::string include_prefix;
-    std::string::size_type last_slash = std::string::npos;
-    if ((last_slash = include_site.rfind("/")) != std::string::npos) {
-      include_prefix = include_site.substr(0, last_slash);
-    }
-
-    program->set_include_prefix(include_prefix);
-    includes_.push_back(program);
-  }
-
-  std::vector<t_program*>& get_includes() { return includes_; }
-
-  void set_include_prefix(std::string include_prefix) {
-    include_prefix_ = include_prefix;
-
-    // this is intended to be a directory; add a trailing slash if necessary
-    std::string::size_type len = include_prefix_.size();
-    if (len > 0 && include_prefix_[len - 1] != '/') {
-      include_prefix_ += '/';
-    }
-  }
-
-  // Language neutral namespace / packaging
-  void set_namespace(std::string language, std::string name_space) {
-    if (language != "*") {
-      size_t sub_index = language.find('.');
-      std::string base_language = language.substr(0, sub_index);
-      std::string sub_namespace;
-
-      if (base_language == "smalltalk") {
-        pwarning(1, "Namespace 'smalltalk' is deprecated. Use 'st' instead");
-        base_language = "st";
-      }
-
-      t_generator_registry::gen_map_t my_copy = t_generator_registry::get_generator_map();
-
-      t_generator_registry::gen_map_t::iterator it;
-      it = my_copy.find(base_language);
-
-      if (it == my_copy.end()) {
-        std::string warning = "No generator named '" + base_language + "' could be found!";
-        pwarning(1, warning.c_str());
-      } else {
-        if (sub_index != std::string::npos) {
-          std::string sub_namespace = language.substr(sub_index + 1);
-          if (!it->second->is_valid_namespace(sub_namespace)) {
-            std::string warning = base_language + " generator does not accept '" + sub_namespace
-                                  + "' as sub-namespace!";
-            pwarning(1, warning.c_str());
-          }
-        }
-      }
-    }
-
-    namespaces_[language] = name_space;
-  }
-
-  std::string get_namespace(std::string language) const {
-    std::map<std::string, std::string>::const_iterator iter;
-    if ((iter = namespaces_.find(language)) != namespaces_.end()
-        || (iter = namespaces_.find("*")) != namespaces_.end()) {
-      return iter->second;
-    }
-    return std::string();
-  }
-
-  const std::map<std::string, std::string>& get_all_namespaces(){
-     return namespaces_;
-  }
-
-  void set_namespace_annotations(std::string language, std::map<std::string, std::string> annotations) {
-    namespace_annotations_[language] = annotations;
-  }
-
-  const std::map<std::string, std::string>& get_namespace_annotations(std::string language) {
-    return namespace_annotations_[language];
-  }
-
-  // Language specific namespace / packaging
-
-  void add_cpp_include(std::string path) { cpp_includes_.push_back(path); }
-
-  const std::vector<std::string>& get_cpp_includes() { return cpp_includes_; }
-
-  void add_c_include(std::string path) { c_includes_.push_back(path); }
-
-  const std::vector<std::string>& get_c_includes() { return c_includes_; }
-
-private:
-  // File path
-  std::string path_;
-
-  // Name
-  std::string name_;
-
-  // Output directory
-  std::string out_path_;
-
-  // Output directory is absolute location for generated source (no gen-*)
-  bool out_path_is_absolute_;
-
-  // Namespace
-  std::string namespace_;
-
-  // Included programs
-  std::vector<t_program*> includes_;
-
-  // Include prefix for this program, if any
-  std::string include_prefix_;
-
-  // Identifier lookup scope
-  t_scope* scope_;
-
-  // Components to generate code for
-  std::vector<t_typedef*> typedefs_;
-  std::vector<t_enum*> enums_;
-  std::vector<t_const*> consts_;
-  std::vector<t_struct*> objects_;
-  std::vector<t_struct*> structs_;
-  std::vector<t_struct*> xceptions_;
-  std::vector<t_service*> services_;
-
-  // Dynamic namespaces
-  std::map<std::string, std::string> namespaces_;
-
-  // Annotations for dynamic namespaces
-  std::map<std::string, std::map<std::string, std::string> > namespace_annotations_;
-
-  // C++ extra includes
-  std::vector<std::string> cpp_includes_;
-
-  // C extra includes
-  std::vector<std::string> c_includes_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_scope.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_scope.h b/compiler/cpp/src/parse/t_scope.h
deleted file mode 100644
index 565fd8f..0000000
--- a/compiler/cpp/src/parse/t_scope.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_SCOPE_H
-#define T_SCOPE_H
-
-#include <map>
-#include <string>
-#include <sstream>
-
-#include "t_type.h"
-#include "t_service.h"
-#include "t_const.h"
-#include "t_const_value.h"
-#include "t_base_type.h"
-#include "t_map.h"
-#include "t_list.h"
-
-namespace plugin_output {
-template <typename From, typename To>
-void convert(From*, To&);
-}
-
-/**
- * This represents a variable scope used for looking up predefined types and
- * services. Typically, a scope is associated with a t_program. Scopes are not
- * used to determine code generation, but rather to resolve identifiers at
- * parse time.
- *
- */
-class t_scope {
-public:
-  t_scope() {}
-
-  void add_type(std::string name, t_type* type) { types_[name] = type; }
-
-  t_type* get_type(std::string name) { return types_[name]; }
-
-  void add_service(std::string name, t_service* service) { services_[name] = service; }
-
-  t_service* get_service(std::string name) { return services_[name]; }
-
-  void add_constant(std::string name, t_const* constant) {
-    if (constants_.find(name) != constants_.end()) {
-      throw "Enum " + name + " is already defined!";
-    } else {
-      constants_[name] = constant;
-    }
-  }
-
-  t_const* get_constant(std::string name) { return constants_[name]; }
-
-  void print() {
-    std::map<std::string, t_type*>::iterator iter;
-    for (iter = types_.begin(); iter != types_.end(); ++iter) {
-      printf("%s => %s\n", iter->first.c_str(), iter->second->get_name().c_str());
-    }
-  }
-
-  void resolve_const_value(t_const_value* const_val, t_type* ttype) {
-    if (ttype->is_map()) {
-      const std::map<t_const_value*, t_const_value*>& map = const_val->get_map();
-      std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
-      for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
-        resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type());
-        resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type());
-      }
-    } else if (ttype->is_list() || ttype->is_set()) {
-      const std::vector<t_const_value*>& val = const_val->get_list();
-      std::vector<t_const_value*>::const_iterator v_iter;
-      for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-        resolve_const_value((*v_iter), ((t_list*)ttype)->get_elem_type());
-      }
-    } else if (ttype->is_struct()) {
-      t_struct* tstruct = (t_struct*)ttype;
-      const std::map<t_const_value*, t_const_value*>& map = const_val->get_map();
-      std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
-      for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
-        t_field* field = tstruct->get_field_by_name(v_iter->first->get_string());
-        if (field == NULL) {
-          throw "No field named \"" + v_iter->first->get_string()
-              + "\" was found in struct of type \"" + tstruct->get_name() + "\"";
-        }
-        resolve_const_value(v_iter->second, field->get_type());
-      }
-    } else if (const_val->get_type() == t_const_value::CV_IDENTIFIER) {
-      if (ttype->is_enum()) {
-        const_val->set_enum((t_enum*)ttype);
-      } else {
-        t_const* constant = get_constant(const_val->get_identifier());
-        if (constant == NULL) {
-          throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!";
-        }
-
-        // Resolve typedefs to the underlying type
-        t_type* const_type = constant->get_type()->get_true_type();
-
-        if (const_type->is_base_type()) {
-          switch (((t_base_type*)const_type)->get_base()) {
-          case t_base_type::TYPE_I16:
-          case t_base_type::TYPE_I32:
-          case t_base_type::TYPE_I64:
-          case t_base_type::TYPE_BOOL:
-          case t_base_type::TYPE_I8:
-            const_val->set_integer(constant->get_value()->get_integer());
-            break;
-          case t_base_type::TYPE_STRING:
-            const_val->set_string(constant->get_value()->get_string());
-            break;
-          case t_base_type::TYPE_DOUBLE:
-            const_val->set_double(constant->get_value()->get_double());
-            break;
-          case t_base_type::TYPE_VOID:
-            throw "Constants cannot be of type VOID";
-          }
-        } else if (const_type->is_map()) {
-          const std::map<t_const_value*, t_const_value*>& map = constant->get_value()->get_map();
-          std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-          const_val->set_map();
-          for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
-            const_val->add_map(v_iter->first, v_iter->second);
-          }
-        } else if (const_type->is_list()) {
-          const std::vector<t_const_value*>& val = constant->get_value()->get_list();
-          std::vector<t_const_value*>::const_iterator v_iter;
-
-          const_val->set_list();
-          for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-            const_val->add_list(*v_iter);
-          }
-        }
-      }
-    } else if (ttype->is_enum()) {
-      // enum constant with non-identifier value. set the enum and find the
-      // value's name.
-      t_enum* tenum = (t_enum*)ttype;
-      t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer());
-      if (enum_value == NULL) {
-        std::ostringstream valstm;
-        valstm << const_val->get_integer();
-        throw "Couldn't find a named value in enum " + tenum->get_name() + " for value "
-            + valstm.str();
-      }
-      const_val->set_identifier(tenum->get_name() + "." + enum_value->get_name());
-      const_val->set_enum(tenum);
-    }
-  }
-
-private:
-  // Map of names to types
-  std::map<std::string, t_type*> types_;
-
-  // Map of names to constants
-  std::map<std::string, t_const*> constants_;
-
-  // Map of names to services
-  std::map<std::string, t_service*> services_;
-
-  // to list map entries
-  template <typename From, typename To>
-    friend void plugin_output::convert(From*, To&);
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_service.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_service.h b/compiler/cpp/src/parse/t_service.h
deleted file mode 100644
index 6fa8398..0000000
--- a/compiler/cpp/src/parse/t_service.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_SERVICE_H
-#define T_SERVICE_H
-
-#include "t_function.h"
-#include <vector>
-
-class t_program;
-
-/**
- * A service consists of a set of functions.
- *
- */
-class t_service : public t_type {
-public:
-  t_service(t_program* program) : t_type(program), extends_(NULL) {}
-
-  bool is_service() const { return true; }
-
-  void set_extends(t_service* extends) { extends_ = extends; }
-
-  void add_function(t_function* func) {
-    std::vector<t_function*>::const_iterator iter;
-    for (iter = functions_.begin(); iter != functions_.end(); ++iter) {
-      if (func->get_name() == (*iter)->get_name()) {
-        throw "Function " + func->get_name() + " is already defined";
-      }
-    }
-    functions_.push_back(func);
-  }
-
-  const std::vector<t_function*>& get_functions() const { return functions_; }
-
-  t_service* get_extends() { return extends_; }
-
-  const t_service* get_extends() const { return extends_; }
-
-private:
-  std::vector<t_function*> functions_;
-  t_service* extends_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_set.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_set.h b/compiler/cpp/src/parse/t_set.h
deleted file mode 100644
index 8a46480..0000000
--- a/compiler/cpp/src/parse/t_set.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_SET_H
-#define T_SET_H
-
-#include "t_container.h"
-
-/**
- * A set is a lightweight container type that just wraps another data type.
- *
- */
-class t_set : public t_container {
-public:
-  t_set(t_type* elem_type) : elem_type_(elem_type) {}
-
-  t_type* get_elem_type() const { return elem_type_; }
-
-  bool is_set() const { return true; }
-
-private:
-  t_type* elem_type_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_struct.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_struct.h b/compiler/cpp/src/parse/t_struct.h
deleted file mode 100644
index 1f48f91..0000000
--- a/compiler/cpp/src/parse/t_struct.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_STRUCT_H
-#define T_STRUCT_H
-
-#include <algorithm>
-#include <vector>
-#include <utility>
-#include <string>
-
-#include "t_type.h"
-#include "t_field.h"
-
-// Forward declare that puppy
-class t_program;
-
-/**
- * A struct is a container for a set of member fields that has a name. Structs
- * are also used to implement exception types.
- *
- */
-class t_struct : public t_type {
-public:
-  typedef std::vector<t_field*> members_type;
-
-  t_struct(t_program* program)
-    : t_type(program),
-      is_xception_(false),
-      is_union_(false),
-      members_validated(false),
-      members_with_value(0),
-      xsd_all_(false) {}
-
-  t_struct(t_program* program, const std::string& name)
-    : t_type(program, name),
-      is_xception_(false),
-      is_union_(false),
-      members_validated(false),
-      members_with_value(0),
-      xsd_all_(false) {}
-
-  void set_name(const std::string& name) {
-    name_ = name;
-    validate_union_members();
-  }
-
-  void set_xception(bool is_xception) { is_xception_ = is_xception; }
-
-  void validate_union_member(t_field* field) {
-    if (is_union_ && (!name_.empty())) {
-
-      // 1) unions can't have required fields
-      // 2) union members are implicitly optional, otherwise bugs like THRIFT-3650 wait to happen
-      if (field->get_req() != t_field::T_OPTIONAL) {
-        // no warning on default requiredness, but do warn on anything else that is explicitly asked for
-        if(field->get_req() != t_field::T_OPT_IN_REQ_OUT) {
-          pwarning(1,
-                   "Union %s field %s: union members must be optional, ignoring specified requiredness.\n",
-                   name_.c_str(),
-                   field->get_name().c_str());
-        }
-        field->set_req(t_field::T_OPTIONAL);
-      }
-
-      // unions may have up to one member defaulted, but not more
-      if (field->get_value() != NULL) {
-        if (1 < ++members_with_value) {
-          throw "Error: Field " + field->get_name() + " provides another default value for union "
-              + name_;
-        }
-      }
-    }
-  }
-
-  void validate_union_members() {
-    if (is_union_ && (!name_.empty()) && (!members_validated)) {
-      members_type::const_iterator m_iter;
-      for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
-        validate_union_member(*m_iter);
-      }
-      members_validated = true;
-    }
-  }
-
-  void set_union(bool is_union) {
-    is_union_ = is_union;
-    validate_union_members();
-  }
-
-  void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; }
-
-  bool get_xsd_all() const { return xsd_all_; }
-
-  bool append(t_field* elem) {
-    typedef members_type::iterator iter_type;
-    std::pair<iter_type, iter_type> bounds = std::equal_range(members_in_id_order_.begin(),
-                                                              members_in_id_order_.end(),
-                                                              elem,
-                                                              t_field::key_compare());
-    if (bounds.first != bounds.second) {
-      return false;
-    }
-    // returns false when there is a conflict of field names
-    if (get_field_by_name(elem->get_name()) != NULL) {
-      return false;
-    }
-    members_.push_back(elem);
-    members_in_id_order_.insert(bounds.second, elem);
-    validate_union_member(elem);
-    return true;
-  }
-
-  const members_type& get_members() const { return members_; }
-
-  const members_type& get_sorted_members() { return members_in_id_order_; }
-
-  bool is_struct() const { return !is_xception_; }
-
-  bool is_xception() const { return is_xception_; }
-
-  bool is_union() const { return is_union_; }
-
-  t_field* get_field_by_name(std::string field_name) {
-    members_type::const_iterator m_iter;
-    for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
-      if ((*m_iter)->get_name() == field_name) {
-        return *m_iter;
-      }
-    }
-    return NULL;
-  }
-
-  const t_field* get_field_by_name(std::string field_name) const {
-    members_type::const_iterator m_iter;
-    for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
-      if ((*m_iter)->get_name() == field_name) {
-        return *m_iter;
-      }
-    }
-    return NULL;
-  }
-
-private:
-  members_type members_;
-  members_type members_in_id_order_;
-  bool is_xception_;
-  bool is_union_;
-  bool members_validated;
-  int members_with_value;
-
-  bool xsd_all_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_type.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_type.h b/compiler/cpp/src/parse/t_type.h
deleted file mode 100644
index bea4ee1..0000000
--- a/compiler/cpp/src/parse/t_type.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_TYPE_H
-#define T_TYPE_H
-
-#include <string>
-#include <map>
-#include <cstring>
-#include <stdint.h>
-#include "t_doc.h"
-
-class t_program;
-
-/**
- * Generic representation of a thrift type. These objects are used by the
- * parser module to build up a tree of object that are all explicitly typed.
- * The generic t_type class exports a variety of useful methods that are
- * used by the code generator to branch based upon different handling for the
- * various types.
- *
- */
-class t_type : public t_doc {
-public:
-  virtual ~t_type() {}
-
-  virtual void set_name(const std::string& name) { name_ = name; }
-
-  virtual const std::string& get_name() const { return name_; }
-
-  virtual bool is_void() const { return false; }
-  virtual bool is_base_type() const { return false; }
-  virtual bool is_string() const { return false; }
-  virtual bool is_bool() const { return false; }
-  virtual bool is_typedef() const { return false; }
-  virtual bool is_enum() const { return false; }
-  virtual bool is_struct() const { return false; }
-  virtual bool is_xception() const { return false; }
-  virtual bool is_container() const { return false; }
-  virtual bool is_list() const { return false; }
-  virtual bool is_set() const { return false; }
-  virtual bool is_map() const { return false; }
-  virtual bool is_service() const { return false; }
-
-  t_program* get_program() { return program_; }
-
-  const t_program* get_program() const { return program_; }
-
-  t_type* get_true_type();
-  const t_type* get_true_type() const;
-
-  // This function will break (maybe badly) unless 0 <= num <= 16.
-  static char nybble_to_xdigit(int num) {
-    if (num < 10) {
-      return '0' + num;
-    } else {
-      return 'A' + num - 10;
-    }
-  }
-
-  static std::string byte_to_hex(uint8_t byte) {
-    std::string rv;
-    rv += nybble_to_xdigit(byte >> 4);
-    rv += nybble_to_xdigit(byte & 0x0f);
-    return rv;
-  }
-
-  std::map<std::string, std::string> annotations_;
-
-protected:
-  t_type() : program_(NULL) { ; }
-
-  t_type(t_program* program) : program_(program) { ; }
-
-  t_type(t_program* program, std::string name) : program_(program), name_(name) { ; }
-
-  t_type(std::string name) : program_(NULL), name_(name) { ; }
-
-  t_program* program_;
-  std::string name_;
-};
-
-/**
- * Placeholder struct for returning the key and value of an annotation
- * during parsing.
- */
-struct t_annotation {
-  std::string key;
-  std::string val;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_typedef.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_typedef.cc b/compiler/cpp/src/parse/t_typedef.cc
deleted file mode 100644
index ddbe749..0000000
--- a/compiler/cpp/src/parse/t_typedef.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-#include <cstdio>
-
-#include "t_typedef.h"
-#include "t_program.h"
-
-t_type* t_typedef::get_type() const {
-  if (type_ == NULL) {
-    t_type* type = get_program()->scope()->get_type(symbolic_);
-    if (type == NULL) {
-      printf("Type \"%s\" not defined\n", symbolic_.c_str());
-      exit(1);
-    }
-    return type;
-  }
-  return type_;
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/t_typedef.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_typedef.h b/compiler/cpp/src/parse/t_typedef.h
deleted file mode 100644
index a39a246..0000000
--- a/compiler/cpp/src/parse/t_typedef.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_TYPEDEF_H
-#define T_TYPEDEF_H
-
-#include <string>
-#include "t_type.h"
-
-/**
- * A typedef is a mapping from a symbolic name to another type. In dymanically
- * typed languages (i.e. php/python) the code generator can actually usually
- * ignore typedefs and just use the underlying type directly, though in C++
- * the symbolic naming can be quite useful for code clarity.
- *
- */
-class t_typedef : public t_type {
-public:
-  t_typedef(t_program* program, t_type* type, const std::string& symbolic)
-    : t_type(program, symbolic), type_(type), symbolic_(symbolic), forward_(false), seen_(false) {}
-
-  /**
-   * This constructor is used to refer to a type that is lazily
-   * resolved at a later time, like for forward declarations or
-   * recursive types.
-   */
-  t_typedef(t_program* program, const std::string& symbolic, bool forward)
-    : t_type(program, symbolic),
-      type_(NULL),
-      symbolic_(symbolic),
-      forward_(forward),
-      seen_(false) {}
-
-  ~t_typedef() {}
-
-  t_type* get_type() const;
-
-  const std::string& get_symbolic() const { return symbolic_; }
-
-  bool is_forward_typedef() const { return forward_; }
-
-  bool is_typedef() const { return true; }
-
-private:
-  t_type* type_;
-  std::string symbolic_;
-  bool forward_;
-  mutable bool seen_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/platform.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/platform.h b/compiler/cpp/src/platform.h
deleted file mode 100644
index 8cbe9db..0000000
--- a/compiler/cpp/src/platform.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-/**
- * define for mkdir,since the method signature
- * is different for the non-POSIX MinGW
- */
-
-#ifdef _MSC_VER
-#include "windows/config.h"
-#endif
-
-#ifdef _WIN32
-#include <direct.h>
-#include <io.h>
-#else
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-
-#ifdef _WIN32
-#define MKDIR(x) mkdir(x)
-#else
-#define MKDIR(x) mkdir(x, S_IRWXU | S_IRWXG | S_IRWXO)
-#endif
-
-#ifdef PATH_MAX
-#define THRIFT_PATH_MAX PATH_MAX
-#else
-#define THRIFT_PATH_MAX MAX_PATH
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/Makefile.am
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/Makefile.am b/compiler/cpp/src/plugin/Makefile.am
deleted file mode 100644
index 7e3c82d..0000000
--- a/compiler/cpp/src/plugin/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you 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.
-#
-#
-# Contains some contributions under the Thrift Software License.
-# Please see doc/old-thrift-license.txt in the Thrift distribution for
-# details.
-
-AUTOMAKE_OPTIONS = subdir-objects
-
-if WITH_PLUGIN
-plugin_gen = plugin_types.h \
-             plugin_types.cpp \
-             plugin_constants.h \
-             plugin_constants.cpp
-
-BUILT_SOURCES = $(plugin_gen)
-gen.stamp: plugin.thrift $(top_builddir)/compiler/cpp/src/thrift-bootstrap
-	@$(RM) -f gen.tmp
-	@touch gen.tmp
-	$(top_builddir)/compiler/cpp/src/thrift-bootstrap -gen cpp -out . $<
-	@mv -f gen.tmp $@
-
-$(plugin_gen): gen.stamp
-	@if test -f $@; then :; else \
-	$(RM) -f gen.stamp; \
-	$(MAKE) $(AM_MAKEFLAGS) gen.stamp; \
-	fi
-
-clean-local:
-	$(RM) version.h windows/version.h $(plugin_gen)
-endif


[30/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_php_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
deleted file mode 100644
index 2fa9b24..0000000
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ /dev/null
@@ -1,2653 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_oop_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-#define NSGLOBAL (nsglobal_.size() ? nsglobal_ : "")
-#define NSGLOBAL_A ("\\" + NSGLOBAL)
-#define NSGLOBAL_B (NSGLOBAL + "\\")
-#define NSGLOBAL_AB ("\\" + NSGLOBAL + "\\")
-
-/**
- * PHP code generator.
- *
- */
-class t_php_generator : public t_oop_generator {
-public:
-  t_php_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    binary_inline_ = false;
-    rest_ = false;
-    phps_ = false;
-    oop_ = false;
-    validate_ = false;
-    json_serializable_ = false;
-    nsglobal_ = ""; // by default global namespace is empty
-    psr4_ = false;
-    for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if (iter->first.compare("inlined") == 0) {
-        binary_inline_ = true;
-      } else if (iter->first.compare("rest") == 0) {
-        rest_ = true;
-      } else if (iter->first.compare("server") == 0) {
-        phps_ = true;
-      } else if (iter->first.compare("oop") == 0) {
-        oop_ = true;
-      } else if (iter->first.compare("validate") == 0) {
-        validate_ = true;
-      } else if (iter->first.compare("json") == 0) {
-        json_serializable_ = true;
-      } else if (iter->first.compare("nsglobal") == 0) {
-        nsglobal_ = iter->second;
-      } else if (iter->first.compare("psr4") == 0) {
-        psr4_ = true;
-      } else {
-        throw "unknown option php:" + iter->first;
-      }
-    }
-
-    if (oop_ && binary_inline_) {
-      throw "oop and inlined are mutually exclusive.";
-    }
-
-    out_dir_base_ = (binary_inline_ ? "gen-phpi" : "gen-php");
-    escape_['$'] = "\\$";
-  }
-
-  static bool is_valid_namespace(const std::string& sub_namespace);
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_consts(vector<t_const*> consts);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-
-  /**
-   * Structs!
-   */
-
-  void generate_php_struct(t_struct* tstruct, bool is_exception);
-  void generate_php_struct_definition(std::ofstream& out,
-                                      t_struct* tstruct,
-                                      bool is_xception = false,
-                                      bool is_result = false);
-  void generate_php_struct_reader(std::ofstream& out, t_struct* tstruct, bool is_result);
-  void generate_php_struct_writer(std::ofstream& out, t_struct* tstruct, bool is_result);
-  void generate_php_function_helpers(t_service* tservice, t_function* tfunction);
-  void generate_php_struct_required_validator(ofstream& out,
-                                              t_struct* tstruct,
-                                              std::string method_name,
-                                              bool write_mode);
-  void generate_php_struct_read_validator(ofstream& out, t_struct* tstruct);
-  void generate_php_struct_write_validator(ofstream& out, t_struct* tstruct);
-  void generate_php_struct_json_serialize(ofstream& out, t_struct* tstruct, bool is_result);
-  bool needs_php_write_validator(t_struct* tstruct, bool is_result);
-  bool needs_php_read_validator(t_struct* tstruct, bool is_result);
-  int get_php_num_required_fields(const vector<t_field*>& fields, bool write_mode);
-
-  void generate_php_type_spec(std::ofstream& out, t_type* t);
-  void generate_php_struct_spec(std::ofstream& out, t_struct* tstruct);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_rest(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_processor(t_service* tservice);
-  void generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction);
-  void generate_service_header(t_service* tservice, std::ofstream& file);
-  void generate_program_header(std::ofstream& file);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  bool inclass = false);
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_php_doc(std::ofstream& out, t_doc* tdoc);
-
-  void generate_php_doc(std::ofstream& out, t_field* tfield);
-
-  void generate_php_doc(std::ofstream& out, t_function* tfunction);
-
-  void generate_php_docstring_comment(std::ofstream& out, string contents);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string php_includes();
-  std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct, bool addTypeHints = true);
-  std::string type_to_cast(t_type* ttype);
-  std::string type_to_enum(t_type* ttype);
-  std::string type_to_phpdoc(t_type* ttype);
-
-  std::string php_namespace_base(const t_program* p) {
-    std::string ns = p->get_namespace("php");
-    const char* delimiter = "\\";
-    size_t position = ns.find('.');
-    while (position != string::npos) {
-      ns.replace(position, 1, delimiter);
-      position = ns.find('.', position + 1);
-    }
-    return ns;
-  }
-
-  // general use namespace prefixing: \my\namespace\ or my_namespace_
-  string php_namespace(const t_program* p) {
-    string ns = php_namespace_base(p);
-    return (nsglobal_.size() ? NSGLOBAL_AB : NSGLOBAL_B) + (ns.size() ? (ns + "\\") : "");
-  }
-
-  // setting the namespace of a file: my\namespace
-  string php_namespace_suffix(const t_program* p) {
-    string ns = php_namespace_base(p);
-
-    return (nsglobal_.size() ? NSGLOBAL_B : NSGLOBAL) + ns;
-  }
-
-  // add a directory to already existing namespace
-  string php_namespace_directory(string directory, bool end = true) {
-    (void)directory;
-    if (end) {
-      return ";";
-    } else {
-      return "";
-    }
-  }
-
-  // writing an autload identifier into globa;ls: my\namespace\ or my_namespace_
-  string php_namespace_autoload(const t_program* p) {
-    std::string ns = php_namespace_base(p);
-    return (nsglobal_.size() ? NSGLOBAL_B : NSGLOBAL) + (ns.size() ? (ns + "\\") : "");
-  }
-
-  // declaring a type: typename or my_namespace_typename
-  string php_namespace_declaration(t_type* t) { return t->get_name(); }
-
-  std::string php_path(t_program* p) {
-    std::string ns = p->get_namespace("php.path");
-    if (ns.empty()) {
-      return p->get_name();
-    }
-
-    // Transform the java-style namespace into a path.
-    for (std::string::iterator it = ns.begin(); it != ns.end(); ++it) {
-      if (*it == '.') {
-        *it = '/';
-      }
-    }
-
-    return ns + '/';
-  }
-
-  /**
-   * Transform class_method into ClassMethod
-   *
-   * @param str
-   * @return stirng
-   */
-  string classify(string str) {
-    string classe = "";
-
-    vector<string> x = split(str, '_');
-
-    for (size_t i = 0; i < x.size(); ++i) {
-      classe = classe + capitalize(x[i]);
-    }
-
-    return classe;
-  }
-
-  /**
-   * Split method
-   * @param s
-   * @param delim
-   * @param elems
-   * @return
-   */
-  vector<string>& split(const string& s, char delim, vector<string>& elems) {
-    stringstream ss(s);
-    string item;
-
-    while (getline(ss, item, delim)) {
-      elems.push_back(item);
-    }
-
-    return elems;
-  }
-
-  vector<string> split(const string& s, char delim) {
-    vector<string> elems;
-
-    return split(s, delim, elems);
-  }
-
-  /**
-   * Capitalize method
-   * @param str
-   * @return
-   */
-  string capitalize(string str) {
-    string::iterator it(str.begin());
-
-    if (it != str.end())
-      str[0] = toupper((unsigned char)str[0]);
-
-    //    while(++it != str.end())
-    //    {
-    //      *it = tolower((unsigned char)*it);
-    //    }
-    return str;
-  }
-
-private:
-  /**
-   * File streams
-   */
-  std::ofstream f_types_;
-  std::ofstream f_service_;
-
-  std::string package_dir_;
-  /**
-   * Generate protocol-independent template? Or Binary inline code?
-   */
-  bool binary_inline_;
-
-  /**
-   * Generate a REST handler class
-   */
-  bool rest_;
-
-  /**
-   * Generate stubs for a PHP server
-   */
-  bool phps_;
-
-  /**
-   * Whether to use OOP base class TBase
-   */
-  bool oop_;
-
-  /**
-   * Whether to hold each class in separate file to allow PSR4-autoloading
-   */
-  bool psr4_;
-
-  /**
-   * Whether to generate validator code
-   */
-  bool validate_;
-
-  /**
-   * Whether to generate JsonSerializable classes
-   */
-  bool json_serializable_;
-
-  /**
-   * Global namespace for PHP 5.3
-   */
-  std::string nsglobal_;
-};
-
-bool t_php_generator::is_valid_namespace(const std::string& sub_namespace) {
-  return sub_namespace == "path";
-}
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_php_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  // Create Real directory Namespaces
-  vector<string> NSx = split(php_namespace_suffix(get_program()), '\\');
-  package_dir_ = get_out_dir();
-
-  for (size_t i = 0; i < NSx.size(); ++i) {
-    package_dir_ = package_dir_ + "/" + NSx[i] + "/";
-    MKDIR(package_dir_.c_str());
-  }
-
-  // Prepare output file for all the types in non-psr4 mode
-  if (!psr4_) {
-    // Make output file
-    string f_types_name = package_dir_ + "Types.php";
-    f_types_.open(f_types_name.c_str());
-    generate_program_header(f_types_);
-  }
-}
-
-/**
- * Prints standard php includes
- */
-string t_php_generator::php_includes() {
-  string includes = "use Thrift\\Base\\TBase;\n"
-                    "use Thrift\\Type\\TType;\n"
-                    "use Thrift\\Type\\TMessageType;\n"
-                    "use Thrift\\Exception\\TException;\n"
-                    "use Thrift\\Exception\\TProtocolException;\n"
-                    "use Thrift\\Protocol\\TProtocol;\n"
-                    "use Thrift\\Protocol\\TBinaryProtocolAccelerated;\n"
-                    "use Thrift\\Exception\\TApplicationException;\n";
-
-  if (json_serializable_) {
-    includes += "use JsonSerializable;\n"
-                "use stdClass;\n";
-  }
-
-  return includes + "\n";
-}
-
-/**
- * Close up (or down) some filez.
- */
-void t_php_generator::close_generator() {
-  if (!psr4_) {
-    // Close types file
-    f_types_ << endl;
-    f_types_.close();
-  }
-}
-
-/**
- * Generates a typedef. This is not done in PHP, types are all implicit.
- *
- * @param ttypedef The type definition
- */
-void t_php_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Generates service header contains namespace suffix and includes inside file specified
- */
-void t_php_generator::generate_service_header(t_service* tservice, std::ofstream& file) {
-  file << "<?php" << endl;
-  if (!php_namespace_suffix(tservice->get_program()).empty()) {
-    file << "namespace " << php_namespace_suffix(tservice->get_program()) << ";" << endl;
-  }
-  file << autogen_comment() << php_includes();
-
-  file << endl;
-}
-
-/**
- * Generates program header contains namespace suffix and includes inside file specified
- */
-void t_php_generator::generate_program_header(std::ofstream& file) {
-  file << "<?php" << endl;
-  if (!php_namespace_suffix(get_program()).empty()) {
-    file << "namespace " << php_namespace_suffix(get_program()) << ";" << endl << endl;
-  }
-  file << autogen_comment() << php_includes();
-
-  file << endl;
-}
-
-/**
- * Generates code for an enumerated type. Since define is expensive to lookup
- * in PHP, we use a global array for this.
- *
- * @param tenum The enumeration
- */
-void t_php_generator::generate_enum(t_enum* tenum) {
-  std::ofstream& f_enum = f_types_;
-  if (psr4_) {
-    string f_enum_name = package_dir_ + tenum->get_name() + ".php";
-    f_enum.open(f_enum_name.c_str());
-    generate_program_header(f_enum);
-  }
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-
-  // We're also doing it this way to see how it performs. It's more legible
-  // code but you can't do things like an 'extract' on it, which is a bit of
-  // a downer.
-  generate_php_doc(f_enum, tenum);
-  f_enum << "final class " << tenum->get_name() << " {" << endl;
-  indent_up();
-
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    generate_php_doc(f_enum, *c_iter);
-    indent(f_enum) << "const " << (*c_iter)->get_name() << " = " << value << ";" << endl;
-  }
-
-  indent(f_enum) << "static public $__names = array(" << endl;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << "  " << value << " => '" << (*c_iter)->get_name() << "'," << endl;
-  }
-  indent(f_enum) << ");" << endl;
-
-  indent_down();
-
-  f_enum << "}" << endl << endl;
-  if (psr4_) {
-    f_enum.close();
-  }
-}
-
-/**
- * Generate constant class
- *
- * Override the one from t_generator
- */
-void t_php_generator::generate_consts(vector<t_const*> consts) {
-  vector<t_const*>::iterator c_iter;
-
-  // Create class only if needed
-  if (consts.size() > 0) {
-
-    std::ofstream& f_consts = f_types_;
-    if (psr4_) {
-      string f_consts_name = package_dir_ + "Constant.php";
-      f_consts.open(f_consts_name.c_str());
-      generate_program_header(f_consts);
-    }
-    f_consts << "final class Constant extends \\Thrift\\Type\\TConstant {" << endl;
-
-    indent_up();
-
-    // Create static property
-    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      string name = (*c_iter)->get_name();
-
-      indent(f_consts) << "static protected $" << name << ";" << endl;
-    }
-
-    // Create init function
-    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      string name = (*c_iter)->get_name();
-
-      f_consts << endl;
-
-      indent(f_consts) << "static protected function init_" << name << "() {" << endl;
-      indent_up();
-
-      indent(f_consts) << "return ";
-      generate_php_doc(f_consts, *c_iter);
-      f_consts << render_const_value((*c_iter)->get_type(), (*c_iter)->get_value());
-      f_consts << ";" << endl;
-
-      indent_down();
-      indent(f_consts) << "}" << endl;
-    }
-
-    indent_down();
-    f_consts << "}" << endl << endl;
-    if (psr4_) {
-      f_consts.close();
-    }
-  }
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_php_generator::render_const_value(t_type* type, t_const_value* value) {
-  std::ostringstream out;
-  type = get_true_type(type);
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    indent(out) << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl;
-    indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      out << indent();
-      out << render_const_value(g_type_string, v_iter->first);
-      out << " => ";
-      out << render_const_value(field_type, v_iter->second);
-      out << "," << endl;
-    }
-    indent_down();
-    indent(out) << "))";
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    out << "array(" << endl;
-    indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent();
-      out << render_const_value(ktype, v_iter->first);
-      out << " => ";
-      out << render_const_value(vtype, v_iter->second);
-      out << "," << endl;
-    }
-    indent_down();
-    indent(out) << ")";
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    out << "array(" << endl;
-    indent_up();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent();
-      out << render_const_value(etype, *v_iter);
-      if (type->is_set()) {
-        out << " => true";
-      }
-      out << "," << endl;
-    }
-    indent_down();
-    indent(out) << ")";
-  }
-  return out.str();
-}
-
-/**
- * Make a struct
- */
-void t_php_generator::generate_struct(t_struct* tstruct) {
-  generate_php_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_php_generator::generate_xception(t_struct* txception) {
-  generate_php_struct(txception, true);
-}
-
-/**
- * Structs can be normal or exceptions.
- */
-void t_php_generator::generate_php_struct(t_struct* tstruct, bool is_exception) {
-  std::ofstream& f_struct = f_types_;
-  if (psr4_) {
-    string f_struct_name = package_dir_ + tstruct->get_name() + ".php";
-    f_struct.open(f_struct_name.c_str());
-    generate_program_header(f_struct);
-  }
-  generate_php_struct_definition(f_struct, tstruct, is_exception);
-  if (psr4_) {
-    f_struct.close();
-  }
-}
-
-void t_php_generator::generate_php_type_spec(ofstream& out, t_type* t) {
-  t = get_true_type(t);
-  indent(out) << "'type' => " << type_to_enum(t) << "," << endl;
-
-  if (t->is_base_type() || t->is_enum()) {
-    // Noop, type is all we need
-  } else if (t->is_struct() || t->is_xception()) {
-    indent(out) << "'class' => '" << php_namespace(t->get_program()) << t->get_name() << "',"
-                << endl;
-  } else if (t->is_map()) {
-    t_type* ktype = get_true_type(((t_map*)t)->get_key_type());
-    t_type* vtype = get_true_type(((t_map*)t)->get_val_type());
-    indent(out) << "'ktype' => " << type_to_enum(ktype) << "," << endl;
-    indent(out) << "'vtype' => " << type_to_enum(vtype) << "," << endl;
-    indent(out) << "'key' => array(" << endl;
-    indent_up();
-    generate_php_type_spec(out, ktype);
-    indent_down();
-    indent(out) << ")," << endl;
-    indent(out) << "'val' => array(" << endl;
-    indent_up();
-    generate_php_type_spec(out, vtype);
-    indent(out) << ")," << endl;
-    indent_down();
-  } else if (t->is_list() || t->is_set()) {
-    t_type* etype;
-    if (t->is_list()) {
-      etype = get_true_type(((t_list*)t)->get_elem_type());
-    } else {
-      etype = get_true_type(((t_set*)t)->get_elem_type());
-    }
-    indent(out) << "'etype' => " << type_to_enum(etype) << "," << endl;
-    indent(out) << "'elem' => array(" << endl;
-    indent_up();
-    generate_php_type_spec(out, etype);
-    indent(out) << ")," << endl;
-    indent_down();
-  } else {
-    throw "compiler error: no type for php struct spec field";
-  }
-}
-
-/**
- * Generates the struct specification structure, which fully qualifies enough
- * type information to generalize serialization routines.
- */
-void t_php_generator::generate_php_struct_spec(ofstream& out, t_struct* tstruct) {
-  indent(out) << "if (!isset(self::$_TSPEC)) {" << endl;
-  indent_up();
-
-  indent(out) << "self::$_TSPEC = array(" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    indent(out) << (*m_iter)->get_key() << " => array(" << endl;
-    indent_up();
-    out << indent() << "'var' => '" << (*m_iter)->get_name() << "'," << endl;
-    generate_php_type_spec(out, t);
-    indent(out) << ")," << endl;
-    indent_down();
-  }
-
-  indent_down();
-  indent(out) << "  );" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is nothing in PHP
- * where the objects are all just associative arrays (unless of course we
- * decide to start using objects for them...)
- *
- * @param tstruct The struct definition
- */
-void t_php_generator::generate_php_struct_definition(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_exception,
-                                                     bool is_result) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  generate_php_doc(out, tstruct);
-  out << "class " << php_namespace_declaration(tstruct);
-  if (is_exception) {
-    out << " extends "
-        << "TException";
-  } else if (oop_) {
-    out << " extends "
-        << "TBase";
-  }
-  if (json_serializable_) {
-    out << " implements JsonSerializable";
-  }
-  out << " {" << endl;
-  indent_up();
-
-  indent(out) << "static $_TSPEC;" << endl << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    string dval = "null";
-    t_type* t = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
-      dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
-    }
-    generate_php_doc(out, *m_iter);
-    indent(out) << "public $" << (*m_iter)->get_name() << " = " << dval << ";" << endl;
-  }
-
-  out << endl;
-
-  // Generate constructor from array
-  string param = (members.size() > 0) ? "$vals=null" : "";
-  out << indent() << "public function __construct(" << param << ") {" << endl;
-  indent_up();
-
-  generate_php_struct_spec(out, tstruct);
-
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
-        indent(out) << "$this->" << (*m_iter)->get_name() << " = "
-                    << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
-      }
-    }
-    out << indent() << "if (is_array($vals)) {" << endl;
-    indent_up();
-    if (oop_) {
-      out << indent() << "parent::__construct(self::$_TSPEC, $vals);" << endl;
-    } else {
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        out << indent() << "if (isset($vals['" << (*m_iter)->get_name() << "'])) {" << endl
-            << indent() << "  $this->" << (*m_iter)->get_name() << " = $vals['"
-            << (*m_iter)->get_name() << "'];" << endl << indent() << "}" << endl;
-      }
-    }
-    indent_down();
-    out << indent() << "}" << endl;
-  }
-  scope_down(out);
-  out << endl;
-
-  out << indent() << "public function getName() {" << endl << indent() << "  return '"
-      << tstruct->get_name() << "';" << endl << indent() << "}" << endl << endl;
-
-  generate_php_struct_reader(out, tstruct, is_result);
-  generate_php_struct_writer(out, tstruct, is_result);
-  if (needs_php_read_validator(tstruct, is_result)) {
-    generate_php_struct_read_validator(out, tstruct);
-  }
-  if (needs_php_write_validator(tstruct, is_result)) {
-    generate_php_struct_write_validator(out, tstruct);
-  }
-  if (json_serializable_) {
-    generate_php_struct_json_serialize(out, tstruct, is_result);
-  }
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates the read() method for a struct
- */
-void t_php_generator::generate_php_struct_reader(ofstream& out, t_struct* tstruct, bool is_result) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "public function read($input)" << endl;
-  scope_up(out);
-
-  if (oop_) {
-    if (needs_php_read_validator(tstruct, is_result)) {
-      indent(out) << "$tmp = $this->_read('" << tstruct->get_name() << "', self::$_TSPEC, $input);"
-                  << endl;
-      indent(out) << "$this->_validateForRead();" << endl;
-      indent(out) << "return $tmp;" << endl;
-    } else {
-      indent(out) << "return $this->_read('" << tstruct->get_name() << "', self::$_TSPEC, $input);"
-                  << endl;
-    }
-    scope_down(out);
-    out << endl;
-    return;
-  }
-
-  out << indent() << "$xfer = 0;" << endl << indent() << "$fname = null;" << endl << indent()
-      << "$ftype = 0;" << endl << indent() << "$fid = 0;" << endl;
-
-  // Declare stack tmp variables
-  if (!binary_inline_) {
-    indent(out) << "$xfer += $input->readStructBegin($fname);" << endl;
-  }
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-
-  scope_up(out);
-
-  // Read beginning field marker
-  if (binary_inline_) {
-    t_field fftype(g_type_i8, "ftype");
-    t_field ffid(g_type_i16, "fid");
-    generate_deserialize_field(out, &fftype);
-    out << indent() << "if ($ftype == "
-        << "TType::STOP) {" << endl << indent() << "  break;" << endl << indent() << "}" << endl;
-    generate_deserialize_field(out, &ffid);
-  } else {
-    indent(out) << "$xfer += $input->readFieldBegin($fname, $ftype, $fid);" << endl;
-    // Check for field STOP marker and break
-    indent(out) << "if ($ftype == "
-                << "TType::STOP) {" << endl;
-    indent_up();
-    indent(out) << "break;" << endl;
-    indent_down();
-    indent(out) << "}" << endl;
-  }
-
-  // Switch statement on the field we are reading
-  indent(out) << "switch ($fid)" << endl;
-
-  scope_up(out);
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
-    indent_up();
-    indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-    generate_deserialize_field(out, *f_iter, "this->");
-    indent_down();
-    out << indent() << "} else {" << endl;
-    if (binary_inline_) {
-      indent(out) << "  $xfer += "
-                  << "TProtocol::skipBinary($input, $ftype);" << endl;
-    } else {
-      indent(out) << "  $xfer += $input->skip($ftype);" << endl;
-    }
-    out << indent() << "}" << endl << indent() << "break;" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  indent(out) << "default:" << endl;
-  if (binary_inline_) {
-    indent(out) << "  $xfer += "
-                << "TProtocol::skipBinary($input, $ftype);" << endl;
-  } else {
-    indent(out) << "  $xfer += $input->skip($ftype);" << endl;
-  }
-  indent(out) << "  break;" << endl;
-
-  scope_down(out);
-
-  if (!binary_inline_) {
-    // Read field end marker
-    indent(out) << "$xfer += $input->readFieldEnd();" << endl;
-  }
-
-  scope_down(out);
-
-  if (!binary_inline_) {
-    indent(out) << "$xfer += $input->readStructEnd();" << endl;
-  }
-
-  if (needs_php_read_validator(tstruct, is_result)) {
-    indent(out) << "$this->_validateForRead();" << endl;
-  }
-
-  indent(out) << "return $xfer;" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates the write() method for a struct
- */
-void t_php_generator::generate_php_struct_writer(ofstream& out, t_struct* tstruct, bool is_result) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  if (binary_inline_) {
-    indent(out) << "public function write(&$output) {" << endl;
-  } else {
-    indent(out) << "public function write($output) {" << endl;
-  }
-  indent_up();
-
-  if (needs_php_write_validator(tstruct, is_result)) {
-    indent(out) << "$this->_validateForWrite();" << endl;
-  }
-
-  if (oop_) {
-    indent(out) << "return $this->_write('" << tstruct->get_name() << "', self::$_TSPEC, $output);"
-                << endl;
-    scope_down(out);
-    out << endl;
-    return;
-  }
-
-  indent(out) << "$xfer = 0;" << endl;
-
-  if (!binary_inline_) {
-    indent(out) << "$xfer += $output->writeStructBegin('" << name << "');" << endl;
-  }
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    out << indent() << "if ($this->" << (*f_iter)->get_name() << " !== null) {" << endl;
-    indent_up();
-
-    t_type* type = get_true_type((*f_iter)->get_type());
-    string expect;
-    if (type->is_container()) {
-      expect = "array";
-    } else if (type->is_struct()) {
-      expect = "object";
-    }
-    if (!expect.empty()) {
-      out << indent() << "if (!is_" << expect << "($this->" << (*f_iter)->get_name() << ")) {"
-          << endl;
-      indent_up();
-      out << indent() << "throw new "
-          << "TProtocolException('Bad type in structure.', "
-          << "TProtocolException::INVALID_DATA);" << endl;
-      scope_down(out);
-    }
-
-    // Write field header
-    if (binary_inline_) {
-      out << indent() << "$output .= pack('c', " << type_to_enum((*f_iter)->get_type()) << ");"
-          << endl << indent() << "$output .= pack('n', " << (*f_iter)->get_key() << ");" << endl;
-    } else {
-      indent(out) << "$xfer += $output->writeFieldBegin("
-                  << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
-                  << ", " << (*f_iter)->get_key() << ");" << endl;
-    }
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this->");
-
-    // Write field closer
-    if (!binary_inline_) {
-      indent(out) << "$xfer += $output->writeFieldEnd();" << endl;
-    }
-
-    indent_down();
-    indent(out) << "}" << endl;
-  }
-
-  if (binary_inline_) {
-    out << indent() << "$output .= pack('c', "
-        << "TType::STOP);" << endl;
-  } else {
-    out << indent() << "$xfer += $output->writeFieldStop();" << endl << indent()
-        << "$xfer += $output->writeStructEnd();" << endl;
-  }
-
-  out << indent() << "return $xfer;" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-void t_php_generator::generate_php_struct_read_validator(ofstream& out, t_struct* tstruct) {
-  generate_php_struct_required_validator(out, tstruct, "_validateForRead", false);
-}
-
-void t_php_generator::generate_php_struct_write_validator(ofstream& out, t_struct* tstruct) {
-  generate_php_struct_required_validator(out, tstruct, "_validateForWrite", true);
-}
-
-void t_php_generator::generate_php_struct_required_validator(ofstream& out,
-                                                             t_struct* tstruct,
-                                                             std::string method_name,
-                                                             bool write_mode) {
-  indent(out) << "private function " << method_name << "() {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-
-  if (fields.size() > 0) {
-    vector<t_field*>::const_iterator f_iter;
-
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* field = (*f_iter);
-      if (field->get_req() == t_field::T_REQUIRED
-          || (field->get_req() == t_field::T_OPT_IN_REQ_OUT && write_mode)) {
-        indent(out) << "if ($this->" << field->get_name() << " === null) {" << endl;
-        indent_up();
-        indent(out) << "throw new TProtocolException('Required field " << tstruct->get_name() << "."
-                    << field->get_name() << " is unset!');" << endl;
-        indent_down();
-        indent(out) << "}" << endl;
-      }
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_php_generator::generate_php_struct_json_serialize(ofstream& out,
-                                                         t_struct* tstruct,
-                                                         bool is_result) {
-  indent(out) << "public function jsonSerialize() {" << endl;
-  indent_up();
-
-  if (needs_php_write_validator(tstruct, is_result)) {
-    indent(out) << "$this->_validateForWrite();" << endl;
-  }
-
-  indent(out) << "$json = new stdClass;" << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-
-  if (fields.size() > 0) {
-    vector<t_field*>::const_iterator f_iter;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* field = (*f_iter);
-      t_type* type = field->get_type();
-      const string& name = field->get_name();
-      if (type->is_map()) {
-        t_type* key_type = ((t_map*)type)->get_key_type();
-        if (!(key_type->is_base_type() || key_type->is_enum())) {
-          // JSON object keys must be strings. PHP's json_encode()
-          // function will convert any scalar key to strings, but
-          // we skip thrift maps with non-scalar keys.
-          continue;
-        }
-      }
-      indent(out) << "if ($this->" << name << " !== null) {" << endl;
-      indent_up();
-      indent(out) << "$json->" << name << " = ";
-      if (type->is_map()) {
-        out << "(object)";
-      } else {
-        out << type_to_cast(type);
-      }
-      out << "$this->" << name << ";" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-
-  indent(out) << "return $json;" << endl;
-  indent_down();
-
-  indent(out) << "}" << endl << endl;
-}
-
-int t_php_generator::get_php_num_required_fields(const vector<t_field*>& fields, bool write_mode) {
-  int num_req = 0;
-
-  if (fields.size() > 0) {
-    vector<t_field*>::const_iterator f_iter;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if ((*f_iter)->get_req() == t_field::T_REQUIRED
-          || ((*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT && write_mode)) {
-        ++num_req;
-      }
-    }
-  }
-  return num_req;
-}
-
-bool t_php_generator::needs_php_write_validator(t_struct* tstruct, bool is_result) {
-  return (validate_ && !is_result && !tstruct->is_union()
-          && get_php_num_required_fields(tstruct->get_members(), true) > 0);
-}
-
-bool t_php_generator::needs_php_read_validator(t_struct* tstruct, bool is_result) {
-  return (validate_ && !is_result
-          && (get_php_num_required_fields(tstruct->get_members(), false) > 0));
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_php_generator::generate_service(t_service* tservice) {
-  if(!psr4_) {
-    string f_service_name = package_dir_ + service_name_ + ".php";
-    f_service_.open(f_service_name.c_str());
-    generate_service_header(tservice, f_service_);
-  }
-
-  // Generate the three main parts of the service (well, two for now in PHP)
-  generate_service_interface(tservice);
-  if (rest_) {
-    generate_service_rest(tservice);
-  }
-  generate_service_client(tservice);
-  generate_service_helpers(tservice);
-  if (phps_) {
-    generate_service_processor(tservice);
-  }
-
-  if(!psr4_) {
-    // Close service file
-    f_service_ << endl;
-    f_service_.close();
-  }
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_php_generator::generate_service_processor(t_service* tservice) {
-  std::ofstream& f_service_processor = f_service_;
-  if (psr4_) {
-    string f_service_processor_name = package_dir_ + service_name_ + "Processor.php";
-    f_service_processor.open(f_service_processor_name.c_str());
-    generate_service_header(tservice, f_service_processor);
-  }
-
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = tservice->get_extends()->get_name();
-    extends_processor = " extends " + php_namespace(tservice->get_extends()->get_program())
-                        + extends + "Processor";
-  }
-
-  // Generate the header portion
-  f_service_processor << "class " << service_name_ << "Processor" << extends_processor << " {" << endl;
-  indent_up();
-
-  if (extends.empty()) {
-    f_service_processor << indent() << "protected $handler_ = null;" << endl;
-  }
-
-  f_service_processor << indent() << "public function __construct($handler) {" << endl;
-  if (extends.empty()) {
-    f_service_processor << indent() << "  $this->handler_ = $handler;" << endl;
-  } else {
-    f_service_processor << indent() << "  parent::__construct($handler);" << endl;
-  }
-  f_service_processor << indent() << "}" << endl << endl;
-
-  // Generate the server implementation
-  indent(f_service_processor) << "public function process($input, $output) {" << endl;
-  indent_up();
-
-  f_service_processor << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl
-                      << indent() << "$mtype = 0;" << endl << endl;
-
-  if (binary_inline_) {
-    t_field ffname(g_type_string, "fname");
-    t_field fmtype(g_type_i8, "mtype");
-    t_field fseqid(g_type_i32, "rseqid");
-    generate_deserialize_field(f_service_processor, &ffname, "", true);
-    generate_deserialize_field(f_service_processor, &fmtype, "", true);
-    generate_deserialize_field(f_service_processor, &fseqid, "", true);
-  } else {
-    f_service_processor << indent() << "$input->readMessageBegin($fname, $mtype, $rseqid);" << endl;
-  }
-
-  // HOT: check for method implementation
-  f_service_processor << indent() << "$methodname = 'process_'.$fname;" << endl << indent()
-                      << "if (!method_exists($this, $methodname)) {" << endl;
-  if (binary_inline_) {
-    f_service_processor << indent() << "  throw new \\Exception('Function '.$fname.' not implemented.');"
-                        << endl;
-  } else {
-    f_service_processor << indent() << "  $input->skip("
-                        << "TType::STRUCT);" << endl << indent() << "  $input->readMessageEnd();" << endl
-                        << indent() << "  $x = new "
-                        << "TApplicationException('Function '.$fname.' not implemented.', "
-                        << "TApplicationException::UNKNOWN_METHOD);" << endl << indent()
-                        << "  $output->writeMessageBegin($fname, "
-                        << "TMessageType::EXCEPTION, $rseqid);" << endl << indent()
-                        << "  $x->write($output);" << endl << indent() << "  $output->writeMessageEnd();"
-                        << endl << indent() << "  $output->getTransport()->flush();" << endl << indent()
-                        << "  return;" << endl;
-  }
-  f_service_processor << indent() << "}" << endl << indent()
-                      << "$this->$methodname($rseqid, $input, $output);" << endl << indent()
-                      << "return true;" << endl;
-  indent_down();
-  f_service_processor << indent() << "}" << endl << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(f_service_processor, tservice, *f_iter);
-  }
-
-  indent_down();
-  f_service_processor << "}" << endl;
-
-  if (psr4_) {
-    f_service_processor.close();
-  }
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_php_generator::generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction) {
-  // Open function
-  indent(out) << "protected function process_" << tfunction->get_name()
-                     << "($seqid, $input, $output) {" << endl;
-  indent_up();
-
-  string argsname = php_namespace(tservice->get_program()) + service_name_ + "_"
-                    + tfunction->get_name() + "_args";
-  string resultname = php_namespace(tservice->get_program()) + service_name_ + "_"
-                      + tfunction->get_name() + "_result";
-
-  out << indent() << "$args = new " << argsname << "();" << endl << indent()
-             << "$args->read($input);" << endl;
-  if (!binary_inline_) {
-    out << indent() << "$input->readMessageEnd();" << endl;
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    out << indent() << "$result = new " << resultname << "();" << endl;
-  }
-
-  // Try block for a function with exceptions
-  if (xceptions.size() > 0) {
-    out << indent() << "try {" << endl;
-    indent_up();
-  }
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    out << "$result->success = ";
-  }
-  out << "$this->handler_->" << tfunction->get_name() << "(";
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      out << ", ";
-    }
-    out << "$args->" << (*f_iter)->get_name();
-  }
-  out << ");" << endl;
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    indent_down();
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      out << indent() << "} catch ("
-                 << php_namespace(get_true_type((*x_iter)->get_type())->get_program())
-                 << (*x_iter)->get_type()->get_name() << " $" << (*x_iter)->get_name() << ") {"
-                 << endl;
-      if (!tfunction->is_oneway()) {
-        indent_up();
-        out << indent() << "$result->" << (*x_iter)->get_name() << " = $"
-                   << (*x_iter)->get_name() << ";" << endl;
-        indent_down();
-        out << indent();
-      }
-    }
-    out << "}" << endl;
-  }
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    out << indent() << "return;" << endl;
-    indent_down();
-    out << indent() << "}" << endl;
-    return;
-  }
-
-  out << indent() << "$bin_accel = ($output instanceof "
-             << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');"
-             << endl;
-
-  out << indent() << "if ($bin_accel)" << endl;
-  scope_up(out);
-
-  out << indent() << "thrift_protocol_write_binary($output, '" << tfunction->get_name()
-             << "', "
-             << "TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());" << endl;
-
-  scope_down(out);
-  out << indent() << "else" << endl;
-  scope_up(out);
-
-  // Serialize the request header
-  if (binary_inline_) {
-    out << indent() << "$buff = pack('N', (0x80010000 | "
-        << "TMessageType::REPLY)); " << endl << indent() << "$buff .= pack('N', strlen('"
-        << tfunction->get_name() << "'));" << endl << indent() << "$buff .= '"
-        << tfunction->get_name() << "';" << endl << indent() << "$buff .= pack('N', $seqid);"
-        << endl << indent() << "$result->write($buff);" << endl << indent()
-        << "$output->write($buff);" << endl << indent() << "$output->flush();" << endl;
-  } else {
-    out << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', "
-        << "TMessageType::REPLY, $seqid);" << endl << indent() << "$result->write($output);"
-        << endl << indent() << "$output->writeMessageEnd();" << endl << indent()
-        << "$output->getTransport()->flush();" << endl;
-  }
-
-  scope_down(out);
-
-  // Close function
-  indent_down();
-  out << indent() << "}" << endl;
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_php_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  std::ofstream& f_struct_definition = f_service_;
-  if (!psr4_) {
-    f_struct_definition << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
-  }
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    string name = ts->get_name();
-    ts->set_name(service_name_ + "_" + name);
-
-    if (psr4_) {
-      string f_struct_definition_name = package_dir_ + service_name_ + "_" + name + ".php";
-      f_struct_definition.open(f_struct_definition_name.c_str());
-      generate_service_header(tservice, f_struct_definition);
-    }
-
-    generate_php_struct_definition(f_struct_definition, ts);
-    if (psr4_) {
-      f_struct_definition.close();
-    }
-
-    generate_php_function_helpers(tservice, *f_iter);
-    ts->set_name(name);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_php_generator::generate_php_function_helpers(t_service* tservice, t_function* tfunction) {
-  if (!tfunction->is_oneway()) {
-    t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
-    t_field success(tfunction->get_returntype(), "success", 0);
-    if (!tfunction->get_returntype()->is_void()) {
-      result.append(&success);
-    }
-
-    t_struct* xs = tfunction->get_xceptions();
-    const vector<t_field*>& fields = xs->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      result.append(*f_iter);
-    }
-
-    std::ofstream& f_struct_helper = f_service_;
-    if (psr4_) {
-      string f_struct_helper_name = package_dir_ + result.get_name() + ".php";
-      f_struct_helper.open(f_struct_helper_name.c_str());
-      generate_service_header(tservice, f_struct_helper);
-    }
-    generate_php_struct_definition(f_struct_helper, &result, false, true);
-    if (psr4_) {
-      f_struct_helper.close();
-    }
-  }
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_php_generator::generate_service_interface(t_service* tservice) {
-  std::ofstream& f_service_interface = f_service_;
-  if (psr4_) {
-    string f_service_interface_name = package_dir_ + service_name_ + "If.php";
-    f_service_interface.open(f_service_interface_name.c_str());
-    generate_service_header(tservice, f_service_interface);
-  }
-
-  string extends = "";
-  string extends_if = "";
-  if (tservice->get_extends() != NULL) {
-    extends = " extends " + php_namespace(tservice->get_extends()->get_program())
-              + tservice->get_extends()->get_name();
-    extends_if = " extends " + php_namespace(tservice->get_extends()->get_program())
-                 + tservice->get_extends()->get_name() + "If";
-  }
-  generate_php_doc(f_service_interface, tservice);
-  f_service_interface << "interface " << php_namespace_declaration(tservice) << "If" << extends_if << " {"
-             << endl;
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_php_doc(f_service_interface, *f_iter);
-    indent(f_service_interface) << "public function " << function_signature(*f_iter) << ";" << endl;
-  }
-  indent_down();
-  f_service_interface << "}" << endl << endl;
-
-  // Close service interface file
-  f_service_interface << endl;
-  if (psr4_) {
-    f_service_interface.close();
-  }
-}
-
-/**
- * Generates a REST interface
- */
-void t_php_generator::generate_service_rest(t_service* tservice) {
-  std::ofstream& f_service_rest = f_service_;
-  if (psr4_) {
-    string f_service_rest_name = package_dir_ + service_name_ + "Rest.php";
-    f_service_rest.open(f_service_rest_name.c_str());
-    generate_service_header(tservice, f_service_rest);
-  }
-
-  string extends = "";
-  string extends_if = "";
-  if (tservice->get_extends() != NULL) {
-    extends = " extends " + php_namespace(tservice->get_extends()->get_program())
-              + tservice->get_extends()->get_name();
-    extends_if = " extends " + php_namespace(tservice->get_extends()->get_program())
-                 + tservice->get_extends()->get_name() + "Rest";
-  }
-  f_service_rest << "class " << service_name_ << "Rest" << extends_if << " {" << endl;
-  indent_up();
-
-  if (extends.empty()) {
-    f_service_rest << indent() << "protected $impl_;" << endl << endl;
-  }
-
-  f_service_rest << indent() << "public function __construct($impl) {" << endl << indent()
-             << "  $this->impl_ = $impl;" << endl << indent() << "}" << endl << endl;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    indent(f_service_rest) << "public function " << (*f_iter)->get_name() << "($request) {" << endl;
-    indent_up();
-    const vector<t_field*>& args = (*f_iter)->get_arglist()->get_members();
-    vector<t_field*>::const_iterator a_iter;
-    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
-      t_type* atype = get_true_type((*a_iter)->get_type());
-      string cast = type_to_cast(atype);
-      string req = "$request['" + (*a_iter)->get_name() + "']";
-      if (atype->is_bool()) {
-        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = " << cast << "(!empty(" << req
-                   << ") && (" << req << " !== 'false'));" << endl;
-      } else {
-        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = isset(" << req << ") ? "
-                   << cast << req << " : null;" << endl;
-      }
-      if (atype->is_string() && ((t_base_type*)atype)->is_string_list()) {
-        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = explode(',', $"
-                       << (*a_iter)->get_name() << ");" << endl;
-      } else if (atype->is_map() || atype->is_list()) {
-        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = json_decode($"
-                       << (*a_iter)->get_name() << ", true);" << endl;
-      } else if (atype->is_set()) {
-        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = array_fill_keys(json_decode($"
-                       << (*a_iter)->get_name() << ", true), 1);" << endl;
-      } else if (atype->is_struct() || atype->is_xception()) {
-        f_service_rest << indent() << "if ($" << (*a_iter)->get_name() << " !== null) {" << endl
-                       << indent() << "  $" << (*a_iter)->get_name() << " = new "
-                       << php_namespace(atype->get_program()) << atype->get_name() << "(json_decode($"
-                       << (*a_iter)->get_name() << ", true));" << endl << indent() << "}" << endl;
-      }
-    }
-    f_service_rest << indent() << "return $this->impl_->" << (*f_iter)->get_name() << "("
-               << argument_list((*f_iter)->get_arglist(), false) << ");" << endl;
-    indent_down();
-    indent(f_service_rest) << "}" << endl << endl;
-  }
-  indent_down();
-  f_service_rest << "}" << endl << endl;
-
-  // Close service rest file
-  f_service_rest << endl;
-  if (psr4_) {
-    f_service_rest.close();
-  }
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_php_generator::generate_service_client(t_service* tservice) {
-  std::ofstream& f_service_client = f_service_;
-  if (psr4_) {
-    string f_service_client_name = package_dir_ + service_name_ + "Client.php";
-    f_service_client.open(f_service_client_name.c_str());
-    generate_service_header(tservice, f_service_client);
-  }
-
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = tservice->get_extends()->get_name();
-    extends_client = " extends " + php_namespace(tservice->get_extends()->get_program()) + extends
-                     + "Client";
-  }
-
-  f_service_client << "class " << php_namespace_declaration(tservice) << "Client" << extends_client
-             << " implements " << php_namespace(tservice->get_program()) << service_name_ << "If {"
-             << endl;
-  indent_up();
-
-  // Private members
-  if (extends.empty()) {
-    f_service_client << indent() << "protected $input_ = null;" << endl << indent()
-               << "protected $output_ = null;" << endl << endl;
-    f_service_client << indent() << "protected $seqid_ = 0;" << endl << endl;
-  }
-
-  // Constructor function
-  f_service_client << indent() << "public function __construct($input, $output=null) {" << endl;
-  if (!extends.empty()) {
-    f_service_client << indent() << "  parent::__construct($input, $output);" << endl;
-  } else {
-    f_service_client << indent() << "  $this->input_ = $input;" << endl << indent()
-               << "  $this->output_ = $output ? $output : $input;" << endl;
-  }
-  f_service_client << indent() << "}" << endl << endl;
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    indent(f_service_client) << "public function " << function_signature(*f_iter) << endl;
-    scope_up(f_service_client);
-    indent(f_service_client) << "$this->send_" << funname << "(";
-
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_client << ", ";
-      }
-      f_service_client << "$" << (*fld_iter)->get_name();
-    }
-    f_service_client << ");" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_service_client << indent();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_client << "return ";
-      }
-      f_service_client << "$this->recv_" << funname << "();" << endl;
-    }
-    scope_down(f_service_client);
-    f_service_client << endl;
-
-    indent(f_service_client) << "public function send_" << function_signature(*f_iter) << endl;
-    scope_up(f_service_client);
-
-    std::string argsname = php_namespace(tservice->get_program()) + service_name_ + "_"
-                           + (*f_iter)->get_name() + "_args";
-
-    f_service_client << indent() << "$args = new " << argsname << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_client << indent() << "$args->" << (*fld_iter)->get_name() << " = $"
-                 << (*fld_iter)->get_name() << ";" << endl;
-    }
-
-    f_service_client << indent() << "$bin_accel = ($this->output_ instanceof "
-               << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');"
-               << endl;
-
-    f_service_client << indent() << "if ($bin_accel)" << endl;
-    scope_up(f_service_client);
-
-    string messageType = (*f_iter)->is_oneway() ? "TMessageType::ONEWAY" : "TMessageType::CALL";
-
-    f_service_client << indent() << "thrift_protocol_write_binary($this->output_, '"
-               << (*f_iter)->get_name() << "', " << messageType
-               << ", $args, $this->seqid_, $this->output_->isStrictWrite());" << endl;
-
-    scope_down(f_service_client);
-    f_service_client << indent() << "else" << endl;
-    scope_up(f_service_client);
-
-    // Serialize the request header
-    if (binary_inline_) {
-      f_service_client << indent() << "$buff = pack('N', (0x80010000 | " << messageType << "));" << endl
-                       << indent() << "$buff .= pack('N', strlen('" << funname << "'));" << endl
-                       << indent() << "$buff .= '" << funname << "';" << endl << indent()
-                       << "$buff .= pack('N', $this->seqid_);" << endl;
-    } else {
-      f_service_client << indent() << "$this->output_->writeMessageBegin('" << (*f_iter)->get_name()
-                       << "', " << messageType << ", $this->seqid_);" << endl;
-    }
-
-    // Write to the stream
-    if (binary_inline_) {
-      f_service_client << indent() << "$args->write($buff);" << endl << indent()
-                       << "$this->output_->write($buff);" << endl << indent()
-                       << "$this->output_->flush();" << endl;
-    } else {
-      f_service_client << indent() << "$args->write($this->output_);" << endl << indent()
-                       << "$this->output_->writeMessageEnd();" << endl << indent()
-                       << "$this->output_->getTransport()->flush();" << endl;
-    }
-
-    scope_down(f_service_client);
-
-    scope_down(f_service_client);
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = php_namespace(tservice->get_program()) + service_name_ + "_"
-                               + (*f_iter)->get_name() + "_result";
-      t_struct noargs(program_);
-
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs);
-      // Open function
-      f_service_client << endl << indent() << "public function " << function_signature(&recv_function)
-                       << endl;
-      scope_up(f_service_client);
-
-      f_service_client << indent() << "$bin_accel = ($this->input_ instanceof "
-                       << "TBinaryProtocolAccelerated)"
-                       << " && function_exists('thrift_protocol_read_binary');" << endl;
-
-      f_service_client << indent()
-                       << "if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '"
-                       << resultname << "', $this->input_->isStrictRead());" << endl;
-      f_service_client << indent() << "else" << endl;
-      scope_up(f_service_client);
-
-      f_service_client << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl
-                 << indent() << "$mtype = 0;" << endl << endl;
-
-      if (binary_inline_) {
-        t_field ffname(g_type_string, "fname");
-        t_field fseqid(g_type_i32, "rseqid");
-        f_service_client << indent() << "$ver = unpack('N', $this->input_->readAll(4));" << endl
-                         << indent() << "$ver = $ver[1];" << endl << indent() << "$mtype = $ver & 0xff;"
-                         << endl << indent() << "$ver = $ver & 0xffff0000;" << endl << indent()
-                         << "if ($ver != 0x80010000) throw new "
-                         << "TProtocolException('Bad version identifier: '.$ver, "
-                         << "TProtocolException::BAD_VERSION);" << endl;
-        generate_deserialize_field(f_service_client, &ffname, "", true);
-        generate_deserialize_field(f_service_client, &fseqid, "", true);
-      } else {
-        f_service_client << indent() << "$this->input_->readMessageBegin($fname, $mtype, $rseqid);"
-                         << endl << indent() << "if ($mtype == "
-                         << "TMessageType::EXCEPTION) {" << endl << indent() << "  $x = new "
-                         << "TApplicationException();" << endl << indent() << "  $x->read($this->input_);"
-                         << endl << indent() << "  $this->input_->readMessageEnd();" << endl << indent()
-                         << "  throw $x;" << endl << indent() << "}" << endl;
-      }
-
-      f_service_client << indent() << "$result = new " << resultname << "();" << endl << indent()
-                       << "$result->read($this->input_);" << endl;
-
-      if (!binary_inline_) {
-        f_service_client << indent() << "$this->input_->readMessageEnd();" << endl;
-      }
-
-      scope_down(f_service_client);
-
-      // Careful, only return result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_client << indent() << "if ($result->success !== null) {" << endl << indent()
-                   << "  return $result->success;" << endl << indent() << "}" << endl;
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_client << indent() << "if ($result->" << (*x_iter)->get_name() << " !== null) {" << endl
-                         << indent() << "  throw $result->" << (*x_iter)->get_name() << ";" << endl
-                         << indent() << "}" << endl;
-      }
-
-      // Careful, only return _result if not a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_client) << "return;" << endl;
-      } else {
-        f_service_client << indent() << "throw new \\Exception(\"" << (*f_iter)->get_name()
-                         << " failed: unknown result\");" << endl;
-      }
-
-      // Close function
-      scope_down(f_service_client);
-      f_service_client << endl;
-    }
-  }
-
-  indent_down();
-  f_service_client << "}" << endl << endl;
-
-  // Close service client file
-  f_service_client << endl;
-  if (psr4_) {
-    f_service_client.close();
-  }
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_php_generator::generate_deserialize_field(ofstream& out,
-                                                 t_field* tfield,
-                                                 string prefix,
-                                                 bool inclass) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else {
-
-    if (type->is_container()) {
-      generate_deserialize_container(out, type, name);
-    } else if (type->is_base_type() || type->is_enum()) {
-
-      if (binary_inline_) {
-        std::string itrans = (inclass ? "$this->input_" : "$input");
-
-        if (type->is_base_type()) {
-          t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-          switch (tbase) {
-          case t_base_type::TYPE_VOID:
-            throw "compiler error: cannot serialize void field in a struct: " + name;
-            break;
-          case t_base_type::TYPE_STRING:
-            out << indent() << "$len = unpack('N', " << itrans << "->readAll(4));" << endl
-                << indent() << "$len = $len[1];" << endl << indent() << "if ($len > 0x7fffffff) {"
-                << endl << indent() << "  $len = 0 - (($len - 1) ^ 0xffffffff);" << endl << indent()
-                << "}" << endl << indent() << "$" << name << " = " << itrans << "->readAll($len);"
-                << endl;
-            break;
-          case t_base_type::TYPE_BOOL:
-            out << indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));"
-                << endl << indent() << "$" << name << " = (bool)$" << name << "[1];" << endl;
-            break;
-          case t_base_type::TYPE_I8:
-            out << indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));"
-                << endl << indent() << "$" << name << " = $" << name << "[1];" << endl;
-            break;
-          case t_base_type::TYPE_I16:
-            out << indent() << "$val = unpack('n', " << itrans << "->readAll(2));" << endl
-                << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fff) {"
-                << endl << indent() << "  $val = 0 - (($val - 1) ^ 0xffff);" << endl << indent()
-                << "}" << endl << indent() << "$" << name << " = $val;" << endl;
-            break;
-          case t_base_type::TYPE_I32:
-            out << indent() << "$val = unpack('N', " << itrans << "->readAll(4));" << endl
-                << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fffffff) {"
-                << endl << indent() << "  $val = 0 - (($val - 1) ^ 0xffffffff);" << endl << indent()
-                << "}" << endl << indent() << "$" << name << " = $val;" << endl;
-            break;
-          case t_base_type::TYPE_I64:
-            out << indent() << "$arr = unpack('N2', " << itrans << "->readAll(8));" << endl
-                << indent() << "if ($arr[1] & 0x80000000) {" << endl << indent()
-                << "  $arr[1] = $arr[1] ^ 0xFFFFFFFF;" << endl << indent()
-                << "  $arr[2] = $arr[2] ^ 0xFFFFFFFF;" << endl << indent() << "  $" << name
-                << " = 0 - $arr[1]*4294967296 - $arr[2] - 1;" << endl << indent() << "} else {"
-                << endl << indent() << "  $" << name << " = $arr[1]*4294967296 + $arr[2];" << endl
-                << indent() << "}" << endl;
-            break;
-          case t_base_type::TYPE_DOUBLE:
-            out << indent() << "$arr = unpack('d', strrev(" << itrans << "->readAll(8)));" << endl
-                << indent() << "$" << name << " = $arr[1];" << endl;
-            break;
-          default:
-            throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase)
-                + tfield->get_name();
-          }
-        } else if (type->is_enum()) {
-          out << indent() << "$val = unpack('N', " << itrans << "->readAll(4));" << endl << indent()
-              << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fffffff) {" << endl
-              << indent() << "  $val = 0 - (($val - 1) ^ 0xffffffff);" << endl << indent() << "}"
-              << endl << indent() << "$" << name << " = $val;" << endl;
-        }
-      } else {
-
-        indent(out) << "$xfer += $input->";
-
-        if (type->is_base_type()) {
-          t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-          switch (tbase) {
-          case t_base_type::TYPE_VOID:
-            throw "compiler error: cannot serialize void field in a struct: " + name;
-            break;
-          case t_base_type::TYPE_STRING:
-            out << "readString($" << name << ");";
-            break;
-          case t_base_type::TYPE_BOOL:
-            out << "readBool($" << name << ");";
-            break;
-          case t_base_type::TYPE_I8:
-            out << "readByte($" << name << ");";
-            break;
-          case t_base_type::TYPE_I16:
-            out << "readI16($" << name << ");";
-            break;
-          case t_base_type::TYPE_I32:
-            out << "readI32($" << name << ");";
-            break;
-          case t_base_type::TYPE_I64:
-            out << "readI64($" << name << ");";
-            break;
-          case t_base_type::TYPE_DOUBLE:
-            out << "readDouble($" << name << ");";
-            break;
-          default:
-            throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
-          }
-        } else if (type->is_enum()) {
-          out << "readI32($" << name << ");";
-        }
-        out << endl;
-      }
-    } else {
-      printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-             tfield->get_name().c_str(),
-             type->get_name().c_str());
-    }
-  }
-}
-
-/**
- * Generates an unserializer for a variable. This makes two key assumptions,
- * first that there is a const char* variable named data that points to the
- * buffer for deserialization, and that there is a variable protocol which
- * is a reference to a TProtocol serialization object.
- */
-void t_php_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  out << indent() << "$" << prefix << " = new " << php_namespace(tstruct->get_program())
-      << tstruct->get_name() << "();" << endl << indent() << "$xfer += $" << prefix
-      << "->read($input);" << endl;
-}
-
-void t_php_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
-
-  t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  out << indent() << "$" << prefix << " = array();" << endl << indent() << "$" << size << " = 0;"
-      << endl;
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    out << indent() << "$" << ktype << " = 0;" << endl << indent() << "$" << vtype << " = 0;"
-        << endl;
-    if (binary_inline_) {
-      generate_deserialize_field(out, &fktype);
-      generate_deserialize_field(out, &fvtype);
-      generate_deserialize_field(out, &fsize);
-    } else {
-      out << indent() << "$xfer += $input->readMapBegin("
-          << "$" << ktype << ", $" << vtype << ", $" << size << ");" << endl;
-    }
-  } else if (ttype->is_set()) {
-    if (binary_inline_) {
-      generate_deserialize_field(out, &fetype);
-      generate_deserialize_field(out, &fsize);
-    } else {
-      out << indent() << "$" << etype << " = 0;" << endl << indent()
-          << "$xfer += $input->readSetBegin("
-          << "$" << etype << ", $" << size << ");" << endl;
-    }
-  } else if (ttype->is_list()) {
-    if (binary_inline_) {
-      generate_deserialize_field(out, &fetype);
-      generate_deserialize_field(out, &fsize);
-    } else {
-      out << indent() << "$" << etype << " = 0;" << endl << indent()
-          << "$xfer += $input->readListBegin("
-          << "$" << etype << ", $" << size << ");" << endl;
-    }
-  }
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) << "for ($" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")" << endl;
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  scope_down(out);
-
-  if (!binary_inline_) {
-    // Read container end
-    if (ttype->is_map()) {
-      indent(out) << "$xfer += $input->readMapEnd();" << endl;
-    } else if (ttype->is_set()) {
-      indent(out) << "$xfer += $input->readSetEnd();" << endl;
-    } else if (ttype->is_list()) {
-      indent(out) << "$xfer += $input->readListEnd();" << endl;
-    }
-  }
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_php_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("key");
-  string val = tmp("val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  indent(out) << declare_field(&fkey, true, true) << endl;
-  indent(out) << declare_field(&fval, true, true) << endl;
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << "$" << prefix << "[$" << key << "] = $" << val << ";" << endl;
-}
-
-void t_php_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  indent(out) << "$" << elem << " = null;" << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << "if (is_scalar($" << elem << ")) {" << endl;
-  indent(out) << "  $" << prefix << "[$" << elem << "] = true;" << endl;
-  indent(out) << "} else {" << endl;
-  indent(out) << "  $" << prefix << " []= $" << elem << ";" << endl;
-  indent(out) << "}" << endl;
-}
-
-void t_php_generator::generate_deserialize_list_element(ofstream& out,
-                                                        t_list* tlist,
-                                                        string prefix) {
-  string elem = tmp("elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  indent(out) << "$" << elem << " = null;" << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << "$" << prefix << " []= $" << elem << ";" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_php_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + tfield->get_name());
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = prefix + tfield->get_name();
-
-    if (binary_inline_) {
-      if (type->is_base_type()) {
-        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-        switch (tbase) {
-        case t_base_type::TYPE_VOID:
-          throw "compiler error: cannot serialize void field in a struct: " + name;
-          break;
-        case t_base_type::TYPE_STRING:
-          out << indent() << "$output .= pack('N', strlen($" << name << "));" << endl << indent()
-              << "$output .= $" << name << ";" << endl;
-          break;
-        case t_base_type::TYPE_BOOL:
-          out << indent() << "$output .= pack('c', $" << name << " ? 1 : 0);" << endl;
-          break;
-        case t_base_type::TYPE_I8:
-          out << indent() << "$output .= pack('c', $" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_I16:
-          out << indent() << "$output .= pack('n', $" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_I32:
-          out << indent() << "$output .= pack('N', $" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_I64:
-          out << indent() << "$output .= pack('N2', $" << name << " >> 32, $" << name
-              << " & 0xFFFFFFFF);" << endl;
-          break;
-        case t_base_type::TYPE_DOUBLE:
-          out << indent() << "$output .= strrev(pack('d', $" << name << "));" << endl;
-          break;
-        default:
-          throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
-        }
-      } else if (type->is_enum()) {
-        out << indent() << "$output .= pack('N', $" << name << ");" << endl;
-      }
-    } else {
-
-      indent(out) << "$xfer += $output->";
-
-      if (type->is_base_type()) {
-        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-        switch (tbase) {
-        case t_base_type::TYPE_VOID:
-          throw "compiler error: cannot serialize void field in a struct: " + name;
-          break;
-        case t_base_type::TYPE_STRING:
-          out << "writeString($" << name << ");";
-          break;
-        case t_base_type::TYPE_BOOL:
-          out << "writeBool($" << name << ");";
-          break;
-        case t_base_type::TYPE_I8:
-          out << "writeByte($" << name << ");";
-          break;
-        case t_base_type::TYPE_I16:
-          out << "writeI16($" << name << ");";
-          break;
-        case t_base_type::TYPE_I32:
-          out << "writeI32($" << name << ");";
-          break;
-        case t_base_type::TYPE_I64:
-          out << "writeI64($" << name << ");";
-          break;
-        case t_base_type::TYPE_DOUBLE:
-          out << "writeDouble($" << name << ");";
-          break;
-        default:
-          throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
-        }
-      } else if (type->is_enum()) {
-        out << "writeI32($" << name << ");";
-      }
-      out << endl;
-    }
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_php_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << "$xfer += $" << prefix << "->write($output);" << endl;
-}
-
-/**
- * Writes out a container
- */
-void t_php_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    if (binary_inline_) {
-      out << indent() << "$output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_key_type())
-          << ");" << endl << indent() << "$output .= pack('c', "
-          << type_to_enum(((t_map*)ttype)->get_val_type()) << ");" << endl << indent()
-          << "$output .= strrev(pack('l', count($" << prefix << ")));" << endl;
-    } else {
-      indent(out) << "$output->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type())
-                  << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
-                  << "count($" << prefix << "));" << endl;
-    }
-  } else if (ttype->is_set()) {
-    if (binary_inline_) {
-      out << indent() << "$output .= pack('c', " << type_to_enum(((t_set*)ttype)->get_elem_type())
-          << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));"
-          << endl;
-
-    } else {
-      indent(out) << "$output->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type())
-                  << ", "
-                  << "count($" << prefix << "));" << endl;
-    }
-  } else if (ttype->is_list()) {
-    if (binary_inline_) {
-      out << indent() << "$output .= pack('c', " << type_to_enum(((t_list*)ttype)->get_elem_type())
-          << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));"
-          << endl;
-
-    } else {
-      indent(out) << "$output->writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
-                  << ", "
-                  << "count($" << prefix << "));" << endl;
-    }
-  }
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    string kiter = tmp("kiter");
-    string viter = tmp("viter");
-    indent(out) << "foreach ($" << prefix << " as "
-                << "$" << kiter << " => $" << viter << ")" << endl;
-    scope_up(out);
-    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
-    scope_down(out);
-  } else if (ttype->is_set()) {
-    string iter = tmp("iter");
-    string iter_val = tmp("iter");
-    indent(out) << "foreach ($" << prefix << " as $" << iter << " => $" << iter_val << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (is_scalar($" << iter_val << ")) {" << endl;
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-    indent(out) << "} else {" << endl;
-    generate_serialize_set_element(out, (t_set*)ttype, iter_val);
-    indent(out) << "}" << endl;
-    scope_down(out);
-  } else if (ttype->is_list()) {
-    string iter = tmp("iter");
-    indent(out) << "foreach ($" << prefix << " as $" << iter << ")" << endl;
-    scope_up(out);
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-    scope_down(out);
-  }
-
-  scope_down(out);
-
-  if (!binary_inline_) {
-    if (ttype->is_map()) {
-      indent(out) << "$output->writeMapEnd();" << endl;
-    } else if (ttype->is_set()) {
-      indent(out) << "$output->writeSetEnd();" << endl;
-    } else if (ttype->is_list()) {
-      indent(out) << "$output->writeListEnd();" << endl;
-    }
-  }
-
-  scope_down(out);
-}
-
-/**
- * Serializes the members of a map.
- *
- */
-void t_php_generator::generate_serialize_map_element(ofstream& out,
-                                                     t_map* tmap,
-                                                     string kiter,
-                                                     string viter) {
-  t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(out, &kfield, "");
-
-  t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(out, &vfield, "");
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_php_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_php_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Emits a PHPDoc comment for the given contents
- */
-void t_php_generator::generate_php_docstring_comment(ofstream& out, string contents) {
-  generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
-}
-
-/**
- * Emits a PHPDoc comment if the provided object has a doc in Thrift
- */
-void t_php_generator::generate_php_doc(ofstream& out, t_doc* tdoc) {
-  if (tdoc->has_doc()) {
-    generate_php_docstring_comment(out, tdoc->get_doc());
-  }
-}
-
-/**
- * Emits a PHPDoc comment for a field
- */
-void t_php_generator::generate_php_doc(ofstream& out, t_field* field) {
-  stringstream ss;
-
-  // prepend free-style doc if available
-  if (field->has_doc()) {
-    ss << field->get_doc() << endl;
-  }
-
-  // append @var tag
-  t_type* type = get_true_type(field->get_type());
-  ss << "@var " << type_to_phpdoc(type) << endl;
-
-  generate_php_docstring_comment(out, ss.str());
-}
-
-/**
- * Emits a PHPDoc comment for a function
- */
-void t_php_generator::generate_php_doc(ofstream& out, t_function* function) {
-  stringstream ss;
-  if (function->has_doc()) {
-    ss << function->get_doc() << endl;
-  }
-
-  // generate parameter types doc
-  const vector<t_field*>& args = function->get_arglist()->get_members();
-  vector<t_field*>::const_iterator a_iter;
-  for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
-    t_field* arg = *a_iter;
-    ss << "@param " << type_to_phpdoc(arg->get_type()) << " $" << arg->get_name();
-    if (arg->has_doc()) {
-      ss << " " << arg->get_doc();
-    }
-    ss << endl;
-  }
-
-  // generate return type doc
-  t_type* ret_type = function->get_returntype();
-  if (!ret_type->is_void() || ret_type->has_doc()) {
-    ss << "@return " << type_to_phpdoc(ret_type);
-    if (ret_type->has_doc()) {
-      ss << " " << ret_type->get_doc();
-    }
-    ss << endl;
-  }
-
-  // generate exceptions doc
-  const vector<t_field*>& excs = function->get_xceptions()->get_members();
-  vector<t_field*>::const_iterator e_iter;
-  for (e_iter = excs.begin(); e_iter != excs.end(); ++e_iter) {
-    t_field* exc = *e_iter;
-    ss << "@throws " << type_to_phpdoc(exc->get_type());
-    if (exc->has_doc()) {
-      ss << " " << exc->get_doc();
-    }
-    ss << endl;
-  }
-
-  generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n");
-}
-
-/**
- * Declares a field, which may include initialization as necessary.
- *
- * @param ttype The type
- */
-string t_php_generator::declare_field(t_field* tfield, bool init, bool obj) {
-  string result = "$" + tfield->get_name();
-  if (init) {
-    t_type* type = get_true_type(tfield->get_type());
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        break;
-      case t_base_type::TYPE_STRING:
-        result += " = ''";
-        break;
-      case t_base_type::TYPE_BOOL:
-        result += " = false";
-        break;
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        result += " = 0.0";
-        break;
-      default:
-        throw "compiler error:

<TRUNCATED>

[45/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_d_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_d_generator.cc b/compiler/cpp/src/generate/t_d_generator.cc
deleted file mode 100644
index 1e0af7d..0000000
--- a/compiler/cpp/src/generate/t_d_generator.cc
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <cassert>
-
-#include <fstream>
-#include <iostream>
-#include <set>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <sys/stat.h>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::set;
-using std::string;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * D code generator.
- *
- * generate_*() functions are called by the base class to emit code for the
- * given entity, print_*() functions write a piece of code to the passed
- * stream, and render_*() return a string containing the D representation of
- * the passed entity.
- */
-class t_d_generator : public t_oop_generator {
-public:
-  t_d_generator(t_program* program,
-                const std::map<string, string>& parsed_options,
-                const string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option d:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-d";
-  }
-
-protected:
-  virtual void init_generator() {
-    // Make output directory
-    MKDIR(get_out_dir().c_str());
-
-    string dir = program_->get_namespace("d");
-    string subdir = get_out_dir();
-    string::size_type loc;
-    while ((loc = dir.find(".")) != string::npos) {
-      subdir = subdir + "/" + dir.substr(0, loc);
-      MKDIR(subdir.c_str());
-      dir = dir.substr(loc + 1);
-    }
-    if (!dir.empty()) {
-      subdir = subdir + "/" + dir;
-      MKDIR(subdir.c_str());
-    }
-
-    package_dir_ = subdir + "/";
-
-    // Make output file
-    string f_types_name = package_dir_ + program_name_ + "_types.d";
-    f_types_.open(f_types_name.c_str());
-
-    // Print header
-    f_types_ << autogen_comment() << "module " << render_package(*program_) << program_name_
-             << "_types;" << endl << endl;
-
-    print_default_imports(f_types_);
-
-    // Include type modules from other imported programs.
-    const vector<t_program*>& includes = program_->get_includes();
-    for (size_t i = 0; i < includes.size(); ++i) {
-      f_types_ << "import " << render_package(*(includes[i])) << includes[i]->get_name()
-               << "_types;" << endl;
-    }
-    if (!includes.empty())
-      f_types_ << endl;
-  }
-
-  virtual void close_generator() {
-    // Close output file
-    f_types_.close();
-  }
-
-  virtual void generate_consts(std::vector<t_const*> consts) {
-    if (!consts.empty()) {
-      string f_consts_name = package_dir_ + program_name_ + "_constants.d";
-      ofstream f_consts;
-      f_consts.open(f_consts_name.c_str());
-
-      f_consts << autogen_comment() << "module " << render_package(*program_) << program_name_
-               << "_constants;" << endl << endl;
-
-      print_default_imports(f_consts);
-
-      f_consts << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl
-               << endl;
-
-      vector<t_const*>::iterator c_iter;
-      for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-        string name = (*c_iter)->get_name();
-        t_type* type = (*c_iter)->get_type();
-        indent(f_consts) << "immutable(" << render_type_name(type) << ") " << name << ";" << endl;
-      }
-
-      f_consts << endl << "static this() {" << endl;
-      indent_up();
-
-      bool first = true;
-      for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-        if (first) {
-          first = false;
-        } else {
-          f_consts << endl;
-        }
-        t_type* type = (*c_iter)->get_type();
-        indent(f_consts) << (*c_iter)->get_name() << " = ";
-        if (!is_immutable_type(type)) {
-          f_consts << "cast(immutable(" << render_type_name(type) << ")) ";
-        }
-        f_consts << render_const_value(type, (*c_iter)->get_value()) << ";" << endl;
-      }
-      indent_down();
-      indent(f_consts) << "}" << endl;
-    }
-  }
-
-  virtual void generate_typedef(t_typedef* ttypedef) {
-    f_types_ << indent() << "alias " << render_type_name(ttypedef->get_type()) << " "
-             << ttypedef->get_symbolic() << ";" << endl << endl;
-  }
-
-  virtual void generate_enum(t_enum* tenum) {
-    vector<t_enum_value*> constants = tenum->get_constants();
-
-    string enum_name = tenum->get_name();
-    f_types_ << indent() << "enum " << enum_name << " {" << endl;
-
-    indent_up();
-
-    vector<t_enum_value*>::const_iterator c_iter;
-    bool first = true;
-    for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_types_ << "," << endl;
-      }
-      indent(f_types_) << (*c_iter)->get_name();
-      f_types_ << " = " << (*c_iter)->get_value();
-    }
-
-    f_types_ << endl;
-    indent_down();
-    indent(f_types_) << "}" << endl;
-
-    f_types_ << endl;
-  }
-
-  virtual void generate_struct(t_struct* tstruct) {
-    print_struct_definition(f_types_, tstruct, false);
-  }
-
-  virtual void generate_xception(t_struct* txception) {
-    print_struct_definition(f_types_, txception, true);
-  }
-
-  virtual void generate_service(t_service* tservice) {
-    string svc_name = tservice->get_name();
-
-    // Service implementation file includes
-    string f_servicename = package_dir_ + svc_name + ".d";
-    std::ofstream f_service;
-    f_service.open(f_servicename.c_str());
-    f_service << autogen_comment() << "module " << render_package(*program_) << svc_name << ";"
-              << endl << endl;
-
-    print_default_imports(f_service);
-
-    f_service << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl;
-
-    t_service* extends_service = tservice->get_extends();
-    if (extends_service != NULL) {
-      f_service << "import " << render_package(*(extends_service->get_program()))
-                << extends_service->get_name() << ";" << endl;
-    }
-
-    f_service << endl;
-
-    string extends = "";
-    if (tservice->get_extends() != NULL) {
-      extends = " : " + render_type_name(tservice->get_extends());
-    }
-
-    f_service << indent() << "interface " << svc_name << extends << " {" << endl;
-    indent_up();
-
-    // Collect all the exception types service methods can throw so we can
-    // emit the necessary aliases later.
-    set<t_type*> exception_types;
-
-    // Print the method signatures.
-    vector<t_function*> functions = tservice->get_functions();
-    vector<t_function*>::iterator fn_iter;
-    for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
-      f_service << indent();
-      print_function_signature(f_service, *fn_iter);
-      f_service << ";" << endl;
-
-      const vector<t_field*>& exceptions = (*fn_iter)->get_xceptions()->get_members();
-      vector<t_field*>::const_iterator ex_iter;
-      for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) {
-        exception_types.insert((*ex_iter)->get_type());
-      }
-    }
-
-    // Alias the exception types into the current scope.
-    if (!exception_types.empty())
-      f_service << endl;
-    set<t_type*>::const_iterator et_iter;
-    for (et_iter = exception_types.begin(); et_iter != exception_types.end(); ++et_iter) {
-      indent(f_service) << "alias " << render_package(*(*et_iter)->get_program())
-                        << (*et_iter)->get_program()->get_name() << "_types"
-                        << "." << (*et_iter)->get_name() << " " << (*et_iter)->get_name() << ";"
-                        << endl;
-    }
-
-    // Write the method metadata.
-    ostringstream meta;
-    indent_up();
-    bool first = true;
-    for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
-      if ((*fn_iter)->get_arglist()->get_members().empty()
-          && (*fn_iter)->get_xceptions()->get_members().empty() && !(*fn_iter)->is_oneway()) {
-        continue;
-      }
-
-      if (first) {
-        first = false;
-      } else {
-        meta << ",";
-      }
-
-      meta << endl << indent() << "TMethodMeta(`" << (*fn_iter)->get_name() << "`, " << endl;
-      indent_up();
-      indent(meta) << "[";
-
-      bool first = true;
-      const vector<t_field*>& params = (*fn_iter)->get_arglist()->get_members();
-      vector<t_field*>::const_iterator p_iter;
-      for (p_iter = params.begin(); p_iter != params.end(); ++p_iter) {
-        if (first) {
-          first = false;
-        } else {
-          meta << ", ";
-        }
-
-        meta << "TParamMeta(`" << (*p_iter)->get_name() << "`, " << (*p_iter)->get_key();
-
-        t_const_value* cv = (*p_iter)->get_value();
-        if (cv != NULL) {
-          meta << ", q{" << render_const_value((*p_iter)->get_type(), cv) << "}";
-        }
-        meta << ")";
-      }
-
-      meta << "]";
-
-      if (!(*fn_iter)->get_xceptions()->get_members().empty() || (*fn_iter)->is_oneway()) {
-        meta << "," << endl << indent() << "[";
-
-        bool first = true;
-        const vector<t_field*>& exceptions = (*fn_iter)->get_xceptions()->get_members();
-        vector<t_field*>::const_iterator ex_iter;
-        for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) {
-          if (first) {
-            first = false;
-          } else {
-            meta << ", ";
-          }
-
-          meta << "TExceptionMeta(`" << (*ex_iter)->get_name() << "`, " << (*ex_iter)->get_key()
-               << ", `" << (*ex_iter)->get_type()->get_name() << "`)";
-        }
-
-        meta << "]";
-      }
-
-      if ((*fn_iter)->is_oneway()) {
-        meta << "," << endl << indent() << "TMethodType.ONEWAY";
-      }
-
-      indent_down();
-      meta << endl << indent() << ")";
-    }
-    indent_down();
-
-    string meta_str(meta.str());
-    if (!meta_str.empty()) {
-      f_service << endl << indent() << "enum methodMeta = [" << meta_str << endl << indent() << "];"
-                << endl;
-    }
-
-    indent_down();
-    indent(f_service) << "}" << endl;
-
-    // Server skeleton generation.
-    string f_skeletonname = package_dir_ + svc_name + "_server.skeleton.d";
-    std::ofstream f_skeleton;
-    f_skeleton.open(f_skeletonname.c_str());
-    print_server_skeleton(f_skeleton, tservice);
-    f_skeleton.close();
-  }
-
-private:
-  /**
-   * Writes a server skeleton for the passed service to out.
-   */
-  void print_server_skeleton(ostream& out, t_service* tservice) {
-    string svc_name = tservice->get_name();
-
-    out << "/*" << endl
-        << " * This auto-generated skeleton file illustrates how to build a server. If you" << endl
-        << " * intend to customize it, you should edit a copy with another file name to " << endl
-        << " * avoid overwriting it when running the generator again." << endl << " */" << endl
-        << "module " << render_package(*tservice->get_program()) << svc_name << "_server;" << endl
-        << endl << "import std.stdio;" << endl << "import thrift.codegen.processor;" << endl
-        << "import thrift.protocol.binary;" << endl << "import thrift.server.simple;" << endl
-        << "import thrift.server.transport.socket;" << endl << "import thrift.transport.buffered;"
-        << endl << "import thrift.util.hashset;" << endl << endl << "import "
-        << render_package(*tservice->get_program()) << svc_name << ";" << endl << "import "
-        << render_package(*get_program()) << program_name_ << "_types;" << endl << endl << endl
-        << "class " << svc_name << "Handler : " << svc_name << " {" << endl;
-
-    indent_up();
-    out << indent() << "this() {" << endl << indent() << "  // Your initialization goes here."
-        << endl << indent() << "}" << endl << endl;
-
-    vector<t_function*> functions = tservice->get_functions();
-    vector<t_function*>::iterator f_iter;
-    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-      out << indent();
-      print_function_signature(out, *f_iter);
-      out << " {" << endl;
-
-      indent_up();
-
-      out << indent() << "// Your implementation goes here." << endl << indent() << "writeln(\""
-          << (*f_iter)->get_name() << " called\");" << endl;
-
-      t_base_type* rt = (t_base_type*)(*f_iter)->get_returntype();
-      if (rt->get_base() != t_base_type::TYPE_VOID) {
-        indent(out) << "return typeof(return).init;" << endl;
-      }
-
-      indent_down();
-
-      out << indent() << "}" << endl << endl;
-    }
-
-    indent_down();
-    out << "}" << endl << endl;
-
-    out << indent() << "void main() {" << endl;
-    indent_up();
-    out << indent() << "auto protocolFactory = new TBinaryProtocolFactory!();" << endl << indent()
-        << "auto processor = new TServiceProcessor!" << svc_name << "(new " << svc_name
-        << "Handler);" << endl << indent() << "auto serverTransport = new TServerSocket(9090);"
-        << endl << indent() << "auto transportFactory = new TBufferedTransportFactory;" << endl
-        << indent() << "auto server = new TSimpleServer(" << endl << indent()
-        << "  processor, serverTransport, transportFactory, protocolFactory);" << endl << indent()
-        << "server.serve();" << endl;
-    indent_down();
-    out << "}" << endl;
-  }
-
-  /**
-   * Writes the definition of a struct or an exception type to out.
-   */
-  void print_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) {
-    const vector<t_field*>& members = tstruct->get_members();
-
-    if (is_exception) {
-      indent(out) << "class " << tstruct->get_name() << " : TException {" << endl;
-    } else {
-      indent(out) << "struct " << tstruct->get_name() << " {" << endl;
-    }
-    indent_up();
-
-    // Declare all fields.
-    vector<t_field*>::const_iterator m_iter;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      indent(out) << render_type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name() << ";"
-                  << endl;
-    }
-
-    if (!members.empty())
-      indent(out) << endl;
-    indent(out) << "mixin TStructHelpers!(";
-
-    if (!members.empty()) {
-      // If there are any fields, construct the TFieldMeta array to pass to
-      // TStructHelpers. We can't just pass an empty array if not because []
-      // doesn't pass the TFieldMeta[] constraint.
-      out << "[";
-      indent_up();
-
-      bool first = true;
-      vector<t_field*>::const_iterator m_iter;
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if (first) {
-          first = false;
-        } else {
-          out << ",";
-        }
-        out << endl;
-
-        indent(out) << "TFieldMeta(`" << (*m_iter)->get_name() << "`, " << (*m_iter)->get_key();
-
-        t_const_value* cv = (*m_iter)->get_value();
-        t_field::e_req req = (*m_iter)->get_req();
-        out << ", " << render_req(req);
-        if (cv != NULL) {
-          out << ", q{" << render_const_value((*m_iter)->get_type(), cv) << "}";
-        }
-        out << ")";
-      }
-
-      indent_down();
-      out << endl << indent() << "]";
-    }
-
-    out << ");" << endl;
-
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-
-  /**
-   * Prints the D function signature (including return type) for the given
-   * method.
-   */
-  void print_function_signature(ostream& out, t_function* fn) {
-    out << render_type_name(fn->get_returntype()) << " " << fn->get_name() << "(";
-
-    const vector<t_field*>& fields = fn->get_arglist()->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        out << ", ";
-      }
-      out << render_type_name((*f_iter)->get_type(), true) << " " << (*f_iter)->get_name();
-    }
-
-    out << ")";
-  }
-
-  /**
-   * Returns the D representation of value. The result is guaranteed to be a
-   * single expression; for complex types, immediately called delegate
-   * literals are used to achieve this.
-   */
-  string render_const_value(t_type* type, t_const_value* value) {
-    // Resolve any typedefs.
-    type = get_true_type(type);
-
-    ostringstream out;
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_STRING:
-        out << '"' << get_escaped_string(value) << '"';
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << ((value->get_integer() > 0) ? "true" : "false");
-        break;
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-        out << "cast(" << render_type_name(type) << ")" << value->get_integer();
-        break;
-      case t_base_type::TYPE_I32:
-        out << value->get_integer();
-        break;
-      case t_base_type::TYPE_I64:
-        out << value->get_integer() << "L";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        if (value->get_type() == t_const_value::CV_INTEGER) {
-          out << value->get_integer();
-        } else {
-          out << value->get_double();
-        }
-        break;
-      default:
-        throw "Compiler error: No const of base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "cast(" << render_type_name(type) << ")" << value->get_integer();
-    } else {
-      out << "{" << endl;
-      indent_up();
-
-      indent(out) << render_type_name(type) << " v;" << endl;
-      if (type->is_struct() || type->is_xception()) {
-        indent(out) << "v = " << (type->is_xception() ? "new " : "") << render_type_name(type)
-                    << "();" << endl;
-
-        const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-        vector<t_field*>::const_iterator f_iter;
-        const map<t_const_value*, t_const_value*>& val = value->get_map();
-        map<t_const_value*, t_const_value*>::const_iterator v_iter;
-        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-          t_type* field_type = NULL;
-          for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-            if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-              field_type = (*f_iter)->get_type();
-            }
-          }
-          if (field_type == NULL) {
-            throw "Type error: " + type->get_name() + " has no field "
-                + v_iter->first->get_string();
-          }
-          string val = render_const_value(field_type, v_iter->second);
-          indent(out) << "v.set!`" << v_iter->first->get_string() << "`(" << val << ");" << endl;
-        }
-      } else if (type->is_map()) {
-        t_type* ktype = ((t_map*)type)->get_key_type();
-        t_type* vtype = ((t_map*)type)->get_val_type();
-        const map<t_const_value*, t_const_value*>& val = value->get_map();
-        map<t_const_value*, t_const_value*>::const_iterator v_iter;
-        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-          string key = render_const_value(ktype, v_iter->first);
-          string val = render_const_value(vtype, v_iter->second);
-          indent(out) << "v[";
-          if (!is_immutable_type(ktype)) {
-            out << "cast(immutable(" << render_type_name(ktype) << "))";
-          }
-          out << key << "] = " << val << ";" << endl;
-        }
-      } else if (type->is_list()) {
-        t_type* etype = ((t_list*)type)->get_elem_type();
-        const vector<t_const_value*>& val = value->get_list();
-        vector<t_const_value*>::const_iterator v_iter;
-        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-          string val = render_const_value(etype, *v_iter);
-          indent(out) << "v ~= " << val << ";" << endl;
-        }
-      } else if (type->is_set()) {
-        t_type* etype = ((t_set*)type)->get_elem_type();
-        const vector<t_const_value*>& val = value->get_list();
-        vector<t_const_value*>::const_iterator v_iter;
-        for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-          string val = render_const_value(etype, *v_iter);
-          indent(out) << "v ~= " << val << ";" << endl;
-        }
-      } else {
-        throw "Compiler error: Invalid type in render_const_value: " + type->get_name();
-      }
-      indent(out) << "return v;" << endl;
-
-      indent_down();
-      indent(out) << "}()";
-    }
-
-    return out.str();
-  }
-
-  /**
-   * Returns the D package to which modules for program are written (with a
-   * trailing dot, if not empty).
-   */
-  string render_package(const t_program& program) const {
-    string package = program.get_namespace("d");
-    if (package.size() == 0)
-      return "";
-    return package + ".";
-  }
-
-  /**
-   * Returns the name of the D repesentation of ttype.
-   *
-   * If isArg is true, a const reference to the type will be returned for
-   * structs.
-   */
-  string render_type_name(const t_type* ttype, bool isArg = false) const {
-    if (ttype->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        return "void";
-      case t_base_type::TYPE_STRING:
-        return "string";
-      case t_base_type::TYPE_BOOL:
-        return "bool";
-      case t_base_type::TYPE_I8:
-        return "byte";
-      case t_base_type::TYPE_I16:
-        return "short";
-      case t_base_type::TYPE_I32:
-        return "int";
-      case t_base_type::TYPE_I64:
-        return "long";
-      case t_base_type::TYPE_DOUBLE:
-        return "double";
-      default:
-        throw "Compiler error: No D type name for base type " + t_base_type::t_base_name(tbase);
-      }
-    }
-
-    if (ttype->is_container()) {
-      t_container* tcontainer = (t_container*)ttype;
-      if (tcontainer->has_cpp_name()) {
-        return tcontainer->get_cpp_name();
-      } else if (ttype->is_map()) {
-        t_map* tmap = (t_map*)ttype;
-        t_type* ktype = tmap->get_key_type();
-
-        string name = render_type_name(tmap->get_val_type()) + "[";
-        if (!is_immutable_type(ktype)) {
-          name += "immutable(";
-        }
-        name += render_type_name(ktype);
-        if (!is_immutable_type(ktype)) {
-          name += ")";
-        }
-        name += "]";
-        return name;
-      } else if (ttype->is_set()) {
-        t_set* tset = (t_set*)ttype;
-        return "HashSet!(" + render_type_name(tset->get_elem_type()) + ")";
-      } else if (ttype->is_list()) {
-        t_list* tlist = (t_list*)ttype;
-        return render_type_name(tlist->get_elem_type()) + "[]";
-      }
-    }
-
-    if (ttype->is_struct() && isArg) {
-      return "ref const(" + ttype->get_name() + ")";
-    } else {
-      return ttype->get_name();
-    }
-  }
-
-  /**
-   * Returns the D TReq enum member corresponding to req.
-   */
-  string render_req(t_field::e_req req) const {
-    switch (req) {
-    case t_field::T_OPT_IN_REQ_OUT:
-      return "TReq.OPT_IN_REQ_OUT";
-    case t_field::T_OPTIONAL:
-      return "TReq.OPTIONAL";
-    case t_field::T_REQUIRED:
-      return "TReq.REQUIRED";
-    default: {
-      std::stringstream ss;
-      ss << "Compiler error: Invalid requirement level " << req;
-      throw ss.str();
-    }
-    }
-  }
-
-  /**
-   * Writes the default list of imports (which are written to every generated
-   * module) to f.
-   */
-  void print_default_imports(ostream& out) {
-    indent(out) << "import thrift.base;" << endl << "import thrift.codegen.base;" << endl
-                << "import thrift.util.hashset;" << endl << endl;
-  }
-
-  /**
-   * Returns whether type is �intrinsically immutable�, in the sense that
-   * a value of that type is implicitly castable to immutable(type), and it is
-   * allowed for AA keys without an immutable() qualifier.
-   */
-  bool is_immutable_type(t_type* type) const {
-    t_type* ttype = get_true_type(type);
-    return ttype->is_base_type() || ttype->is_enum();
-  }
-
-  /*
-   * File streams, stored here to avoid passing them as parameters to every
-   * function.
-   */
-  ofstream f_types_;
-  ofstream f_header_;
-
-  string package_dir_;
-};
-
-THRIFT_REGISTER_GENERATOR(d, "D", "")


[35/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_javame_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_javame_generator.cc b/compiler/cpp/src/generate/t_javame_generator.cc
deleted file mode 100644
index e9a206b..0000000
--- a/compiler/cpp/src/generate/t_javame_generator.cc
+++ /dev/null
@@ -1,3295 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <sstream>
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <cctype>
-
-#include <sys/stat.h>
-#include <stdexcept>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Java code generator.
- *
- */
-class t_javame_generator : public t_oop_generator {
-public:
-  t_javame_generator(t_program* program,
-                     const std::map<std::string, std::string>& parsed_options,
-                     const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)parsed_options;
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option javame:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-javame";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_union(t_struct* tunion);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(std::ofstream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool in_static,
-                         bool defval = false);
-  std::string render_const_value(std::ofstream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_java_struct(t_struct* tstruct, bool is_exception);
-
-  void generate_java_struct_definition(std::ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_xception = false,
-                                       bool in_class = false,
-                                       bool is_result = false);
-  void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_java_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
-  std::string get_java_type_string(t_type* type);
-  void generate_reflection_setters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_reflection_getters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
-
-  void generate_function_helpers(t_function* tfunction);
-  std::string get_cap_name(std::string name);
-  std::string generate_isset_check(t_field* field);
-  std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
-  std::string isset_field_id(t_field* field);
-
-  void generate_primitive_service_interface(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  void generate_java_union(t_struct* tstruct);
-  void generate_union_constructor(ofstream& out, t_struct* tstruct);
-  void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
-  void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
-  void generate_check_type(ofstream& out, t_struct* tstruct);
-  void generate_read_value(ofstream& out, t_struct* tstruct);
-  void generate_write_value(ofstream& out, t_struct* tstruct);
-  void generate_get_field_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_field_name(ofstream& out, t_struct* tstruct);
-
-  void generate_union_comparisons(ofstream& out, t_struct* tstruct);
-  void generate_union_hashcode(ofstream& out, t_struct* tstruct);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_java_doc(std::ofstream& out, t_field* field);
-
-  void generate_java_doc(std::ofstream& out, t_doc* tdoc);
-
-  void generate_java_doc(std::ofstream& out, t_function* tdoc);
-
-  void generate_java_docstring_comment(std::ofstream& out, string contents);
-
-  void generate_deep_copy_container(std::ofstream& out,
-                                    std::string source_name_p1,
-                                    std::string source_name_p2,
-                                    std::string result_name,
-                                    t_type* type);
-  void generate_deep_copy_non_container(std::ofstream& out,
-                                        std::string source_name,
-                                        std::string dest_name,
-                                        t_type* type);
-
-  bool has_bit_vector(t_struct* tstruct);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string java_package();
-  std::string java_type_imports();
-  std::string java_thrift_imports();
-  std::string type_name(t_type* ttype,
-                        bool in_container = false,
-                        bool in_init = false,
-                        bool skip_generic = false);
-  std::string base_type_name(t_base_type* tbase, bool in_container = false);
-  std::string declare_field(t_field* tfield, bool init = false);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct, bool include_types = true);
-  std::string type_to_enum(t_type* ttype);
-  std::string get_enum_class_name(t_type* type);
-  void generate_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_field_descs(ofstream& out, t_struct* tstruct);
-  std::string box_type(t_type* type, string value);
-
-  bool type_can_be_null(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()
-           || ttype->is_enum();
-  }
-
-  std::string constant_name(std::string name);
-
-private:
-  /**
-   * File streams
-   */
-
-  std::string package_name_;
-  std::ofstream f_service_;
-  std::string package_dir_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_javame_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  package_name_ = program_->get_namespace("java");
-
-  string dir = package_name_;
-  string subdir = get_out_dir();
-  string::size_type loc;
-  while ((loc = dir.find(".")) != string::npos) {
-    subdir = subdir + "/" + dir.substr(0, loc);
-    MKDIR(subdir.c_str());
-    dir = dir.substr(loc + 1);
-  }
-  if (dir.size() > 0) {
-    subdir = subdir + "/" + dir;
-    MKDIR(subdir.c_str());
-  }
-
-  package_dir_ = subdir;
-}
-
-/**
- * Packages the generated file
- *
- * @return String of the package, i.e. "package org.apache.thriftdemo;"
- */
-string t_javame_generator::java_package() {
-  if (!package_name_.empty()) {
-    return string("package ") + package_name_ + ";\n\n";
-  }
-  return "";
-}
-
-/**
- * Prints standard java imports
- *
- * @return List of imports for Java types that are used in here
- */
-string t_javame_generator::java_type_imports() {
-  return string() + "import java.util.Hashtable;\n" + "import java.util.Vector;\n"
-         + "import java.util.Enumeration;\n\n";
-}
-
-/**
- * Prints standard java imports
- *
- * @return List of imports necessary for thrift
- */
-string t_javame_generator::java_thrift_imports() {
-  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
-         + "import org.apache.thrift.transport.*;\n" + "import org.apache.thrift.protocol.*;\n\n";
-}
-
-/**
- * Nothing in Java
- */
-void t_javame_generator::close_generator() {
-}
-
-/**
- * Generates a typedef. This is not done in Java, since it does
- * not support arbitrary name replacements, and it'd be a wacky waste
- * of overhead to make wrapper classes.
- *
- * @param ttypedef The type definition
- */
-void t_javame_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Enums are a class with a set of static constants.
- *
- * @param tenum The enumeration
- */
-void t_javame_generator::generate_enum(t_enum* tenum) {
-  // Make output file
-  string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".java";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
-
-  // Comment and package it
-  f_enum << autogen_comment() << java_package();
-
-  generate_java_doc(f_enum, tenum);
-  indent(f_enum) << "public class " << tenum->get_name() << " implements org.apache.thrift.TEnum ";
-  scope_up(f_enum);
-  f_enum << endl;
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    generate_java_doc(f_enum, *c_iter);
-    indent(f_enum) << "public static final " << tenum->get_name() << " " << (*c_iter)->get_name()
-                   << " = new " << tenum->get_name() << "(" << value << ");" << endl;
-  }
-  f_enum << endl;
-
-  // Field for thriftCode
-  indent(f_enum) << "private final int value;" << endl << endl;
-
-  indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl;
-  indent(f_enum) << "  this.value = value;" << endl;
-  indent(f_enum) << "}" << endl << endl;
-
-  indent(f_enum) << "/**" << endl;
-  indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL."
-                 << endl;
-  indent(f_enum) << " */" << endl;
-  indent(f_enum) << "public int getValue() {" << endl;
-  indent(f_enum) << "  return value;" << endl;
-  indent(f_enum) << "}" << endl << endl;
-
-  indent(f_enum) << "/**" << endl;
-  indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL."
-                 << endl;
-  indent(f_enum) << " * @return null if the value is not found." << endl;
-  indent(f_enum) << " */" << endl;
-  indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl;
-
-  indent_up();
-
-  indent(f_enum) << "switch (value) {" << endl;
-  indent_up();
-
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << "case " << value << ":" << endl;
-    indent(f_enum) << "  return " << (*c_iter)->get_name() << ";" << endl;
-  }
-
-  indent(f_enum) << "default:" << endl;
-  indent(f_enum) << "  return null;" << endl;
-
-  indent_down();
-
-  indent(f_enum) << "}" << endl;
-
-  indent_down();
-
-  indent(f_enum) << "}" << endl;
-
-  scope_down(f_enum);
-
-  f_enum.close();
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_javame_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-
-  string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.java";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  // Print header
-  f_consts << autogen_comment() << java_package() << java_type_imports();
-
-  f_consts << "public class " << program_name_ << "Constants {" << endl << endl;
-  indent_up();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    print_const_value(f_consts,
-                      (*c_iter)->get_name(),
-                      (*c_iter)->get_type(),
-                      (*c_iter)->get_value(),
-                      false);
-  }
-  indent_down();
-  indent(f_consts) << "}" << endl;
-  f_consts.close();
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-void t_javame_generator::print_const_value(std::ofstream& out,
-                                           string name,
-                                           t_type* type,
-                                           t_const_value* value,
-                                           bool in_static,
-                                           bool defval) {
-  type = get_true_type(type);
-
-  indent(out);
-  if (!defval) {
-    out << (in_static ? "" : "public static final ") << type_name(type) << " ";
-  }
-  if (type->is_base_type()) {
-    string v2 = render_const_value(out, name, type, value);
-    out << name << " = " << v2 << ";" << endl << endl;
-  } else if (type->is_enum()) {
-    out << name << " = " << render_const_value(out, name, type, value) << ";" << endl << endl;
-  } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    out << name << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "static {" << endl;
-      indent_up();
-    }
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(out, name, field_type, v_iter->second);
-      indent(out) << name << ".";
-      std::string cap_name = get_cap_name(v_iter->first->get_string());
-      out << "set" << cap_name << "(" << val << ");" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_map()) {
-    out << name << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "static {" << endl;
-      indent_up();
-    }
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, name, ktype, v_iter->first);
-      string val = render_const_value(out, name, vtype, v_iter->second);
-      indent(out) << name << ".put(" << box_type(ktype, key) << ", " << box_type(vtype, val) << ");"
-                  << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_list() || type->is_set()) {
-    out << name << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "static {" << endl;
-      indent_up();
-    }
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      if (type->is_list()) {
-        indent(out) << name << ".addElement(" << box_type(etype, val) << ");" << endl;
-      } else {
-        indent(out) << name << ".put(" << box_type(etype, val) << ", " << box_type(etype, val)
-                    << ");" << endl;
-      }
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else {
-    throw "compiler error: no const of type " + type->get_name();
-  }
-}
-
-string t_javame_generator::render_const_value(ofstream& out,
-                                              string name,
-                                              t_type* type,
-                                              t_const_value* value) {
-  (void)name;
-  type = get_true_type(type);
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-      render << "(byte)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I16:
-      render << "(short)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << value->get_integer() << "L";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << "(double)" << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << type_name(type, false, false) << "." << value->get_identifier();
-  } else {
-    string t = tmp("tmp");
-    print_const_value(out, t, type, value, true);
-    render << t;
-  }
-
-  return render.str();
-}
-
-string t_javame_generator::box_type(t_type* type, string value) {
-  if (type->is_base_type()) {
-    switch (((t_base_type*)type)->get_base()) {
-    case t_base_type::TYPE_BOOL:
-      return "new Boolean(" + value + ")";
-    case t_base_type::TYPE_I8:
-      return "new Byte(" + value + ")";
-    case t_base_type::TYPE_I16:
-      return "new Short(" + value + ")";
-    case t_base_type::TYPE_I32:
-      return "new Integer(" + value + ")";
-    case t_base_type::TYPE_I64:
-      return "new Long(" + value + ")";
-    case t_base_type::TYPE_DOUBLE:
-      return "new Double(" + value + ")";
-    default:
-      break;
-    }
-  }
-  return value;
-}
-
-/**
- * Generates a struct definition for a thrift data type. This will be a TBase
- * implementor.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_struct(t_struct* tstruct) {
-  if (tstruct->is_union()) {
-    generate_java_union(tstruct);
-  } else {
-    generate_java_struct(tstruct, false);
-  }
-}
-
-/**
- * Exceptions are structs, but they inherit from Exception
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_xception(t_struct* txception) {
-  generate_java_struct(txception, true);
-}
-
-/**
- * Java struct definition.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_struct(t_struct* tstruct, bool is_exception) {
-  // Make output file
-  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
-
-  generate_java_struct_definition(f_struct, tstruct, is_exception);
-  f_struct.close();
-}
-
-/**
- * Java union definition.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_union(t_struct* tstruct) {
-  // Make output file
-  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
-
-  generate_java_doc(f_struct, tstruct);
-
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-
-  indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
-                   << " extends TUnion ";
-
-  scope_up(f_struct);
-
-  generate_struct_desc(f_struct, tstruct);
-  generate_field_descs(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_constructor(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_abstract_methods(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_getters_and_setters(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_comparisons(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_hashcode(f_struct, tstruct);
-
-  f_struct << endl;
-
-  scope_down(f_struct);
-
-  f_struct.close();
-}
-
-void t_javame_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public " << type_name(tstruct) << "() {" << endl;
-  indent(out) << "  super();" << endl;
-  indent(out) << "}" << endl << endl;
-
-  indent(out) << "public " << type_name(tstruct) << "(_Fields setField, Object value) {" << endl;
-  indent(out) << "  super(setField, value);" << endl;
-  indent(out) << "}" << endl << endl;
-
-  indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {"
-              << endl;
-  indent(out) << "  super(other);" << endl;
-  indent(out) << "}" << endl;
-
-  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
-  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
-  indent(out) << "}" << endl << endl;
-
-  // generate "constructors" for each field
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "("
-                << type_name((*m_iter)->get_type()) << " value) {" << endl;
-    indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl;
-    indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl;
-    indent(out) << "  return x;" << endl;
-    indent(out) << "}" << endl << endl;
-  }
-}
-
-void t_javame_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  bool first = true;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (first) {
-      first = false;
-    } else {
-      out << endl;
-    }
-
-    t_field* field = (*m_iter);
-
-    generate_java_doc(out, field);
-    indent(out) << "public " << type_name(field->get_type()) << " get"
-                << get_cap_name(field->get_name()) << "() {" << endl;
-    indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
-                << endl;
-    indent(out) << "    return (" << type_name(field->get_type(), true) << ")getFieldValue();"
-                << endl;
-    indent(out) << "  } else {" << endl;
-    indent(out) << "    throw new RuntimeException(\"Cannot get field '" << field->get_name()
-                << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
-                << endl;
-    indent(out) << "  }" << endl;
-    indent(out) << "}" << endl;
-
-    out << endl;
-
-    generate_java_doc(out, field);
-    indent(out) << "public void set" << get_cap_name(field->get_name()) << "("
-                << type_name(field->get_type()) << " value) {" << endl;
-    if (type_can_be_null(field->get_type())) {
-      indent(out) << "  if (value == null) throw new NullPointerException();" << endl;
-    }
-    indent(out) << "  setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl;
-    indent(out) << "  value_ = value;" << endl;
-    indent(out) << "}" << endl;
-  }
-}
-
-void t_javame_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
-  generate_check_type(out, tstruct);
-  out << endl;
-  generate_read_value(out, tstruct);
-  out << endl;
-  generate_write_value(out, tstruct);
-  out << endl;
-  generate_get_field_desc(out, tstruct);
-  out << endl;
-  generate_get_struct_desc(out, tstruct);
-  out << endl;
-}
-
-void t_javame_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
-  indent(out)
-      << "protected void checkType(_Fields setField, Object value) throws ClassCastException {"
-      << endl;
-  indent_up();
-
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent(out) << "  if (value instanceof " << type_name(field->get_type(), true, false, true)
-                << ") {" << endl;
-    indent(out) << "    break;" << endl;
-    indent(out) << "  }" << endl;
-    indent(out) << "  throw new ClassCastException(\"Was expecting value of type "
-                << type_name(field->get_type(), true, false) << " for field '" << field->get_name()
-                << "', but got \" + value.getClass().getSimpleName());" << endl;
-    // do the real check here
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_javame_generator::generate_read_value(ofstream& out, t_struct* tstruct) {
-  indent(out) << "protected Object readValue(TProtocol iprot, TField field) throws TException {"
-              << endl;
-
-  indent_up();
-
-  indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl;
-  indent(out) << "if (setField != null) {" << endl;
-  indent_up();
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {"
-                << endl;
-    indent_up();
-    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";"
-                << endl;
-    generate_deserialize_field(out, field, "");
-    indent(out) << "return " << field->get_name() << ";" << endl;
-    indent_down();
-    indent(out) << "} else {" << endl;
-    indent(out) << "  TProtocolUtil.skip(iprot, field.type);" << endl;
-    indent(out) << "  return null;" << endl;
-    indent(out) << "}" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalStateException(\"setField wasn't null, but didn't match any "
-                 "of the case statements!\");" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "} else {" << endl;
-  indent_up();
-  indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl;
-  indent(out) << "return null;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_javame_generator::generate_write_value(ofstream& out, t_struct* tstruct) {
-  indent(out) << "protected void writeValue(TProtocol oprot) throws TException {" << endl;
-
-  indent_up();
-
-  indent(out) << "switch (setField_) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = ("
-                << type_name(field->get_type(), true, false) << ")value_;" << endl;
-    generate_serialize_field(out, field, "");
-    indent(out) << "return;" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + "
-                 "setField_);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-
-  indent(out) << "}" << endl;
-}
-
-void t_javame_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
-  indent(out) << "protected TField getFieldDesc(_Fields setField) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent(out) << "  return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl;
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_javame_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "protected TStruct getStructDesc() {" << endl;
-  indent(out) << "  return STRUCT_DESC;" << endl;
-  indent(out) << "}" << endl;
-}
-
-void t_javame_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
-  // equality
-  indent(out) << "public boolean equals(Object other) {" << endl;
-  indent(out) << "  if (other instanceof " << tstruct->get_name() << ") {" << endl;
-  indent(out) << "    return equals((" << tstruct->get_name() << ")other);" << endl;
-  indent(out) << "  } else {" << endl;
-  indent(out) << "    return false;" << endl;
-  indent(out) << "  }" << endl;
-  indent(out) << "}" << endl;
-
-  out << endl;
-
-  indent(out) << "public boolean equals(" << tstruct->get_name() << " other) {" << endl;
-  indent(out) << "  return other != null && getSetField() == other.getSetField() && "
-                 "getFieldValue().equals(other.getFieldValue());" << endl;
-  indent(out) << "}" << endl;
-  out << endl;
-
-  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
-  indent(out) << "  int lastComparison = TBaseHelper.compareTo(getSetField(), other.getSetField());"
-              << endl;
-  indent(out) << "  if (lastComparison == 0) {" << endl;
-  indent(out) << "    return TBaseHelper.compareTo(getFieldValue(), other.getFieldValue());"
-              << endl;
-  indent(out) << "  }" << endl;
-  indent(out) << "  return lastComparison;" << endl;
-  indent(out) << "}" << endl;
-  out << endl;
-}
-
-void t_javame_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "/**" << endl;
-  indent(out)
-      << " * If you'd like this to perform more respectably, use the hashcode generator option."
-      << endl;
-  indent(out) << " */" << endl;
-  indent(out) << "public int hashCode() {" << endl;
-  indent(out) << "  return 0;" << endl;
-  indent(out) << "}" << endl;
-}
-
-/**
- * Java struct definition. This has various parameters, as it could be
- * generated standalone or inside another class as a helper. If it
- * is a helper than it is a static class.
- *
- * @param tstruct      The struct definition
- * @param is_exception Is this an exception?
- * @param in_class     If inside a class, needs to be static class
- * @param is_result    If this is a result it needs a different writer
- */
-void t_javame_generator::generate_java_struct_definition(ofstream& out,
-                                                         t_struct* tstruct,
-                                                         bool is_exception,
-                                                         bool in_class,
-                                                         bool is_result) {
-  generate_java_doc(out, tstruct);
-
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-
-  indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class "
-              << tstruct->get_name() << " ";
-
-  if (is_exception) {
-    out << "extends Exception ";
-  }
-  out << "implements TBase ";
-
-  scope_up(out);
-
-  generate_struct_desc(out, tstruct);
-
-  // Members are public for -java, private for -javabean
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  out << endl;
-
-  generate_field_descs(out, tstruct);
-
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "private ";
-    out << declare_field(*m_iter, false) << endl;
-  }
-
-  // isset data
-  if (members.size() > 0) {
-    out << endl;
-
-    indent(out) << "// isset id assignments" << endl;
-
-    int i = 0;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (!type_can_be_null((*m_iter)->get_type())) {
-        indent(out) << "private static final int " << isset_field_id(*m_iter) << " = " << i << ";"
-                    << endl;
-        i++;
-      }
-    }
-
-    if (i > 0) {
-      indent(out) << "private boolean[] __isset_vector = new boolean[" << i << "];" << endl;
-    }
-
-    out << endl;
-  }
-
-  bool all_optional_members = true;
-
-  // Default constructor
-  indent(out) << "public " << tstruct->get_name() << "() {" << endl;
-  indent_up();
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL) {
-      print_const_value(out,
-                        "this." + (*m_iter)->get_name(),
-                        t,
-                        (*m_iter)->get_value(),
-                        true,
-                        true);
-    }
-    if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-      all_optional_members = false;
-    }
-  }
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  if (!members.empty() && !all_optional_members) {
-    // Full constructor for all fields
-    indent(out) << "public " << tstruct->get_name() << "(" << endl;
-    indent_up();
-    bool first = true;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-        if (!first) {
-          out << "," << endl;
-        }
-        first = false;
-        indent(out) << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
-      }
-    }
-    out << ")" << endl;
-    indent_down();
-    indent(out) << "{" << endl;
-    indent_up();
-    indent(out) << "this();" << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-        indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";"
-                    << endl;
-        generate_isset_set(out, (*m_iter));
-      }
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-
-  // copy constructor
-  indent(out) << "/**" << endl;
-  indent(out) << " * Performs a deep copy on <i>other</i>." << endl;
-  indent(out) << " */" << endl;
-  indent(out) << "public " << tstruct->get_name() << "(" << tstruct->get_name() << " other) {"
-              << endl;
-  indent_up();
-
-  if (has_bit_vector(tstruct)) {
-    indent(out) << "System.arraycopy(other.__isset_vector, 0, __isset_vector, 0, "
-                   "other.__isset_vector.length);" << endl;
-  }
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-    std::string field_name = field->get_name();
-    t_type* type = field->get_type();
-    bool can_be_null = type_can_be_null(type);
-
-    if (can_be_null) {
-      indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl;
-      indent_up();
-    }
-
-    if (type->is_container()) {
-      generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type);
-      indent(out) << "this." << field_name << " = __this__" << field_name << ";" << endl;
-    } else {
-      indent(out) << "this." << field_name << " = ";
-      generate_deep_copy_non_container(out, "other." + field_name, field_name, type);
-      out << ";" << endl;
-    }
-
-    if (can_be_null) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  // clone method, so that you can deep copy an object when you don't know its class.
-  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
-  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
-  indent(out) << "}" << endl << endl;
-
-  generate_java_struct_clear(out, tstruct);
-
-  generate_java_bean_boilerplate(out, tstruct);
-  generate_generic_field_getters_setters(out, tstruct);
-
-  generate_java_struct_equality(out, tstruct);
-  generate_java_struct_compare_to(out, tstruct);
-
-  generate_java_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_java_struct_result_writer(out, tstruct);
-  } else {
-    generate_java_struct_writer(out, tstruct);
-  }
-  generate_java_struct_tostring(out, tstruct);
-  generate_java_validator(out, tstruct);
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generates equals methods and a hashCode method for a structure.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_struct_equality(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public boolean equals(Object that) {" << endl;
-  indent_up();
-  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl
-      << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent()
-      << "  return this.equals((" << tstruct->get_name() << ")that);" << endl << indent()
-      << "return false;" << endl;
-  scope_down(out);
-  out << endl;
-
-  out << indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl;
-  indent_up();
-  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    out << endl;
-
-    t_type* t = get_true_type((*m_iter)->get_type());
-    // Most existing Thrift code does not use isset or optional/required,
-    // so we treat "default" fields as required.
-    bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
-    bool can_be_null = type_can_be_null(t);
-    string name = (*m_iter)->get_name();
-
-    string this_present = "true";
-    string that_present = "true";
-    string unequal;
-
-    if (is_optional || can_be_null) {
-      this_present += " && this." + generate_isset_check(*m_iter);
-      that_present += " && that." + generate_isset_check(*m_iter);
-    }
-
-    out << indent() << "boolean this_present_" << name << " = " << this_present << ";" << endl
-        << indent() << "boolean that_present_" << name << " = " << that_present << ";" << endl
-        << indent() << "if ("
-        << "this_present_" << name << " || that_present_" << name << ") {" << endl;
-    indent_up();
-    out << indent() << "if (!("
-        << "this_present_" << name << " && that_present_" << name << "))" << endl << indent()
-        << "  return false;" << endl;
-
-    if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
-      unequal = "TBaseHelper.compareTo(this." + name + ", that." + name + ") != 0";
-    } else if (can_be_null) {
-      unequal = "!this." + name + ".equals(that." + name + ")";
-    } else {
-      unequal = "this." + name + " != that." + name;
-    }
-
-    out << indent() << "if (" << unequal << ")" << endl << indent() << "  return false;" << endl;
-
-    scope_down(out);
-  }
-  out << endl;
-  indent(out) << "return true;" << endl;
-  scope_down(out);
-  out << endl;
-
-  out << indent() << "public int hashCode() {" << endl;
-  indent_up();
-  indent(out) << "return 0;" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_javame_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public int compareTo(Object otherObject) {" << endl;
-  //  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
-  indent_up();
-
-  indent(out) << "if (!getClass().equals(otherObject.getClass())) {" << endl;
-  indent(out) << "  return getClass().getName().compareTo(otherObject.getClass().getName());"
-              << endl;
-  indent(out) << "}" << endl;
-  out << endl;
-  indent(out) << type_name(tstruct) << " other = (" << type_name(tstruct) << ")otherObject;";
-
-  indent(out) << "int lastComparison = 0;" << endl;
-  out << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = *m_iter;
-    indent(out) << "lastComparison = TBaseHelper.compareTo(" << generate_isset_check(field)
-                << ", other." << generate_isset_check(field) << ");" << endl;
-    indent(out) << "if (lastComparison != 0) {" << endl;
-    indent(out) << "  return lastComparison;" << endl;
-    indent(out) << "}" << endl;
-
-    indent(out) << "if (" << generate_isset_check(field) << ") {" << endl;
-    if (field->get_type()->is_struct() || field->get_type()->is_xception()) {
-      indent(out) << "  lastComparison = this." << field->get_name() << ".compareTo(other."
-                  << field->get_name() << ");" << endl;
-    } else {
-      indent(out) << "  lastComparison = TBaseHelper.compareTo(this." << field->get_name()
-                  << ", other." << field->get_name() << ");" << endl;
-    }
-
-    indent(out) << "  if (lastComparison != 0) {" << endl;
-    indent(out) << "    return lastComparison;" << endl;
-    indent(out) << "  }" << endl;
-    indent(out) << "}" << endl;
-  }
-
-  indent(out) << "return 0;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to read all the fields of the struct.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_struct_reader(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public void read(TProtocol iprot) throws TException {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Declare stack tmp variables and read struct header
-  out << indent() << "TField field;" << endl << indent() << "iprot.readStructBegin();" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-  scope_up(out);
-
-  // Read beginning field marker
-  indent(out) << "field = iprot.readFieldBegin();" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if (field.type == TType.STOP) { " << endl;
-  indent_up();
-  indent(out) << "break;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  // Switch statement on the field we are reading
-  indent(out) << "switch (field.id) {" << endl;
-
-  indent_up();
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << (*f_iter)->get_key() << ": // "
-                << constant_name((*f_iter)->get_name()) << endl;
-    indent_up();
-    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-
-    generate_deserialize_field(out, *f_iter, "this.");
-    generate_isset_set(out, *f_iter);
-    indent_down();
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
-        << endl << indent() << "}" << endl << indent() << "break;" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  TProtocolUtil.skip(iprot, field.type);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  // Read field end marker
-  indent(out) << "iprot.readFieldEnd();" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  out << indent() << "iprot.readStructEnd();" << endl;
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-// generates java method to perform various checks
-// (e.g. check that all required fields are set)
-void t_javame_generator::generate_java_validator(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public void validate() throws TException {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "// check for required fields" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      out << indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl << indent()
-          << "  throw new TProtocolException(\"Required field '" << (*f_iter)->get_name()
-          << "' is unset! Struct:\" + toString());" << endl << indent() << "}" << endl << endl;
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_struct_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public void write(TProtocol oprot) throws TException {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl << endl;
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
-      indent_up();
-    }
-    bool optional = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (optional) {
-      indent(out) << "if (" << generate_isset_check((*f_iter)) << ") {" << endl;
-      indent_up();
-    }
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    if (optional) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    if (null_allowed) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-  // Write the struct map
-  out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
-      << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct,
- * which is a function result. These fields are only written
- * if they are set in the Isset array, and only one of them
- * can be set at a time.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public void write(TProtocol oprot) throws TException {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out << endl << indent() << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
-
-    indent_up();
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}";
-  }
-  // Write the struct map
-  out << endl << indent() << "oprot.writeFieldStop();" << endl << indent()
-      << "oprot.writeStructEnd();" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-void t_javame_generator::generate_reflection_getters(ostringstream& out,
-                                                     t_type* type,
-                                                     string field_name,
-                                                     string cap_name) {
-  indent(out) << "case " << constant_name(field_name) << ":" << endl;
-  indent_up();
-
-  if (type->is_base_type() && !type->is_string()) {
-    t_base_type* base_type = (t_base_type*)type;
-
-    indent(out) << "return new " << type_name(type, true, false) << "("
-                << (base_type->is_bool() ? "is" : "get") << cap_name << "());" << endl << endl;
-  } else {
-    indent(out) << "return get" << cap_name << "();" << endl << endl;
-  }
-
-  indent_down();
-}
-
-void t_javame_generator::generate_reflection_setters(ostringstream& out,
-                                                     t_type* type,
-                                                     string field_name,
-                                                     string cap_name) {
-  indent(out) << "case " << constant_name(field_name) << ":" << endl;
-  indent_up();
-  indent(out) << "if (value == null) {" << endl;
-  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
-  indent(out) << "} else {" << endl;
-  indent(out) << "  set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl;
-  indent(out) << "}" << endl;
-  indent(out) << "break;" << endl << endl;
-
-  indent_down();
-}
-
-void t_javame_generator::generate_generic_field_getters_setters(std::ofstream& out,
-                                                                t_struct* tstruct) {
-  (void)out;
-  std::ostringstream getter_stream;
-  std::ostringstream setter_stream;
-
-  // build up the bodies of both the getter and setter at once
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    indent_up();
-    generate_reflection_setters(setter_stream, type, field_name, cap_name);
-    generate_reflection_getters(getter_stream, type, field_name, cap_name);
-    indent_down();
-  }
-}
-
-/**
- * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
- * for the given struct.
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_bean_boilerplate(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    if (type->is_container()) {
-      // Method to return the size of the collection
-      indent(out) << "public int get" << cap_name;
-      out << get_cap_name("size() {") << endl;
-
-      indent_up();
-      indent(out) << "return (this." << field_name << " == null) ? 0 : "
-                  << "this." << field_name << ".size();" << endl;
-      indent_down();
-      indent(out) << "}" << endl << endl;
-    }
-
-    if (type->is_set() || type->is_list()) {
-
-      t_type* element_type;
-      if (type->is_set()) {
-        element_type = ((t_set*)type)->get_elem_type();
-      } else {
-        element_type = ((t_list*)type)->get_elem_type();
-      }
-
-      // Iterator getter for sets and lists
-      indent(out) << "public Enumeration get" << cap_name;
-      out << get_cap_name("Enumeration() {") << endl;
-
-      indent_up();
-      indent(out) << "return (this." << field_name << " == null) ? null : "
-                  << "this." << field_name << ".elements();" << endl;
-      indent_down();
-      indent(out) << "}" << endl << endl;
-
-      // Add to set or list, create if the set/list is null
-      indent(out);
-      out << "public void add" << get_cap_name("to");
-      out << cap_name << "(" << type_name(element_type) << " elem) {" << endl;
-
-      indent_up();
-      indent(out) << "if (this." << field_name << " == null) {" << endl;
-      indent_up();
-      indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();"
-                  << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-      if (type->is_set()) {
-        indent(out) << "this." << field_name << ".put(" << box_type(element_type, "elem") << ", "
-                    << box_type(element_type, "elem") << ");" << endl;
-      } else {
-        indent(out) << "this." << field_name << ".addElement(" << box_type(element_type, "elem")
-                    << ");" << endl;
-      }
-      indent_down();
-      indent(out) << "}" << endl << endl;
-
-    } else if (type->is_map()) {
-      // Put to map
-      t_type* key_type = ((t_map*)type)->get_key_type();
-      t_type* val_type = ((t_map*)type)->get_val_type();
-
-      indent(out);
-      out << "public void putTo" << cap_name << "(" << type_name(key_type, true) << " key, "
-          << type_name(val_type, true) << " val) {" << endl;
-
-      indent_up();
-      indent(out) << "if (this." << field_name << " == null) {" << endl;
-      indent_up();
-      indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();"
-                  << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-      indent(out) << "this." << field_name << ".put(key, val);" << endl;
-      indent_down();
-      indent(out) << "}" << endl << endl;
-    }
-
-    // Simple getter
-    generate_java_doc(out, field);
-    indent(out) << "public " << type_name(type);
-    if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) {
-      out << " is";
-    } else {
-      out << " get";
-    }
-    out << cap_name << "() {" << endl;
-    indent_up();
-    indent(out) << "return this." << field_name << ";" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Simple setter
-    generate_java_doc(out, field);
-    indent(out) << "public ";
-    out << "void";
-    out << " set" << cap_name << "(" << type_name(type) << " " << field_name << ") {" << endl;
-    indent_up();
-    indent(out) << "this." << field_name << " = " << field_name << ";" << endl;
-    generate_isset_set(out, field);
-
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Unsetter
-    indent(out) << "public void unset" << cap_name << "() {" << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "this." << field_name << " = null;" << endl;
-    } else {
-      indent(out) << "__isset_vector[" << isset_field_id(field) << "] = false;" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // isSet method
-    indent(out) << "/** Returns true if field " << field_name
-                << " is set (has been assigned a value) and false otherwise */" << endl;
-    indent(out) << "public boolean is" << get_cap_name("set") << cap_name << "() {" << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "return this." << field_name << " != null;" << endl;
-    } else {
-      indent(out) << "return __isset_vector[" << isset_field_id(field) << "];" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    indent(out) << "public void set" << cap_name << get_cap_name("isSet") << "(boolean value) {"
-                << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "if (!value) {" << endl;
-      indent(out) << "  this." << field_name << " = null;" << endl;
-      indent(out) << "}" << endl;
-    } else {
-      indent(out) << "__isset_vector[" << isset_field_id(field) << "] = value;" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates a toString() method for the given struct
- *
- * @param tstruct The struct definition
- */
-void t_javame_generator::generate_java_struct_tostring(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public String toString() {" << endl;
-  indent_up();
-
-  out << indent() << "StringBuffer sb = new StringBuffer(\"" << tstruct->get_name() << "(\");"
-      << endl;
-  out << indent() << "boolean first = true;" << endl << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
-      indent_up();
-    }
-
-    t_field* field = (*f_iter);
-
-    if (!first) {
-      indent(out) << "if (!first) sb.append(\", \");" << endl;
-    }
-    indent(out) << "sb.append(\"" << (*f_iter)->get_name() << ":\");" << endl;
-    bool can_be_null = type_can_be_null(field->get_type());
-    if (can_be_null) {
-      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
-      indent(out) << "  sb.append(\"null\");" << endl;
-      indent(out) << "} else {" << endl;
-      indent_up();
-    }
-
-    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
-      indent(out) << "TBaseHelper.toString(this." << field->get_name() << ", sb);" << endl;
-    } else {
-      indent(out) << "sb.append(this." << (*f_iter)->get_name() << ");" << endl;
-    }
-
-    if (can_be_null) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    indent(out) << "first = false;" << endl;
-
-    if (could_be_unset) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    first = false;
-  }
-  out << indent() << "sb.append(\")\");" << endl << indent() << "return sb.toString();" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Returns a string with the java representation of the given thrift type
- * (e.g. for the type struct it returns "TType.STRUCT")
- */
-std::string t_javame_generator::get_java_type_string(t_type* type) {
-  if (type->is_list()) {
-    return "TType.LIST";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_enum()) {
-    return "TType.ENUM";
-  } else if (type->is_typedef()) {
-    return get_java_type_string(((t_typedef*)type)->get_type());
-  } else if (type->is_base_type()) {
-    switch (((t_base_type*)type)->get_base()) {
-    case t_base_type::TYPE_VOID:
-      return "TType.VOID";
-      break;
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-      break;
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-      break;
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-      break;
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-      break;
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-      break;
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-      break;
-    default:
-      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
-                               + "\" passed to t_javame_generator::get_java_type_string!");
-      break; // This should never happen!
-    }
-  } else {
-    throw std::runtime_error(
-        "Unknown thrift type \"" + type->get_name()
-        + "\" passed to t_javame_generator::get_java_type_string!"); // This should never happen!
-  }
-}
-
-void t_javame_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
-  out << endl;
-  indent_up();
-  indent_up();
-  if (type->is_struct() || type->is_xception()) {
-    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type) << ".class";
-  } else if (type->is_container()) {
-    if (type->is_list()) {
-      indent(out) << "new ListMetaData(TType.LIST, ";
-      t_type* elem_type = ((t_list*)type)->get_elem_type();
-      generate_field_value_meta_data(out, elem_type);
-    } else if (type->is_set()) {
-      indent(out) << "new SetMetaData(TType.SET, ";
-      t_type* elem_type = ((t_list*)type)->get_elem_type();
-      generate_field_value_meta_data(out, elem_type);
-    } else { // map
-      indent(out) << "new MapMetaData(TType.MAP, ";
-      t_type* key_type = ((t_map*)type)->get_key_type();
-      t_type* val_type = ((t_map*)type)->get_val_type();
-      generate_field_value_meta_data(out, key_type);
-      out << ", ";
-      generate_field_value_meta_data(out, val_type);
-    }
-  } else if (type->is_enum()) {
-    indent(out) << "new EnumMetaData(TType.ENUM, " << type_name(type) << ".class";
-  } else {
-    indent(out) << "new FieldValueMetaData(" << get_java_type_string(type);
-    if (type->is_typedef()) {
-      indent(out) << ", \"" << ((t_typedef*)type)->get_symbolic() << "\"";
-    }
-  }
-  out << ")";
-  indent_down();
-  indent_down();
-}
-
-/**
- * Generates a thrift service. In C++, this comprises an entirely separate
- * header and source file. The header file defines the methods and includes
- * the data types defined in the main header file, and the implementation
- * file contains implementations of the basic printer and default interfaces.
- *
- * @param tservice The service definition
- */
-void t_javame_generator::generate_service(t_service* tservice) {
-  // Make output file
-  string f_service_name = package_dir_ + "/" + service_name_ + ".java";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
-
-  f_service_ << "public class " << service_name_ << " {" << endl << endl;
-  indent_up();
-
-  // Generate the three main parts of the service
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-
-  indent_down();
-  f_service_ << "}" << endl;
-  f_service_.close();
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_javame_generator::generate_primitive_service_interface(t_service* tservice) {
-  f_service_ << indent() << "public interface Iface extends " << service_name_ << "Iface { }"
-             << endl << endl;
-
-  string f_interface_name = package_dir_ + "/" + service_name_ + "Iface.java";
-  std::ofstream f_iface;
-  f_iface.open(f_interface_name.c_str());
-
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends_iface = " extends " + type_name(tservice->get_extends()) + "Iface";
-  }
-
-  f_iface << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
-  generate_java_doc(f_iface, tservice);
-  f_iface << "public interface " << service_name_ << "Iface" << extends_iface << " {" << endl
-          << endl;
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_java_doc(f_iface, *f_iter);
-    f_iface << "  public " << function_signature(*f_iter) << ";" << endl << endl;
-  }
-  f_iface << "}" << endl << endl;
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_javame_generator::generate_service_interface(t_service* tservice) {
-  string extends = "";
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_iface = " extends " + extends + ".Iface";
-  }
-
-  generate_java_doc(f_service_, tservice);
-  f_service_ << indent() << "public interface Iface" << extends_iface << " {" << endl << endl;
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_java_doc(f_service_, *f_iter);
-    indent(f_service_) << "public " << function_signature(*f_iter) << ";" << endl << endl;
-  }
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates structs for all the service args and return types
- *
- * @param tservice The service
- */
-void t_javame_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_java_struct_definition(f_service_, ts, false, true);
-    generate_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_javame_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_client = " extends " + extends + ".Client";
-  }
-
-  indent(f_service_) << "public static class Client" << extends_client
-                     << " implements TServiceClient, Iface {" << endl;
-  indent_up();
-
-  indent(f_service_) << "public Client(TProtocol prot)" << endl;
-  scope_up(f_service_);
-  indent(f_service_) << "this(prot, prot);" << endl;
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)" << endl;
-  scope_up(f_service_);
-  if (extends.empty()) {
-    f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl;
-  } else {
-    f_service_ << indent() << "super(iprot, oprot);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent()
-               << "protected TProtocol oprot_;" << endl << endl << indent()
-               << "protected int seqid_;" << endl << endl;
-
-    indent(f_service_) << "public TProtocol getInputProtocol()" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return this.iprot_;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    indent(f_service_) << "public TProtocol getOutputProtocol()" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return this.oprot_;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "send_" << funname << "(";
-
-    // Get the struct of function call params
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    // Declare the function arguments
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << (*fld_iter)->get_name();
-    }
-    f_service_ << ");" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_service_ << indent();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
-      }
-      f_service_ << "recv_" << funname << "();" << endl;
-    }
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    t_function send_function(g_type_void,
-                             string("send_") + (*f_iter)->get_name(),
-                             (*f_iter)->get_arglist());
-
-    string argsname = (*f_iter)->get_name() + "_args";
-
-    // Open function
-    indent(f_service_) << "public " << function_signature(&send_function) << endl;
-    scope_up(f_service_);
-
-    // Serialize the request
-    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", "
-               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
-               << ", ++seqid_));" << endl << indent() << argsname << " args = new " << argsname
-               << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args.set" << get_cap_name((*fld_iter)->get_name()) << "("
-                 << (*fld_iter)->get_name() << ");" << endl;
-    }
-
-    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
-               << "oprot_.writeMessageEnd();" << endl << indent()
-               << "oprot_.getTransport().flush();" << endl;
-
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      string resultname = (*f_iter)->get_name() + "_result";
-
-      t_struct noargs(program_);
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs,
-                               (*f_iter)->get_xceptions());
-      // Open function
-      indent(f_service_) << "public " << function_signature(&recv_function) << endl;
-      scope_up(f_service_);
-
-      f_service_ << indent() << "TMessage msg = iprot_.readMessageBegin();" << endl << indent()
-                 << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent()
-                 << "  TApplicationException x = TApplicationException.read(iprot_);" << endl
-                 << indent() << "  iprot_.readMessageEnd();" << endl << indent() << "  throw x;"
-                 << endl << indent() << "}" << endl << indent() << "if (msg.seqid != seqid_) {"
-                 << endl << indent()
-                 << "  throw new TApplicationException(TApplicationException.BAD_SEQUENCE_ID, \""
-                 << (*f_iter)->get_name() << " failed: out of sequence response\");" << endl
-                 << indent() << "}" << endl << indent() << resultname << " result = new "
-                 << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl
-                 << indent() << "iprot_.readMessageEnd();" << endl;
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl
-                   << indent() << "  return result.success;" << endl << indent() << "}" << endl;
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl
-                   << indent() << "  throw result." << (*x_iter)->get_name() << ";" << endl
-                   << indent() << "}" << endl;
-      }
-
-      // If you get here it's an exception, unless a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "return;" << endl;
-      } else {
-        f_service_ << indent()
-                   << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \""
-                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
-      }
-
-      // Close function
-      scope_down(f_service_);
-      f_service_ << endl;
-    }
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl;
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_javame_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  // Extends stuff
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_processor = " extends " + extends + ".Processor";
-  }
-
-  // Generate the header portion
-  indent(f_service_) << "public static class Processor" << extends_processor
-                     << " implements TProcessor {" << endl;
-  indent_up();
-
-  indent(f_service_) << "public Processor(Iface iface)" << endl;
-  scope_up(f_service_);
-  if (!extends.empty()) {
-    f_service_ << indent() << "super(iface);" << endl;
-  }
-  f_service_ << indent() << "iface_ = iface;" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "processMap_.put(\"" << (*f_iter)->get_name() << "\", new "
-               << (*f_iter)->get_name() << "());" << endl;
-  }
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_
-        << indent() << "protected static interface ProcessFunction {" << endl << indent()
-        << "  public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException;"
-        << endl << indent() << "}" << endl << endl;
-  }
-
-  f_service_ << indent() << "private Iface iface_;" << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected final Hashtable processMap_ = new Hashtable();" << endl;
-  }
-
-  f_service_ << endl;
-
-  // Generate the server implementation
-  indent(f_service_) << "public boolean process(TProtocol iprot, TProtocol oprot) throws TException"
-                     << endl;
-  scope_up(f_service_);
-
-  f_service_ << indent() << "TMessage msg = iprot.readMessageBegin();" << endl;
-
-  // TODO(mcslee): validate message, was the seqid etc. legit?
-
-  f_service_
-      << indent() << "ProcessFunction fn = (ProcessFunction)processMap_.get(msg.name);" << endl
-      << indent() << "if (fn == null) {" << endl << indent()
-      << "  TProtocolUtil.skip(iprot, TType.STRUCT);" << endl << indent()
-      << "  iprot.readMessageEnd();" << endl << indent()
-      << "  TApplicationException x = new "
-         "TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid method name: "
-         "'\"+msg.name+\"'\");" << endl << indent()
-      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
-      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
-      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
-      << "  return true;" << endl << indent() << "}" << endl << indent()
-      << "fn.process(msg.seqid, iprot, oprot);" << endl;
-
-  f_service_ << indent() << "return true;" << endl;
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl << endl;
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_javame_generator::generate_function_helpers(t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  t_struct result(program_, tfunction->get_name() + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_java_struct_definition(f_service_, &result, false, true, true);
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_javame_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open class
-  indent(f_service_) << "private class " << tfunction->get_name() << " implements ProcessFunction {"
-                     << endl;
-  indent_up();
-
-  // Open function
-  indent(f_service_)
-      << "public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException"
-      << endl;
-  scope_up(f_service_);
-
-  string argsname = tfunction->get_name() + "_args";
-  string resultname = tfunction->get_name() + "_result";
-
-  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl << indent()
-             << "try {" << endl;
-  indent_up();
-  f_service_ << indent() << "args.read(iprot);" << endl;
-  indent_down();
-  f_service_ << indent() << "} catch (TProtocolException e) {" << endl;
-  indent_up();
-  f_service_ << indent() << "iprot.readMessageEnd();" << endl << indent()
-             << "TApplicationException x = new "
-                "TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());"
-             << endl << indent() << "oprot.writeMessageBegin(new TMessage(\""
-             << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl << indent()
-             << "x.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();" << endl
-             << indent() << "oprot.getTransport().flush();" << endl << indent() << "return;"
-             << endl;
-  indent_down();
-  f_service_ << indent() << "}" << endl;
-  f_service_ << indent() << "iprot.readMessageEnd();" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
-  }
-
-  // Try block for a function with exceptions
-  if (xceptions.size() > 0) {
-    f_service_ << indent() << "try {" << endl;
-    indent_up();
-  }
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_ << indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "result.success = ";
-  }
-  f_service_ << "iface_." << tfunction->get_name() << "(";
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_service_ << ", ";
-    }
-    f_service_ << "args." << (*f_iter)->get_name();
-  }
-  f_service_ << ");" << endl;
-
-  // Set isset on success field
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()
-      && !type_can_be_null(tfunction->get_returntype())) {
-    f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet")
-               << "(true);" << endl;
-  }
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    indent_down();
-    f_service_ << indent() << "}";
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << " catch (" << type_name((*x_iter)->get_type(), false, false) << " "
-                 << (*x_iter)->get_name() << ") {" << endl;
-      if (!tfunction->is_oneway()) {
-        indent_up();
-        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
-                   << (*x_iter)->get_name() << ";" << endl;
-        indent_down();
-        f_service_ << indent() << "}";
-      } else {
-        f_service_ << "}";
-      }
-    }
-    f_service_ << " catch (Throwable th) {" << endl;
-    indent_up();
-    f_service_ << indent() << "TApplicationException x = new "
-                              "TApplicationException(TApplicationException.INTERNAL_ERROR, "
-                              "\"Internal error processing " << tfunction->get_name() << "\");"
-               << endl << indent() << "oprot.writeMessageBegin(new TMessage(\""
-               << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl
-               << indent() << "x.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();"
-               << endl << indent() << "oprot.getTransport().flush();" << endl << indent()
-               << "return;" << endl;
-    indent_down();
-    f_service_ << indent() << "}" << endl;
-  }
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "return;" << endl;
-    scope_down(f_service_);
-
-    // Close class
-    indent_down();
-    f_service_ << indent() << "}" << endl << endl;
-    return;
-  }
-
-  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
-             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
-             << "oprot.getTransport().flush();" << endl;
-
-  // Close function
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Close class
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Deserializes a field of any type.
- *
- * @param tfield The field
- * @param prefix The variable name or container for this field
- */
-void t_javame_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type()) {
-    indent(out) << name << " = iprot.";
-
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "compiler error: cannot serialize void field in a struct: " + name;
-      break;
-    case t_base_type::TYPE_STRING:
-      if (!((t_base_type*)type)->is_binary()) {
-        out << "readString();";
-      } else {
-        out << "readBinary();";
-      }
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << "readBool();";
-      break;
-    case t_base_type::TYPE_I8:
-      out << "readByte();";
-      break;
-    case t_base_type::TYPE_I16:
-      out << "readI16();";
-      break;
-    case t_base_type::TYPE_I32:
-      out << "readI32();";
-      break;
-    case t_base_type::TYPE_I64:
-      out << "readI64();";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      out << "readDouble();";
-      break;
-    default:
-      throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
-    }
-    out << endl;
-  } else if (type->is_enum()) {
-    indent(out) << name << " = "
-                << type_name(tfield->get_type(), true, false) + ".findByV

<TRUNCATED>

[48/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_cocoa_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_cocoa_generator.cc b/compiler/cpp/src/generate/t_cocoa_generator.cc
deleted file mode 100644
index 794fb44..0000000
--- a/compiler/cpp/src/generate/t_cocoa_generator.cc
+++ /dev/null
@@ -1,3301 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_oop_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ostream;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Objective-C code generator.
- *
- * mostly copy/pasting/tweaking from mcslee's work.
- */
-class t_cocoa_generator : public t_oop_generator {
-public:
-  t_cocoa_generator(t_program* program,
-                    const std::map<std::string, std::string>& parsed_options,
-                    const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    log_unexpected_ = false;
-    validate_required_ = false;
-    async_clients_ = false;
-    promise_kit_ = false;
-    debug_descriptions_ = false;
-    pods_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("log_unexpected") == 0) {
-        log_unexpected_ = true;
-      } else if( iter->first.compare("validate_required") == 0) {
-        validate_required_ = true;
-      } else if( iter->first.compare("async_clients") == 0) {
-        async_clients_ = true;
-      } else if( iter->first.compare("promise_kit") == 0) {
-        promise_kit_ = true;
-      } else if( iter->first.compare("debug_descriptions") == 0) {
-        debug_descriptions_ = true;
-      } else if( iter->first.compare("pods") == 0) {
-        pods_ = true;
-      } else {
-        throw "unknown option cocoa:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-cocoa";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(ostream& out,
-                         string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool defval = false);
-  std::string render_const_value(ostream& out,
-                                 t_type* type,
-                                 t_const_value* value,
-                                 bool box_it = false);
-
-  void generate_cocoa_struct(t_struct* tstruct, bool is_exception);
-  void generate_cocoa_struct_interface(std::ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_xception = false);
-  void generate_cocoa_struct_implementation(std::ofstream& out,
-                                            t_struct* tstruct,
-                                            bool is_xception = false,
-                                            bool is_result = false);
-  void generate_cocoa_struct_initializer_signature(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_init_with_coder_method(ofstream& out,
-                                                    t_struct* tstruct,
-                                                    bool is_exception);
-  void generate_cocoa_struct_encode_with_coder_method(ofstream& out,
-                                                      t_struct* tstruct,
-                                                      bool is_exception);
-  void generate_cocoa_struct_copy_method(ofstream& out,
-                                         t_struct* tstruct,
-                                         bool is_exception);
-  void generate_cocoa_struct_hash_method(ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_is_equal_method(ofstream& out,
-                                             t_struct* tstruct,
-                                             bool is_exception);
-  void generate_cocoa_struct_field_accessor_implementations(std::ofstream& out,
-                                                            t_struct* tstruct,
-                                                            bool is_exception);
-  void generate_cocoa_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_description(std::ofstream& out, t_struct* tstruct);
-
-  std::string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
-  std::string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
-  void generate_function_helpers(t_service *tservice, t_function* tfunction);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_cocoa_service_protocol(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_async_protocol(std::ofstream& out, t_service* tservice);
-
-  void generate_cocoa_service_client_interface(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_client_async_interface(std::ofstream& out, t_service* tservice);
-
-  void generate_cocoa_service_client_send_function_implementation(ofstream& out,
-                                                                  t_service* tservice,
-                                                                  t_function* tfunction,
-                                                                  bool needs_protocol);
-  void generate_cocoa_service_client_send_function_invocation(ofstream& out, t_function* tfunction);
-  void generate_cocoa_service_client_send_async_function_invocation(ofstream& out,
-                                                                    t_function* tfunction,
-                                                                    string failureBlockName);
-  void generate_cocoa_service_client_recv_function_implementation(ofstream& out,
-                                                                  t_service* tservice,
-                                                                  t_function* tfunction,
-                                                                  bool needs_protocol);
-  void generate_cocoa_service_client_implementation(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_client_async_implementation(std::ofstream& out, t_service* tservice);
-
-  void generate_cocoa_service_server_interface(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_server_implementation(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string fieldName);
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string fieldName = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out,
-                                       t_list* tlist,
-                                       std::string index,
-                                       std::string listName);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string cocoa_prefix();
-  std::string cocoa_imports();
-  std::string cocoa_thrift_imports();
-  std::string type_name(t_type* ttype, bool class_ref = false, bool needs_mutable = false);
-  std::string element_type_name(t_type* ttype);
-  std::string base_type_name(t_base_type* tbase);
-  std::string declare_property(t_field* tfield);
-  std::string declare_property_isset(t_field* tfield);
-  std::string declare_property_unset(t_field* tfield);
-  std::string invalid_return_statement(t_function* tfunction);
-  std::string function_signature(t_function* tfunction, bool include_error);
-  std::string async_function_signature(t_function* tfunction, bool include_error);
-  std::string promise_function_signature(t_function* tfunction);
-  std::string argument_list(t_struct* tstruct, string protocol_name, bool include_error);
-  std::string type_to_enum(t_type* ttype);
-  std::string format_string_for_type(t_type* type);
-  std::string format_cast_for_type(t_type* type);
-  std::string call_field_setter(t_field* tfield, std::string fieldName);
-  std::string box(t_type *ttype, std::string field_name);
-  std::string unbox(t_type* ttype, std::string field_name);
-  std::string getter_name(string field_name);
-  std::string setter_name(string field_name);
-
-  bool type_can_be_null(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
-           || ttype->is_string();
-  }
-
-private:
-  std::string cocoa_prefix_;
-  std::string constants_declarations_;
-  int error_constant_;
-
-  /**
-   * File streams
-   */
-
-  std::ofstream f_header_;
-  std::ofstream f_impl_;
-
-  bool log_unexpected_;
-  bool validate_required_;
-  bool async_clients_;
-  bool promise_kit_;
-  bool debug_descriptions_;
-  bool pods_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- */
-void t_cocoa_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  cocoa_prefix_ = program_->get_namespace("cocoa");
-
-  // we have a .h header file...
-  string f_header_name = cocoa_prefix_ + capitalize(program_name_) + ".h";
-  string f_header_fullname = get_out_dir() + f_header_name;
-  f_header_.open(f_header_fullname.c_str());
-
-  f_header_ << autogen_comment() << endl;
-
-  f_header_ << cocoa_imports() << cocoa_thrift_imports();
-
-  // ...and a .m implementation file
-  string f_impl_name = cocoa_prefix_ + capitalize(program_name_) + ".m";
-  string f_impl_fullname = get_out_dir() + f_impl_name;
-  f_impl_.open(f_impl_fullname.c_str());
-
-  f_impl_ << autogen_comment() << endl;
-
-  f_impl_ << cocoa_imports() << cocoa_thrift_imports() << "#import \"" << f_header_name << "\""
-          << endl << endl;
-  
-  error_constant_ = 60000;
-}
-
-/**
- * Prints standard Cocoa imports
- *
- * @return List of imports for Cocoa libraries
- */
-string t_cocoa_generator::cocoa_imports() {
-  return string() + "#import <Foundation/Foundation.h>\n" + "\n";
-}
-
-/**
- * Prints thrift runtime imports
- *
- * @return List of imports necessary for thrift runtime
- */
-string t_cocoa_generator::cocoa_thrift_imports() {
-
-  vector<string> includes_list;
-  includes_list.push_back("TProtocol.h");
-  includes_list.push_back("TProtocolFactory.h");
-  includes_list.push_back("TApplicationError.h");
-  includes_list.push_back("TProtocolError.h");
-  includes_list.push_back("TProtocolUtil.h");
-  includes_list.push_back("TProcessor.h");
-  includes_list.push_back("TBase.h");
-  includes_list.push_back("TAsyncTransport.h");
-  includes_list.push_back("TBaseClient.h");
-
-  std::ostringstream includes;
-
-  vector<string>::const_iterator i_iter;
-  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) {
-    includes << "#import ";
-    if (pods_) {
-      includes << "<Thrift/" << *i_iter << ">";
-    } else {
-      includes << "\"" << *i_iter << "\"";
-    }
-    includes << endl;
-  }
-  
-  includes << endl;
-  
-  if (promise_kit_) {
-    includes << "#import ";
-    if (pods_) {
-      includes << "<PromiseKit/PromiseKit.h>";
-    } else {
-      includes << "\"PromiseKit.h\"";
-    }
-    includes << endl;
-  }
-
-  // Include other Thrift includes
-  const vector<t_program*>& other_includes = program_->get_includes();
-  for (size_t i = 0; i < other_includes.size(); ++i) {
-    includes << "#import \""
-             << other_includes[i]->get_namespace("cocoa")
-             << capitalize(other_includes[i]->get_name())
-             << ".h\"" << endl;
-  }
-  
-  includes << endl;
-
-  return includes.str();
-}
-
-/**
- * Finish up generation.
- */
-void t_cocoa_generator::close_generator() {
-  // stick our constants declarations at the end of the header file
-  // since they refer to things we are defining.
-  f_header_ << constants_declarations_ << endl;
-}
-
-/**
- * Generates a typedef. This is just a simple 1-liner in objective-c
- *
- * @param ttypedef The type definition
- */
-void t_cocoa_generator::generate_typedef(t_typedef* ttypedef) {
-  if (ttypedef->get_type()->is_map()) {
-    t_map *map = (t_map *)ttypedef->get_type();
-    if (map->get_key_type()->is_struct()) {
-      f_header_ << indent() << "@class " << type_name(map->get_key_type(), true) << ";" << endl;
-    }
-    if (map->get_val_type()->is_struct()) {
-      f_header_ << indent() << "@class " << type_name(map->get_val_type(), true) << ";" << endl;
-    }
-  }
-  else if (ttypedef->get_type()->is_set()) {
-    t_set *set = (t_set *)ttypedef->get_type();
-    if (set->get_elem_type()->is_struct()) {
-      f_header_ << indent() << "@class " << type_name(set->get_elem_type(), true) << ";" << endl;
-    }
-  }
-  else if (ttypedef->get_type()->is_list()) {
-    t_list *list = (t_list *)ttypedef->get_type();
-    if (list->get_elem_type()->is_struct()) {
-      f_header_ << indent() << "@class " << type_name(list->get_elem_type(), true) << ";" << endl;
-    }
-  }
-  f_header_ << indent() << "typedef " << type_name(ttypedef->get_type()) << " " << cocoa_prefix_
-            << ttypedef->get_symbolic() << ";" << endl << endl;
-  if (ttypedef->get_type()->is_container()) {
-    f_header_ << indent() << "typedef " << type_name(ttypedef->get_type(), false, true) << " " << cocoa_prefix_
-              << "Mutable" << ttypedef->get_symbolic() << ";" << endl << endl;
-  }
-}
-
-/**
- * Generates code for an enumerated type. In Objective-C, this is
- * essentially the same as the thrift definition itself, instead using
- * NS_ENUM keyword in Objective-C.  For namespace purposes, the name of
- * the enum is prefixed to each element in keeping with Cocoa & Swift
- * standards.
- *
- * @param tenum The enumeration
- */
-void t_cocoa_generator::generate_enum(t_enum* tenum) {
-  f_header_ << indent() << "typedef NS_ENUM(SInt32, " << cocoa_prefix_ << tenum->get_name() << ") {" << endl;
-  indent_up();
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  bool first = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_header_ << "," << endl;
-    }
-    f_header_ << indent() << cocoa_prefix_ << tenum->get_name() << (*c_iter)->get_name();
-    f_header_ << " = " << (*c_iter)->get_value();
-  }
-
-  indent_down();
-  f_header_ << endl << "};" << endl << endl;
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
-  std::ostringstream const_interface;
-
-  const_interface << "FOUNDATION_EXPORT NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain;" << endl
-                  << endl;
-  
-
-  bool needs_class = false;
-
-  // Public constants for base types & strings
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    t_type* type = (*c_iter)->get_type()->get_true_type();
-    if (!type->is_container() && !type->is_struct()) {
-      const_interface << "FOUNDATION_EXPORT " << type_name(type) << " "
-                      << cocoa_prefix_ << capitalize((*c_iter)->get_name()) << ";" << endl;
-    }
-    else {
-      needs_class = true;
-    }
-  }
-  
-  
-  string constants_class_name = cocoa_prefix_ + capitalize(program_name_) + "Constants";
-
-  if (needs_class) {
-    
-    const_interface << endl;
-
-    const_interface << "@interface " << constants_class_name << " : NSObject ";
-    scope_up(const_interface);
-    scope_down(const_interface);
-
-    // getter method for each constant defined.
-    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      string name = (*c_iter)->get_name();
-      t_type* type = (*c_iter)->get_type()->get_true_type();
-      if (type->is_container() || type->is_struct()) {
-        t_type* type = (*c_iter)->get_type();
-        const_interface << endl << "+ (" << type_name(type) << ") " << name << ";" << endl;
-      }
-    }
-
-    const_interface << endl << "@end";
-  }
-
-  // this gets spit into the header file in ::close_generator
-  constants_declarations_ = const_interface.str();
-  
-  f_impl_ << "NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain = "
-          << "@\"" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain\";" << endl << endl;
-
-  // variables in the .m hold all simple constant values
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    string name = (*c_iter)->get_name();
-    t_type* type = (*c_iter)->get_type();
-    f_impl_ << type_name(type) << " " << cocoa_prefix_ << name;
-    t_type* ttype = type->get_true_type();
-    if (!ttype->is_container() && !ttype->is_struct()) {
-      f_impl_ << " = " << render_const_value(f_impl_, type, (*c_iter)->get_value());
-    }
-    f_impl_ << ";" << endl;
-  }
-  f_impl_ << endl;
-
-  if (needs_class) {
-
-    f_impl_ << "@implementation " << constants_class_name << endl << endl;
-
-    // initialize complex constants when the class is loaded
-    f_impl_ << "+ (void) initialize ";
-    scope_up(f_impl_);
-
-    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      t_type* ttype = (*c_iter)->get_type()->get_true_type();
-      if (ttype->is_container() || ttype->is_struct()) {
-        f_impl_ << endl;
-        print_const_value(f_impl_,
-                          cocoa_prefix_ + (*c_iter)->get_name(),
-                          (*c_iter)->get_type(),
-                          (*c_iter)->get_value(),
-                          false);
-        f_impl_ << ";" << endl;
-      }
-    }
-    scope_down(f_impl_);
-
-    // getter method for each constant
-    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      string name = (*c_iter)->get_name();
-      t_type* type = (*c_iter)->get_type()->get_true_type();
-      if (type->is_container() || type->is_struct()) {
-        f_impl_ << endl << "+ (" << type_name(type) << ") " << name << " ";
-        scope_up(f_impl_);
-        indent(f_impl_) << "return " << cocoa_prefix_ << name << ";" << endl;
-        scope_down(f_impl_);
-      }
-    }
-
-    f_impl_ << "@end" << endl << endl;
-  }
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is a class
- * with protected data members, read(), write(), and getters and setters.
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_struct(t_struct* tstruct) {
-  generate_cocoa_struct_interface(f_header_, tstruct, false);
-  generate_cocoa_struct_implementation(f_impl_, tstruct, false);
-}
-
-/**
- * Exceptions are structs, but they inherit from NSException
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_xception(t_struct* txception) {
-  generate_cocoa_struct_interface(f_header_, txception, true);
-  generate_cocoa_struct_implementation(f_impl_, txception, true);
-}
-
-/**
- * Generate the interface for a struct
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_interface(ofstream& out,
-                                                        t_struct* tstruct,
-                                                        bool is_exception) {
-  
-  if (is_exception) {
-    out << "enum {" << endl
-        << "  " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() <<  " = -" << error_constant_++ << endl
-        << "};" << endl
-        << endl;
-  }
-  
-  out << "@interface " << cocoa_prefix_ << tstruct->get_name() << " : ";
-
-  if (is_exception) {
-    out << "NSError ";
-  } else {
-    out << "NSObject ";
-  }
-  out << "<TBase, NSCoding, NSCopying> " << endl;
-  
-  out << endl;
-
-  // properties
-  const vector<t_field*>& members = tstruct->get_members();
-  if (members.size() > 0) {
-    vector<t_field*>::const_iterator m_iter;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      out << indent() << declare_property(*m_iter) << endl;
-      out << indent() << declare_property_isset(*m_iter) << endl;
-      out << indent() << declare_property_unset(*m_iter) << endl;
-      out << endl;
-    }
-  }
-  
-  out << endl;
-
-  // initializer for all fields
-  if (!members.empty()) {
-    generate_cocoa_struct_initializer_signature(out, tstruct);
-    out << ";" << endl;
-  }
-  out << endl;
-
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generate signature for initializer of struct with a parameter for
- * each field.
- */
-void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ofstream& out,
-                                                                    t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  indent(out) << "- (instancetype) initWith";
-  for (m_iter = members.begin(); m_iter != members.end();) {
-    if (m_iter == members.begin()) {
-      out << capitalize((*m_iter)->get_name());
-    } else {
-      out << (*m_iter)->get_name();
-    }
-    out << ": (" << type_name((*m_iter)->get_type()) << ") " << (*m_iter)->get_name();
-    ++m_iter;
-    if (m_iter != members.end()) {
-      out << " ";
-    }
-  }
-}
-
-/**
- * Generate the initWithCoder method for this struct so it's compatible with
- * the NSCoding protocol
- */
-void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ofstream& out,
-                                                                     t_struct* tstruct,
-                                                                     bool is_exception) {
-
-  indent(out) << "- (instancetype) initWithCoder: (NSCoder *) decoder" << endl;
-  scope_up(out);
-  
-  if (is_exception) {
-    // NSExceptions conform to NSCoding, so we can call super
-    indent(out) << "self = [super initWithCoder: decoder];" << endl;
-  } else {
-    indent(out) << "self = [super init];" << endl;
-  }
-  
-  indent(out) << "if (self) ";
-  scope_up(out);
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    out << indent() << "if ([decoder containsValueForKey: @\"" << (*m_iter)->get_name() << "\"])"
-        << endl;
-    scope_up(out);
-    out << indent() << "_" << (*m_iter)->get_name() << " = ";
-    if (type_can_be_null(t)) {
-      out << "[decoder decodeObjectForKey: @\"" << (*m_iter)->get_name() << "\"];"
-          << endl;
-    } else if (t->is_enum()) {
-      out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-    } else {
-      t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_BOOL:
-        out << "[decoder decodeBoolForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I8:
-        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I16:
-        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I32:
-        out << "[decoder decodeInt32ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I64:
-        out << "[decoder decodeInt64ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "[decoder decodeDoubleForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      default:
-        throw "compiler error: don't know how to decode thrift type: "
-            + t_base_type::t_base_name(tbase);
-      }
-    }
-    out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl;
-    scope_down(out);
-  }
-  
-  scope_down(out);
-
-  out << indent() << "return self;" << endl;
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generate the encodeWithCoder method for this struct so it's compatible with
- * the NSCoding protocol
- */
-void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ofstream& out,
-                                                                       t_struct* tstruct,
-                                                                       bool is_exception) {
-
-  indent(out) << "- (void) encodeWithCoder: (NSCoder *) encoder" << endl;
-  scope_up(out);
-  
-  if (is_exception) {
-    // NSExceptions conform to NSCoding, so we can call super
-    out << indent() << "[super encodeWithCoder: encoder];" << endl;
-  }
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
-    scope_up(out);
-    if (type_can_be_null(t)) {
-      out << indent() << "[encoder encodeObject: _" << (*m_iter)->get_name() << " forKey: @\""
-          << (*m_iter)->get_name() << "\"];" << endl;
-    } else if (t->is_enum()) {
-      out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
-          << (*m_iter)->get_name() << "\"];" << endl;
-    } else {
-      t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_BOOL:
-        out << indent() << "[encoder encodeBool: _" << (*m_iter)->get_name() << " forKey: @\""
-            << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I8:
-        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
-            << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I16:
-        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
-            << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I32:
-        out << indent() << "[encoder encodeInt32: _" << (*m_iter)->get_name() << " forKey: @\""
-            << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_I64:
-        out << indent() << "[encoder encodeInt64: _" << (*m_iter)->get_name() << " forKey: @\""
-            << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << indent() << "[encoder encodeDouble: _" << (*m_iter)->get_name() << " forKey: @\""
-            << (*m_iter)->get_name() << "\"];" << endl;
-        break;
-      default:
-        throw "compiler error: don't know how to encode thrift type: "
-            + t_base_type::t_base_name(tbase);
-      }
-    }
-    scope_down(out);
-  }
-
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generate the copy method for this struct
- */
-void t_cocoa_generator::generate_cocoa_struct_copy_method(ofstream& out, t_struct* tstruct, bool is_exception) {
-  out << indent() << "- (instancetype) copyWithZone:(NSZone *)zone" << endl;
-  scope_up(out);
-  
-  if (is_exception) {
-    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " errorWithDomain: self.domain code: self.code userInfo: self.userInfo];" << endl;
-  } else {
-    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " new];" << endl;
-  }
-  
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
-    scope_up(out);
-    if (type_can_be_null(t)) {
-      out << indent() << "val." << (*m_iter)->get_name() << " = [self." << (*m_iter)->get_name() << " copy];";
-    } else {
-      out << indent() << "val." << (*m_iter)->get_name() << " = self." << (*m_iter)->get_name() << ";";
-    }
-    out << endl;
-    scope_down(out);
-  }
-  
-  out << indent() << "return val;" << endl;
-  
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generate the hash method for this struct
- */
-void t_cocoa_generator::generate_cocoa_struct_hash_method(ofstream& out, t_struct* tstruct) {
-  indent(out) << "- (NSUInteger) hash" << endl;
-  scope_up(out);
-  out << indent() << "NSUInteger hash = 17;" << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    out << indent() << "hash = (hash * 31) ^ _" << (*m_iter)->get_name()
-        << "IsSet ? 2654435761 : 0;" << endl;
-    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
-    scope_up(out);
-    if (type_can_be_null(t)) {
-      out << indent() << "hash = (hash * 31) ^ [_" << (*m_iter)->get_name() << " hash];" << endl;
-    } else {
-      out << indent() << "hash = (hash * 31) ^ [@(_" << (*m_iter)->get_name() << ") hash];"
-          << endl;
-    }
-    scope_down(out);
-  }
-
-  out << indent() << "return hash;" << endl;
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generate the isEqual method for this struct
- */
-void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ofstream& out, t_struct* tstruct, bool is_exception) {
-  indent(out) << "- (BOOL) isEqual: (id) anObject" << endl;
-  scope_up(out);
-
-  indent(out) << "if (self == anObject) {" << endl;
-  indent_up();
-  indent(out) << "return YES;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  string class_name = cocoa_prefix_ + tstruct->get_name();
-
-  if (is_exception) {
-    indent(out) << "if (![super isEqual:anObject]) {" << endl;
-    indent_up();
-    indent(out) << "return NO;" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-  else {
-    indent(out) << "if (![anObject isKindOfClass:[" << class_name << " class]]) {" << endl;
-    indent_up();
-    indent(out) << "return NO;" << endl;
-    indent_down();
-    indent(out) << "}" << endl;
-  }
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  if (!members.empty()) {
-    indent(out) << class_name << " *other = (" << class_name << " *)anObject;" << endl;
-    
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      string name = (*m_iter)->get_name();
-      if (type_can_be_null(t)) {
-        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl
-            << indent() << "    "
-            << "(_" << name << "IsSet && "
-            << "((_" << name << " || other->_" << name << ") && "
-            << "![_" << name << " isEqual:other->_" << name << "]))) {" << endl;
-      } else {
-        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl
-            << indent() << "    "
-            << "(_" << name << "IsSet && "
-            << "(_" << name << " != other->_" << name << "))) {" << endl;
-      }
-      indent_up();
-      indent(out) << "return NO;" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-
-  out << indent() << "return YES;" << endl;
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generate struct implementation.
- *
- * @param tstruct      The struct definition
- * @param is_exception Is this an exception?
- * @param is_result    If this is a result it needs a different writer
- */
-void t_cocoa_generator::generate_cocoa_struct_implementation(ofstream& out,
-                                                             t_struct* tstruct,
-                                                             bool is_exception,
-                                                             bool is_result) {
-  indent(out) << "@implementation " << cocoa_prefix_ << tstruct->get_name() << endl << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  // exceptions need to call the designated initializer on NSException
-  if (is_exception) {
-    out << indent() << "- (instancetype) init" << endl;
-    scope_up(out);
-    out << indent() << "return [super initWithDomain: " << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain" << endl
-        << indent() << "                        code: " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() << endl
-        << indent() << "                    userInfo: nil];" << endl;
-    scope_down(out);
-    out << endl;
-  } else {
-    // struct
-
-    // default initializer
-    // setup instance variables with default values
-    indent(out) << "- (instancetype) init" << endl;
-    scope_up(out);
-    indent(out) << "self = [super init];" << endl;
-    indent(out) << "if (self)";
-    scope_up(out);
-    if (members.size() > 0) {
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        t_type* t = get_true_type((*m_iter)->get_type());
-        if ((*m_iter)->get_value() != NULL) {
-          print_const_value(out,
-                            "self." + (*m_iter)->get_name(),
-                            t,
-                            (*m_iter)->get_value(),
-                            false);
-        }
-      }
-    }
-    scope_down(out);
-    indent(out) << "return self;" << endl;
-    scope_down(out);
-    out << endl;
-  }
-
-  // initializer with all fields as params
-  if (!members.empty()) {
-    generate_cocoa_struct_initializer_signature(out, tstruct);
-    out << endl;
-    scope_up(out);
-    if (is_exception) {
-      out << indent() << "self = [self init];" << endl;
-    } else {
-      out << indent() << "self = [super init];" << endl;
-    }
-    
-    indent(out) << "if (self)";
-    scope_up(out);
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      out << indent() << "_" << (*m_iter)->get_name() << " = ";
-      if (get_true_type((*m_iter)->get_type())->is_container()) {
-        out << "[" << (*m_iter)->get_name() << " mutableCopy];" << endl;
-      } else {
-        out << (*m_iter)->get_name() << ";" << endl;
-      }
-      out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl;
-    }
-    scope_down(out);
-
-    out << indent() << "return self;" << endl;
-    scope_down(out);
-    out << endl;
-  }
-
-  // initWithCoder for NSCoding
-  generate_cocoa_struct_init_with_coder_method(out, tstruct, is_exception);
-  // encodeWithCoder for NSCoding
-  generate_cocoa_struct_encode_with_coder_method(out, tstruct, is_exception);
-  // hash and isEqual for NSObject
-  generate_cocoa_struct_hash_method(out, tstruct);
-  generate_cocoa_struct_is_equal_method(out, tstruct, is_exception);
-  // copy for NSObject
-  generate_cocoa_struct_copy_method(out, tstruct, is_exception);
-
-  // the rest of the methods
-  generate_cocoa_struct_field_accessor_implementations(out, tstruct, is_exception);
-  generate_cocoa_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_cocoa_struct_result_writer(out, tstruct);
-  } else {
-    generate_cocoa_struct_writer(out, tstruct);
-  }
-  generate_cocoa_struct_validator(out, tstruct);
-  generate_cocoa_struct_description(out, tstruct);
-
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates a function to read all the fields of the struct.
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_reader(ofstream& out, t_struct* tstruct) {
-  out << "- (BOOL) read: (id <TProtocol>) inProtocol error: (NSError *__autoreleasing *)__thriftError" << endl;
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Declare stack tmp variables
-  indent(out) << "NSString * fieldName;" << endl;
-  indent(out) << "SInt32 fieldType;" << endl;
-  indent(out) << "SInt32 fieldID;" << endl;
-  out << endl;
-
-  indent(out) << "if (![inProtocol readStructBeginReturningName: NULL error: __thriftError]) return NO;" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-  scope_up(out);
-
-  // Read beginning field marker
-  indent(out)
-      << "if (![inProtocol readFieldBeginReturningName: &fieldName type: &fieldType fieldID: &fieldID error: __thriftError]) return NO;"
-      << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if (fieldType == TTypeSTOP) { " << endl;
-  indent_up();
-  indent(out) << "break;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  // Switch statement on the field we are reading
-  indent(out) << "switch (fieldID)" << endl;
-
-  scope_up(out);
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
-    indent_up();
-    indent(out) << "if (fieldType == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-
-    generate_deserialize_field(out, *f_iter, "fieldValue");
-    indent(out) << call_field_setter(*f_iter, "fieldValue") << endl;
-
-    indent_down();
-    out << indent() << "} else { " << endl;
-    if (log_unexpected_) {
-      out << indent() << "  NSLog(@\"%s: field ID %i has unexpected type %i.  Skipping.\", "
-                         "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl;
-    }
-    
-    out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
-    out << indent() << "}" << endl << indent() << "break;" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  out << indent() << "default:" << endl;
-  if (log_unexpected_) {
-    out << indent() << "  NSLog(@\"%s: unexpected field ID %i with type %i.  Skipping.\", "
-                       "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl;
-  }
-
-  out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
-  
-  out << indent() << "  break;" << endl;
-
-  scope_down(out);
-
-  // Read field end marker
-  indent(out) << "if (![inProtocol readFieldEnd: __thriftError]) return NO;" << endl;
-
-  scope_down(out);
-
-  out << indent() << "if (![inProtocol readStructEnd: __thriftError]) return NO;" << endl;
-
-  // performs various checks (e.g. check that all required fields are set)
-  if (validate_required_) {
-    out << indent() << "if (![self validate: __thriftError]) return NO;" << endl;
-  }
-
-  indent(out) << "return YES;" << endl;
-  
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    out << indent() << "if (_" << (*f_iter)->get_name() << "IsSet) {" << endl;
-    indent_up();
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl;
-      indent_up();
-    }
-
-    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name()
-                << "\" type: " << type_to_enum((*f_iter)->get_type())
-                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name());
-
-    // Write field closer
-    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
-
-    if (null_allowed) {
-      scope_down(out);
-    }
-    scope_down(out);
-  }
-  // Write the struct map
-  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl
-      << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl;
-
-  indent(out) << "return YES;" << endl;
-  
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct, which
- * is a function result. These fields are only written if they are
- * set, and only one of them can be set at a time.
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out << endl << indent() << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(_" << (*f_iter)->get_name() << "IsSet) {" << endl;
-    indent_up();
-
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl;
-      indent_up();
-    }
-
-    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name()
-                << "\" type: " << type_to_enum((*f_iter)->get_type())
-                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name());
-
-    // Write field closer
-    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
-
-    if (null_allowed) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-
-    indent_down();
-    indent(out) << "}";
-  }
-  // Write the struct map
-  out << endl << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;"
-      << endl << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;"
-      << endl;
-
-  indent(out) << "return YES;" << endl;
-  
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a function to perform various checks
- * (e.g. check that all required fields are set)
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_validator(ofstream& out, t_struct* tstruct) {
-  out << indent() << "- (BOOL) validate: (NSError *__autoreleasing *)__thriftError {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "// check for required fields" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = (*f_iter);
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      out << indent() << "if (!_" << field->get_name() << "IsSet) ";
-      scope_up(out);
-      indent(out) << "if (__thriftError) ";
-      scope_up(out);
-      out << indent() << "*__thriftError = [NSError errorWithDomain: TProtocolErrorDomain" << endl
-          << indent() << "                                     code: TProtocolErrorUnknown" << endl
-          << indent() << "                                 userInfo: @{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMissingRequiredField)," << endl
-          << indent() << "                                             TProtocolErrorFieldNameKey: @\"" << (*f_iter)->get_name() << "\"}];" << endl;
-      scope_down(out);
-      scope_down(out);
-    }
-  }
-  indent(out) << "return YES;" << endl;
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generate property accessor methods for all fields in the struct.
- * getter, setter, isset getter.
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ofstream& out,
-                                                                             t_struct* tstruct,
-                                                                             bool is_exception) {
-  (void)is_exception;
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = field_name;
-    cap_name[0] = toupper(cap_name[0]);
-
-    // Simple setter
-    indent(out) << "- (void) set" << cap_name << ": (" << type_name(type, false, true) << ") " << field_name
-                << " {" << endl;
-    indent_up();
-    indent(out) << "_" << field_name << " = " << field_name << ";" << endl;
-    indent(out) << "_" << field_name << "IsSet = YES;" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Unsetter - do we need this?
-    indent(out) << "- (void) unset" << cap_name << " {" << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "_" << field_name << " = nil;" << endl;
-    }
-    indent(out) << "_" << field_name << "IsSet = NO;" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates a description method for the given struct
- *
- * @param tstruct The struct definition
- */
-void t_cocoa_generator::generate_cocoa_struct_description(ofstream& out, t_struct* tstruct) {
-  
-  // Allow use of debugDescription so the app can add description via a cateogory/extension
-  if (debug_descriptions_) {
-    out << indent() << "- (NSString *) debugDescription {" << endl;
-  }
-  else {
-    out << indent() << "- (NSString *) description {" << endl;
-  }
-  indent_up();
-
-  out << indent() << "NSMutableString * ms = [NSMutableString stringWithString: @\""
-      << cocoa_prefix_ << tstruct->get_name() << "(\"];" << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      indent(out) << "[ms appendString: @\"" << (*f_iter)->get_name() << ":\"];" << endl;
-    } else {
-      indent(out) << "[ms appendString: @\"," << (*f_iter)->get_name() << ":\"];" << endl;
-    }
-    t_type* ttype = (*f_iter)->get_type();
-    indent(out) << "[ms appendFormat: @\"" << format_string_for_type(ttype) << "\", "
-                << format_cast_for_type(ttype) << "_" << (*f_iter)->get_name() << "];" << endl;
-  }
-  out << indent() << "[ms appendString: @\")\"];" << endl << indent()
-      << "return [NSString stringWithString: ms];" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a thrift service.  In Objective-C this consists of a
- * protocol definition, a client interface and a client implementation.
- *
- * @param tservice The service definition
- */
-void t_cocoa_generator::generate_service(t_service* tservice) {
-  generate_cocoa_service_protocol(f_header_, tservice);
-  generate_cocoa_service_client_interface(f_header_, tservice);
-  generate_cocoa_service_server_interface(f_header_, tservice);
-  generate_cocoa_service_helpers(tservice);
-  generate_cocoa_service_client_implementation(f_impl_, tservice);
-  generate_cocoa_service_server_implementation(f_impl_, tservice);
-  if (async_clients_) {
-    generate_cocoa_service_async_protocol(f_header_, tservice);
-    generate_cocoa_service_client_async_interface(f_header_, tservice);
-    generate_cocoa_service_client_async_implementation(f_impl_, tservice);
-  }
-}
-
-/**
- * Generates structs for all the service return types
- *
- * @param tservice The service
- */
-void t_cocoa_generator::generate_cocoa_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    
-    t_struct* ts = (*f_iter)->get_arglist();
-    
-    string qname = function_args_helper_struct_type(tservice, *f_iter);
-    
-    t_struct qname_ts = t_struct(ts->get_program(), qname);
-
-    const vector<t_field*>& members = ts->get_members();
-    vector<t_field*>::const_iterator m_iter;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      qname_ts.append(*m_iter);
-    }
-    
-    generate_cocoa_struct_interface(f_impl_, &qname_ts, false);
-    generate_cocoa_struct_implementation(f_impl_, &qname_ts, false, false);
-    generate_function_helpers(tservice, *f_iter);
-  }
-}
-
-string t_cocoa_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return tservice->get_name() + "_" + tfunction->get_name();
-  } else {
-    return tservice->get_name() + "_" + tfunction->get_name() + "_result";
-  }
-}
-
-string t_cocoa_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) {
-  return tservice->get_name() + "_" + tfunction->get_name() + "_args";
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_cocoa_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  // create a result struct with a success field of the return type,
-  // and a field for each type of exception thrown
-  t_struct result(program_, function_result_helper_struct_type(tservice, tfunction));
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  // generate the result struct
-  generate_cocoa_struct_interface(f_impl_, &result, false);
-  generate_cocoa_struct_implementation(f_impl_, &result, false, true);
-}
-
-/**
- * Generates a service protocol definition.
- *
- * @param tservice The service to generate a protocol definition for
- */
-void t_cocoa_generator::generate_cocoa_service_protocol(ofstream& out, t_service* tservice) {
-  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << " <NSObject>" << endl;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << "- " << function_signature(*f_iter, true) << ";"
-        << "  // throws ";
-    t_struct* xs = (*f_iter)->get_xceptions();
-    const std::vector<t_field*>& xceptions = xs->get_members();
-    vector<t_field*>::const_iterator x_iter;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      out << type_name((*x_iter)->get_type()) + ", ";
-    }
-    out << "TException" << endl;
-  }
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates an asynchronous service protocol definition.
- *
- * @param tservice The service to generate a protocol definition for
- */
-void t_cocoa_generator::generate_cocoa_service_async_protocol(ofstream& out, t_service* tservice) {
-  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << "Async"
-      << " <NSObject>" << endl;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << "- " << async_function_signature(*f_iter, false) << ";" << endl;
-    if (promise_kit_) {
-      out << "- " << promise_function_signature(*f_iter) << ";" << endl;
-    }
-  }
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates a service client interface definition.
- *
- * @param tservice The service to generate a client interface definition for
- */
-void t_cocoa_generator::generate_cocoa_service_client_interface(ofstream& out,
-                                                                t_service* tservice) {
-  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "Client : TBaseClient <"
-      << cocoa_prefix_ << tservice->get_name() << "> " << endl;
-
-  out << "- (id) initWithProtocol: (id <TProtocol>) protocol;" << endl;
-  out << "- (id) initWithInProtocol: (id <TProtocol>) inProtocol outProtocol: (id <TProtocol>) "
-         "outProtocol;" << endl;
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates a service client interface definition.
- *
- * @param tservice The service to generate a client interface definition for
- */
-void t_cocoa_generator::generate_cocoa_service_client_async_interface(ofstream& out,
-                                                                      t_service* tservice) {
-  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "ClientAsync : TBaseClient <"
-      << cocoa_prefix_ << tservice->get_name() << "Async> " << endl
-      << endl;
-
-  out << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) protocolFactory "
-      << "transportFactory: (id <TAsyncTransportFactory>) transportFactory;" << endl;
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates a service server interface definition. In other words, the TProcess implementation for
- *the
- * service definition.
- *
- * @param tservice The service to generate a client interface definition for
- */
-void t_cocoa_generator::generate_cocoa_service_server_interface(ofstream& out,
-                                                                t_service* tservice) {
-  out << "@interface " << cocoa_prefix_ << tservice->get_name()
-      << "Processor : NSObject <TProcessor> " << endl;
-
-  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_
-      << tservice->get_name() << ">) service;" << endl;
-  out << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service;" << endl;
-
-  out << "@end" << endl << endl;
-}
-
-void t_cocoa_generator::generate_cocoa_service_client_send_function_implementation(
-    ofstream& out,
-    t_service *tservice,
-    t_function* tfunction,
-    bool needs_protocol) {
-  string funname = tfunction->get_name();
-
-  t_function send_function(g_type_bool,
-                           string("send_") + tfunction->get_name(),
-                           tfunction->get_arglist());
-
-  string argsname = function_args_helper_struct_type(tservice, tfunction);
-
-  // Open function
-  indent(out) << "- (BOOL) send_" << tfunction->get_name() << argument_list(tfunction->get_arglist(), needs_protocol ? "outProtocol" : "", true) << endl;
-  scope_up(out);
-  
-  // Serialize the request
-  out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\""
-      << (tfunction->is_oneway() ? " type: TMessageTypeONEWAY" : " type: TMessageTypeCALL")
-      << " sequenceID: 0 error: __thriftError]) return NO;" << endl;
-
-  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << argsname
-                  << "\" error: __thriftError]) return NO;" << endl;
-
-  // write out function parameters
-  t_struct* arg_struct = tfunction->get_arglist();
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator fld_iter;
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-    string fieldName = (*fld_iter)->get_name();
-    if (type_can_be_null((*fld_iter)->get_type())) {
-      out << indent() << "if (" << fieldName << " != nil)";
-      scope_up(out);
-    }
-    out << indent() << "if (![outProtocol writeFieldBeginWithName: @\"" << fieldName
-        << "\""
-           " type: " << type_to_enum((*fld_iter)->get_type())
-        << " fieldID: " << (*fld_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
-
-    generate_serialize_field(out, *fld_iter, fieldName);
-
-    out << indent() << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
-
-    if (type_can_be_null((*fld_iter)->get_type())) {
-      indent_down();
-      out << indent() << "}" << endl;
-    }
-  }
-
-  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl;
-  out << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl;
-  out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
-  out << indent() << "return YES;" << endl;
-  scope_down(out);
-  out << endl;
-}
-
-void t_cocoa_generator::generate_cocoa_service_client_recv_function_implementation(
-    ofstream& out,
-    t_service* tservice,
-    t_function* tfunction,
-    bool needs_protocol) {
-
-  
-  // Open function
-  indent(out) << "- (BOOL) recv_" << tfunction->get_name();
-  if (!tfunction->get_returntype()->is_void()) {
-    out << ": (" << type_name(tfunction->get_returntype(), false, true) << " *) result ";
-    if (needs_protocol) {
-      out << "protocol";
-    } else {
-      out << "error";
-    }
-  }
-  if (needs_protocol) {
-    out << ": (id<TProtocol>) inProtocol error";
-  }
-  out << ": (NSError *__autoreleasing *)__thriftError" << endl;
-  scope_up(out);
-
-  // TODO(mcslee): Message validation here, was the seqid etc ok?
-
-  // check for an exception
-  out << indent() << "NSError *incomingException = [self checkIncomingMessageException: inProtocol];" << endl
-      << indent() << "if (incomingException)";
-  scope_up(out);
-  out << indent() << "if (__thriftError)";
-  scope_up(out);
-  out << indent() << "*__thriftError = incomingException;" << endl;
-  scope_down(out);
-  out << indent() << "return NO;" << endl;
-  scope_down(out);
-
-  // FIXME - could optimize here to reduce creation of temporary objects.
-  string resultname = function_result_helper_struct_type(tservice, tfunction);
-  out << indent() << cocoa_prefix_ << resultname << " * resulter = [" << cocoa_prefix_ << resultname << " new];" << endl;
-  indent(out) << "if (![resulter read: inProtocol error: __thriftError]) return NO;" << endl;
-  indent(out) << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
-
-  // Careful, only return _result if not a void function
-  if (!tfunction->get_returntype()->is_void()) {
-    out << indent() << "if (resulter.successIsSet)";
-    scope_up(out);
-    out << indent() << "*result = resulter.success;" << endl;
-    out << indent() << "return YES;" << endl;
-    scope_down(out);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-    out << indent() << "if (resulter." << (*x_iter)->get_name() << "IsSet)";
-    scope_up(out);
-    out << indent() << "if (__thriftError)";
-    scope_up(out);
-    out << indent() << "*__thriftError = [resulter " << (*x_iter)->get_name() << "];" << endl;
-    scope_down(out);
-    out << indent() << "return NO;" << endl;
-    scope_down(out);
-  }
-
-  // If you get here it's an exception, unless a void function
-  if (tfunction->get_returntype()->is_void()) {
-    indent(out) << "return YES;" << endl;
-  } else {
-    out << indent() << "if (__thriftError)";
-    scope_up(out);
-    out << indent() << "*__thriftError = [NSError errorWithDomain: TApplicationErrorDomain" << endl
-        << indent() << "                                     code: TApplicationErrorMissingResult" << endl
-        << indent() << "                                 userInfo: @{TApplicationErrorMethodKey: @\""
-        << tfunction->get_name() << "\"}];" << endl;
-    scope_down(out);
-    out << indent() << "return NO;" << endl;
-  }
-
-  // Close function
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generates an invocation of a given 'send_' function.
- *
- * @param tfunction The service to generate an implementation for
- */
-void t_cocoa_generator::generate_cocoa_service_client_send_function_invocation(
-                                                                               ofstream& out,
-                                                                               t_function* tfunction) {
-  
-  t_struct* arg_struct = tfunction->get_arglist();
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator fld_iter;
-  out << indent() << "if (![self send_" << tfunction->get_name();
-  bool first = true;
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-    string fieldName = (*fld_iter)->get_name();
-    out << " ";
-    if (first) {
-      first = false;
-      out << ": " << fieldName;
-    } else {
-      out << fieldName << ": " << fieldName;
-    }
-  }
-  if (!fields.empty()) {
-    out << " error";
-  }
-  out << ": __thriftError]) " << invalid_return_statement(tfunction) << endl;
-}
-
-/**
- * Generates an invocation of a given 'send_' function.
- *
- * @param tfunction The service to generate an implementation for
- */
-void t_cocoa_generator::generate_cocoa_service_client_send_async_function_invocation(
-                                                                                     ofstream& out,
-                                                                                     t_function* tfunction,
-                                                                                     string failureBlockName) {
-  
-  t_struct* arg_struct = tfunction->get_arglist();
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator fld_iter;
-  out << indent() << "if (![self send_" << tfunction->get_name();
-  bool first = true;
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-    string fieldName = (*fld_iter)->get_name();
-    out << " ";
-    if (first) {
-      first = false;
-      out << ": " << fieldName;
-    } else {
-      out << fieldName << ": " << fieldName;
-    }
-  }
-  if (!fields.empty()) {
-    out << " protocol";
-  }
-  out << ": protocol error: &thriftError]) ";
-  scope_up(out);
-  out << indent() << failureBlockName << "(thriftError);" << endl
-      << indent() << "return;" << endl;
-  scope_down(out);
-}
-
-/**
- * Generates a service client implementation.
- *
- * @param tservice The service to generate an implementation for
- */
-void t_cocoa_generator::generate_cocoa_service_client_implementation(ofstream& out,
-                                                                     t_service* tservice) {
-  
-  string name = cocoa_prefix_ + tservice->get_name() + "Client";
-  
-  out << "@interface " << name << " () ";
-  scope_up(out);
-  out << endl;
-  out << indent() << "id<TProtocol> inProtocol;" << endl;
-  out << indent() << "id<TProtocol> outProtocol;" << endl;
-  out << endl;
-  scope_down(out);
-  out << endl;
-  out << "@end" << endl << endl;
-  
-  out << "@implementation " << name << endl;
-
-  // initializers
-  out << "- (id) initWithProtocol: (id <TProtocol>) protocol" << endl;
-  scope_up(out);
-  out << indent() << "return [self initWithInProtocol: protocol outProtocol: protocol];" << endl;
-  scope_down(out);
-  out << endl;
-
-  out << "- (id) initWithInProtocol: (id <TProtocol>) anInProtocol outProtocol: (id <TProtocol>) "
-         "anOutProtocol" << endl;
-  scope_up(out);
-  out << indent() << "self = [super init];" << endl;
-  out << indent() << "if (self) ";
-  scope_up(out);
-  out << indent() << "inProtocol = anInProtocol;" << endl;
-  out << indent() << "outProtocol = anOutProtocol;" << endl;
-  scope_down(out);
-  out << indent() << "return self;" << endl;
-  scope_down(out);
-  out << endl;
-
-  // generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-
-    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, false);
-
-    if (!(*f_iter)->is_oneway()) {
-      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, false);
-    }
-
-    // Open function
-    indent(out) << "- " << function_signature(*f_iter, true) << endl;
-    scope_up(out);
-    generate_cocoa_service_client_send_function_invocation(out, *f_iter);
-
-    out << indent() << "if (![[outProtocol transport] flush: __thriftError]) " << invalid_return_statement(*f_iter) << endl;
-    if (!(*f_iter)->is_oneway()) {
-      if ((*f_iter)->get_returntype()->is_void()) {
-        out << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": __thriftError]) return NO;" << endl;
-        out << indent() << "return YES;" << endl;
-      } else {
-        out << indent() << type_name((*f_iter)->get_returntype(), false, true) << " __result;" << endl
-            << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": &__result error: __thriftError]) "
-            << invalid_return_statement(*f_iter) << endl;
-        if (type_can_be_null((*f_iter)->get_returntype())) {
-          out << indent() << "return __result;" << endl;
-        } else {
-          out << indent() << "return @(__result);" << endl;
-        }
-      }
-    }
-    else {
-      out << indent() << "return YES;" << endl;
-    }
-    scope_down(out);
-    out << endl;
-  }
-
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates a service client implementation for its asynchronous interface.
- *
- * @param tservice The service to generate an implementation for
- */
-void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ofstream& out,
-                                                                           t_service* tservice) {
-  
-  string name = cocoa_prefix_ + tservice->get_name() + "ClientAsync";
-
-  out << "@interface " << name << " () ";
-  scope_up(out);
-  out << endl;
-  out << indent() << "id<TProtocolFactory> protocolFactory;" << endl;
-  out << indent() << "id<TAsyncTransportFactory> transportFactory;" << endl;
-  out << endl;
-  scope_down(out);
-  out << endl;
-  out << "@end" << endl << endl;
-  
-  
-  out << "@implementation " << name << endl
-      << endl << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) aProtocolFactory "
-                 "transportFactory: (id <TAsyncTransportFactory>) aTransportFactory;" << endl;
-
-  scope_up(out);
-  out << indent() << "self = [super init];" << endl;
-  out << indent() << "if (self) {" << endl;
-  out << indent() << "  protocolFactory = aProtocolFactory;" << endl;
-  out << indent() << "  transportFactory = aTransportFactory;" << endl;
-  out << indent() << "}" << endl;
-  out << indent() << "return self;" << endl;
-  scope_down(out);
-  out << endl;
-
-  // generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-
-    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, true);
-
-    if (!(*f_iter)->is_oneway()) {
-      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, true);
-    }
-
-    // Open function
-    indent(out) << "- " << async_function_signature(*f_iter, false) << endl;
-    scope_up(out);
-    
-    out << indent() << "NSError *thriftError;" << endl
-        << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl
-        << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl
-        << endl;
-    
-    generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "failureBlock");
-
-    out << indent() << "[transport flushWithCompletion:^{" << endl;
-    indent_up();
-
-    if (!(*f_iter)->is_oneway()) {
-      out << indent() << "NSError *thriftError;" << endl;
-      
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl;
-      }
-      out << indent() << "if (![self recv_" << (*f_iter)->get_name();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        out << ": &result protocol";
-      }
-      out << ": protocol error: &thriftError]) ";
-      scope_up(out);
-      out << indent() << "failureBlock(thriftError);" << endl
-          << indent() << "return;" << endl;
-      scope_down(out);
-    }
-    
-    out << indent() << "responseBlock(";
-    if (!(*f_iter)->is_oneway() && !(*f_iter)->get_returntype()->is_void()) {
-      out << "result";
-    }
-    out << ");" << endl;
-
-    indent_down();
-    
-    out << indent() << "} failure:failureBlock];" << endl;
-    
-    scope_down(out);
-
-    out << endl;
-    
-    // Promise function
-    if (promise_kit_) {
-      
-      indent(out) << "- " << promise_function_signature(*f_iter) << endl;
-      scope_up(out);
-      
-      out << indent() << "return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {" << endl;
-      indent_up();
-      
-      out << indent() << "NSError *thriftError;" << endl
-          << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl
-          << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl
-          << endl;
-      
-      generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "resolver");
-      
-      out << indent() << "[transport flushWithCompletion:^{" << endl;
-      indent_up();
-      
-      if (!(*f_iter)->is_oneway()) {
-        out << indent() << "NSError *thriftError;" << endl;
-        
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl;
-        }
-        out << indent() << "if (![self recv_" << (*f_iter)->get_name();
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          out << ": &result protocol";
-        }
-        out << ": protocol error: &thriftError]) ";
-        scope_up(out);
-        out << indent() << "resolver(thriftError);" << endl
-            << indent() << "return;" << endl;
-        scope_down(out);
-      }
-      
-      out << indent() << "resolver(";
-      if ((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void()) {
-        out << "@YES";
-      } else if (type_can_be_null((*f_iter)->get_returntype())) {
-        out << "result";
-      } else {
-        out << "@(result)";
-      }
-      out << ");" << endl;
-      
-      indent_down();
-      
-      out << indent() << "} failure:^(NSError *error) {" << endl;
-      indent_up();
-      out << indent() << "resolver(error);" << endl;
-      indent_down();
-      out << indent() << "}];" << endl;
-      
-      indent_down();
-      out << indent() << "}];" << endl;
-      
-      scope_down(out);
-      
-      out << endl;
-      
-    }
-    
-  }
-
-  out << "@end" << endl << endl;
-}
-
-/**
- * Generates a service server implementation.  In other words the actual TProcessor implementation
- * for the service.
- *
- * @param tservice The service to generate an implementation for
- */
-void t_cocoa_generator::generate_cocoa_service_server_implementation(ofstream& out,
-                                                                     t_service* tservice) {
-  
-  string name = cocoa_prefix_ + tservice->get_name() + "Processor";
-  
-  out << "@interface " << name << " () ";
-  
-  scope_up(out);
-  out << indent() << "id <" << cocoa_prefix_ << tservice->get_name() << "> service;" << endl;
-  out << indent() << "NSDictionary * methodMap;" << endl;
-  scope_down(out);
-  
-  out << "@end" << endl << endl;
-  
-  out << "@implementation " << name << endl;
-
-  // initializer
-  out << endl;
-  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ << tservice->get_name() << ">) aService" << endl;
-  scope_up(out);
-  out << indent() << "self = [super init];" << endl;
-  out << indent() << "if (self) ";
-  scope_up(out);
-  out << indent() << "service = aService;" << endl;
-  out << indent() << "methodMap = [NSMutableDictionary dictionary];" << endl;
-
-  // generate method map for routing incoming calls
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-    scope_up(out);
-    out << indent() << "SEL s = @selector(process_" << funname << "_withSequenceID:inProtocol:outProtocol:error:);" << endl;
-    out << indent() << "NSMethodSignature * sig = [self methodSignatureForSelector: s];" << endl;
-    out << indent() << "NSInvocation * invocation = [NSInvocation invocationWithMethodSignature: sig];" << endl;
-    out << indent() << "[invocation setSelector: s];" << endl;
-    out << indent() << "[invocation retainArguments];" << endl;
-    out << indent() << "[methodMap setValue: invocation forKey: @\"" << funname << "\"];" << endl;
-    scope_down(out);
-  }
-  scope_down(out);
-  out << indent() << "return self;" << endl;
-  scope_down(out);
-
-  // implementation of the 'service' method which returns the service associated with this
-  // processor
-  out << endl;
-  out << indent() << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service" << endl;
-  out << indent() << "{" << endl;
-  out << indent() << "  return service;" << endl;
-  out << indent() << "}" << endl;
-
-  // implementation of the TProcess method, which dispatches the incoming call using the method map
-  out << endl;
-  out << indent() << "- (BOOL) processOnInputProtocol: (id <TProtocol>) inProtocol" << endl;
-  out << indent() << "                 outputProtocol: (id <TProtocol>) outProtocol" << endl;
-  out << indent() << "                          error: (NSError *__autoreleasing *)__thriftError" << endl;
-  out << indent() << "{" << endl;
-  out << indent() << "  NSString * messageName;" << endl;
-  out << indent() << "  SInt32 messageType;" << endl;
-  out << indent() << "  SInt32 seqID;" << endl;
-  out << indent() << "  if (![inProtocol readMessageBeginReturningName: &messageName" << endl;
-  out << indent() << "                                       type: &messageType" << endl;
-  out << indent() << "                                 sequenceID: &seqID" << endl;
-  out << indent() << "                                      error: __thriftError]) return NO;" << endl;
-  out << indent() << "  NSInvocation * invocation = [methodMap valueForKey: messageName];" << endl;
-  out << indent() << "  if (invocation == nil) {" << endl;
-  out << indent() << "    if (![TProtocolUtil skipType: TTypeSTRUCT onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
-  out << indent() << "    if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
-  out << indent() << "    NSError * x = [NSError errorWithDomain: TApplicationErrorDomain" << endl;
-  out << indent() << "                                      code: TApplicationErrorUnknownMethod" << endl;
-  out << indent() << "                                  userInfo: @{TApplicationErrorMethodKey: messageName}];" << endl;
-  out << indent() << "    if (![outProtocol writeMessageBeginWithName: messageName" << endl;
-  out << indent() << "                                           type: TMessageTypeEXCEPTION" << endl;
-  out << indent() << "                                     sequenceID: seqID" << endl;
-  out << indent() << "                                          error: __thriftError]) return NO;" << endl;
-  out << indent() << "    if (![x write: outProtocol error: __thriftError]) return NO;" << endl;
-  out << indent() << "    if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
-  out << indent() << "    if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl;
-  out << indent() << "    return YES;" << endl;
-  out << indent() << "  }" << endl;
-  out << indent() << "  // NSInvocation does not conform to NSCopying protocol" << endl;
-  out << indent() << "  NSInvocation * i = [NSInvocation invocationWithMethodSignature: "
-                     "[invocation methodSignature]];" << endl;
-  out << indent() << "  [i setSelector: [invocation selector]];" << endl;
-  out << indent() << "  [i setArgument: &seqID atIndex: 2];" << endl;
-  out << indent() << "  [i setArgument: &inProtocol atIndex: 3];" << endl;
-  out << indent() << "  [i setArgument: &outProtocol atIndex: 4];" << endl;
-  out << indent() << "  [i setArgument: &__thriftError atIndex: 5];" << endl;
-  out << indent() << "  [i setTarget: self];" << endl;
-  out << indent() << "  [i invoke];" << endl;
-  out << indent() << "  return YES;" << endl;
-  out << indent() << "}" << endl;
-
-  // generate a process_XXXX method for each service function, which reads args, calls the service,
-  // and writes results
-  functions = tservice->get_functions();
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << endl;
-    string funname = (*f_iter)->get_name();
-    out << indent() << "- (BOOL) process_" << funname
-        << "_withSequenceID: (SInt32) seqID inProtocol: (id<TProtocol>) inProtocol outProtocol: "
-           "(id<TProtocol>) outProtocol error:(NSError *__autoreleasing *)__thriftError" << endl;
-    scope_up(out);
-    string argstype = cocoa_prefix_ + function_args_helper_struct_type(tservice, *f_iter);
-    out << indent() << argstype << " * args = [" << argstype << " new];" << endl;
-    out << indent() << "if (![args read: inProtocol error: __thriftError]) return NO;" << endl;
-    out << indent() << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
-
-    // prepare the result if not oneway
-    if (!(*f_iter)->is_oneway()) {
-      string resulttype = cocoa_prefix_ + function_result_helper_struct_type(tservice, *f_iter);
-      out << indent() << resulttype << " * result = [" << resulttype << " new];" << endl;
-    }
-
-    // make the call to the actual service object
-    out << indent();
-    if ((*f_iter)->get_returntype()->is_void()) {
-      out << "BOOL";
-    } else if (type_can_be_null((*f_iter)->get_returntype())) {
-      out << type_name((*f_iter)->get_returntype(), false, true);
-    } else {
-      out << "NSNumber *";
-    }
-    out << " serviceResult = ";
-    if ((*f_iter)->get_returntype()->get_true_type()->is_container()) {
-      out << "(" << type_name((*f_iter)->get_returntype(), false, true) << ")";
-    }
-    out << "[service " << funname;
-    // supplying arguments
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      string fieldName = (*fld_iter)->get_name();
-      if (first) {
-        first = false;
-        out << ": [args " << fieldName << "]";
-      } else {
-        out << " " << fieldName << ": [args " << fieldName << "]";
-      }
-    }
-    if (!fields.empty()) {
-      out << " error";
-    }
-    out << ": __thriftError];" << endl;
-    out << indent() << "if (!serviceResult) return NO;" << endl;
-    if (!(*f_iter)->get_returntype()->is_void()) {
-      out << indent() << "[result setSuccess: " << unbox((*f_iter)->get_returntype(), "serviceResult") << "];" << endl;
-    }
-    
-    // write out the result if not oneway
-    if (!(*f_iter)->is_oneway()) {
-      out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" << endl;
-      out << indent() << "                                       type: TMessageTypeREPLY" << endl;
-      out << indent() << "                                 sequenceID: seqID" << endl;
-      out << indent() << "                                      error: __thriftError]) return NO;" << endl;
-      out << indent() << "if (![result write: outProtocol error: __thriftError]) return NO;" << endl;
-      out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
-      out << indent() << "if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl;
-    }
-    out << indent() << "return YES;" << endl;
-
-    scope_down(out);
-  }
-
-  out << "@end" << endl << endl;
-}
-
-/**
- * Deserializes a field of any type.
- *
- * @param tfield The field
- * @param fieldName The variable name for this field
- */
-void t_cocoa_generator::generate_deserialize_field(ofstream& out,
-                                                   t_field* tfield,
-                                                   string fieldName) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, fieldName);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, fieldName);
-  } else if (type->is_base_type() || type->is_enum()) {
-    indent(out) << type_name(type) << " " << fieldName << ";" << endl;
-    indent(out) << "if (![inProtocol ";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + tfield->get_name();
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "readBinary:&" << fieldName << " error: __thriftError]";
-        } else {
-          out << "readString:&" << fieldName << " error: __thriftError]";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool:&" << fieldName << " error: __thriftError]";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte:(UInt8 *)&" << fieldName << " error: __thriftError]";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16:&" << fieldName << " error: __thriftError]";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32:&" << fieldName << " error: __thriftError]";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64:&" << fieldName << " error: __thriftError]";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble:&" << fieldName << " error: __thriftError]";
-        break;
-      default:
-        throw "compiler error: no Objective-C name for base type "
-            + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32:&" << fieldName << " error: __thriftError]";
-    }
-    out << ") return NO;" << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a struct, allocates the struct and invokes read:
- */
-void t_cocoa_generator::generate_deserialize_struct(ofstream& out,
-                                                    t_struct* tstruct,
-                                                    string fieldName) {
-  indent(out) << type_name(tstruct) << fieldName << " = [[" << type_name(tstruct, true)
-              << " alloc] init];" << endl;
-  indent(out) << "if (![" << fieldName << " read: inProtocol error: __thriftError]) return NO;" << endl;
-}
-
-/**
- * Deserializes a container by reading its size and then iterating
- */
-void t_cocoa_generator::generate_deserialize_container(ofstream& out,
-                                                       t_type* ttype,
-                                                       string fieldName) {
-  string size = tmp("_size");
-  indent(out) << "SInt32 " << size << ";" << endl;
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    indent(out) << "if (![inProtocol readMapBeginReturningKeyType: NULL valueType: NULL size: &" << size << " error: __thriftError]) return NO;" << endl;
-    indent(out) << "NSMutableDictionary * " << fieldName
-                << " = [[NSMutableDictionary alloc] initWithCapacity: " << size << "];" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "if (![inProtocol readSetBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;"
-                << endl;
-    indent(out) << "NSMutableSet * " << fieldName
-                << " = [[NSMutableSet alloc] initWithCapacity: " << size << "];" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "if (![inProtocol readListBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;"
-                << endl;
-    indent(out) << "NSMutableArray * " << fieldName
-                << " = [[NSMutableArray alloc] initWithCapacity: " << size << "];" << endl;
-  }
-  // FIXME - the code above does not verify that the element types of
-  // the conta

<TRUNCATED>

[50/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_as3_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_as3_generator.cc b/compiler/cpp/src/generate/t_as3_generator.cc
deleted file mode 100644
index 67beaf6..0000000
--- a/compiler/cpp/src/generate/t_as3_generator.cc
+++ /dev/null
@@ -1,2594 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <sstream>
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <cctype>
-
-#include <sys/stat.h>
-#include <stdexcept>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * AS3 code generator.
- *
- */
-class t_as3_generator : public t_oop_generator {
-public:
-  t_as3_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    bindable_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("bindable") == 0) {
-        bindable_ = true;
-      } else {
-        throw "unknown option as3:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-as3";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(std::ofstream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool in_static,
-                         bool defval = false);
-  std::string render_const_value(ofstream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_as3_struct(t_struct* tstruct, bool is_exception);
-
-  void generate_as3_struct_definition(std::ofstream& out,
-                                      t_struct* tstruct,
-                                      bool is_xception = false,
-                                      bool in_class = false,
-                                      bool is_result = false);
-  // removed -- equality,compare_to
-  void generate_as3_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_struct_tostring(std::ofstream& out, t_struct* tstruct, bool bindable);
-  void generate_as3_meta_data_map(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
-  std::string get_as3_type_string(t_type* type);
-  void generate_reflection_setters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_reflection_getters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_bean_boilerplate(std::ofstream& out, t_struct* tstruct, bool bindable);
-
-  void generate_function_helpers(t_function* tfunction);
-  std::string get_cap_name(std::string name);
-  std::string generate_isset_check(t_field* field);
-  std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
-  // removed std::string isset_field_id(t_field* field);
-
-  void generate_service_interface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_as3_doc(std::ofstream& out, t_doc* tdoc);
-
-  void generate_as3_doc(std::ofstream& out, t_function* tdoc);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string as3_package();
-  std::string as3_type_imports();
-  std::string as3_thrift_imports();
-  std::string as3_thrift_gen_imports(t_struct* tstruct, string& imports);
-  std::string as3_thrift_gen_imports(t_service* tservice);
-  std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false);
-  std::string base_type_name(t_base_type* tbase, bool in_container = false);
-  std::string declare_field(t_field* tfield, bool init = false);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string get_enum_class_name(t_type* type);
-
-  bool type_can_be_null(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
-           || ttype->is_string();
-  }
-
-  std::string constant_name(std::string name);
-
-private:
-  /**
-   * File streams
-   */
-
-  std::string package_name_;
-  std::ofstream f_service_;
-  std::string package_dir_;
-
-  bool bindable_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_as3_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  package_name_ = program_->get_namespace("as3");
-
-  string dir = package_name_;
-  string subdir = get_out_dir();
-  string::size_type loc;
-  while ((loc = dir.find(".")) != string::npos) {
-    subdir = subdir + "/" + dir.substr(0, loc);
-    MKDIR(subdir.c_str());
-    dir = dir.substr(loc + 1);
-  }
-  if (dir.size() > 0) {
-    subdir = subdir + "/" + dir;
-    MKDIR(subdir.c_str());
-  }
-
-  package_dir_ = subdir;
-}
-
-/**
- * Packages the generated file
- *
- * @return String of the package, i.e. "package org.apache.thriftdemo;"
- */
-string t_as3_generator::as3_package() {
-  if (!package_name_.empty()) {
-    return string("package ") + package_name_ + " ";
-  }
-  return "package ";
-}
-
-/**
- * Prints standard as3 imports
- *
- * @return List of imports for As3 types that are used in here
- */
-string t_as3_generator::as3_type_imports() {
-  return string() + "import org.apache.thrift.Set;\n" + "import flash.utils.ByteArray;\n"
-         + "import flash.utils.Dictionary;\n\n";
-}
-
-/**
- * Prints standard as3 imports
- *
- * @return List of imports necessary for thrift
- */
-string t_as3_generator::as3_thrift_imports() {
-  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
-         + "import org.apache.thrift.protocol.*;\n\n";
-}
-
-/**
- * Prints imports needed for a given type
- *
- * @return List of imports necessary for a given t_struct
- */
-string t_as3_generator::as3_thrift_gen_imports(t_struct* tstruct, string& imports) {
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  // For each type check if it is from a differnet namespace
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_program* program = (*m_iter)->get_type()->get_program();
-    if (program != NULL && program != program_) {
-      string package = program->get_namespace("as3");
-      if (!package.empty()) {
-        if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) {
-          imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n");
-        }
-      }
-    }
-  }
-  return imports;
-}
-
-/**
- * Prints imports needed for a given type
- *
- * @return List of imports necessary for a given t_service
- */
-string t_as3_generator::as3_thrift_gen_imports(t_service* tservice) {
-  string imports;
-  const vector<t_function*>& functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-
-  // For each type check if it is from a differnet namespace
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_program* program = (*f_iter)->get_returntype()->get_program();
-    if (program != NULL && program != program_) {
-      string package = program->get_namespace("as3");
-      if (!package.empty()) {
-        if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) {
-          imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name()
-                         + ";\n");
-        }
-      }
-    }
-
-    as3_thrift_gen_imports((*f_iter)->get_arglist(), imports);
-    as3_thrift_gen_imports((*f_iter)->get_xceptions(), imports);
-  }
-
-  return imports;
-}
-
-/**
- * Nothing in As3
- */
-void t_as3_generator::close_generator() {
-}
-
-/**
- * Generates a typedef. This is not done in As3, since it does
- * not support arbitrary name replacements, and it'd be a wacky waste
- * of overhead to make wrapper classes.
- *
- * @param ttypedef The type definition
- */
-void t_as3_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Enums are a class with a set of static constants.
- *
- * @param tenum The enumeration
- */
-void t_as3_generator::generate_enum(t_enum* tenum) {
-  // Make output file
-  string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".as";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
-
-  // Comment and package it
-  f_enum << autogen_comment() << as3_package() << endl;
-
-  scope_up(f_enum);
-  // Add as3 imports
-  f_enum << string() + "import org.apache.thrift.Set;" << endl << "import flash.utils.Dictionary;"
-         << endl;
-
-  indent(f_enum) << "public class " << tenum->get_name() << " ";
-  scope_up(f_enum);
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << "public static const " << (*c_iter)->get_name() << ":int = " << value << ";"
-                   << endl;
-  }
-
-  // Create a static Set with all valid values for this enum
-  f_enum << endl;
-
-  indent(f_enum) << "public static const VALID_VALUES:Set = new Set(";
-  indent_up();
-  bool firstValue = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    // populate set
-    f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name();
-    firstValue = false;
-  }
-  indent_down();
-  f_enum << ");" << endl;
-
-  indent(f_enum) << "public static const VALUES_TO_NAMES:Dictionary = new Dictionary();" << endl;
-
-  scope_up(f_enum);
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    indent(f_enum) << "VALUES_TO_NAMES[" << (*c_iter)->get_name() << "] = \""
-                   << (*c_iter)->get_name() << "\";" << endl;
-  }
-  f_enum << endl;
-
-  scope_down(f_enum);
-
-  scope_down(f_enum); // end class
-
-  scope_down(f_enum); // end package
-
-  f_enum.close();
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_as3_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-
-  string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.as";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  // Print header
-  f_consts << autogen_comment() << as3_package();
-
-  scope_up(f_consts);
-  f_consts << endl;
-
-  f_consts << as3_type_imports();
-
-  indent(f_consts) << "public class " << program_name_ << "Constants {" << endl << endl;
-  indent_up();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    print_const_value(f_consts,
-                      (*c_iter)->get_name(),
-                      (*c_iter)->get_type(),
-                      (*c_iter)->get_value(),
-                      false);
-  }
-  indent_down();
-  indent(f_consts) << "}" << endl;
-  scope_down(f_consts);
-  f_consts.close();
-}
-
-void t_as3_generator::print_const_value(std::ofstream& out,
-                                        string name,
-                                        t_type* type,
-                                        t_const_value* value,
-                                        bool in_static,
-                                        bool defval) {
-  type = get_true_type(type);
-
-  indent(out);
-  if (!defval) {
-    out << (in_static ? "var " : "public static const ");
-  }
-  if (type->is_base_type()) {
-    string v2 = render_const_value(out, name, type, value);
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = " << v2 << ";" << endl << endl;
-  } else if (type->is_enum()) {
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = " << value->get_integer() << ";" << endl << endl;
-  } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
-        << endl;
-    if (!in_static) {
-      indent(out) << "{" << endl;
-      indent_up();
-      indent(out) << "new function():void {" << endl;
-      indent_up();
-    }
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(out, name, field_type, v_iter->second);
-      indent(out) << name << ".";
-      out << v_iter->first->get_string() << " = " << val << ";" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}();" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_map()) {
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "{" << endl;
-      indent_up();
-      indent(out) << "new function():void {" << endl;
-      indent_up();
-    }
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, name, ktype, v_iter->first);
-      string val = render_const_value(out, name, vtype, v_iter->second);
-      indent(out) << name << "[" << key << "] = " << val << ";" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}();" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_list() || type->is_set()) {
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "{" << endl;
-      indent_up();
-      indent(out) << "new function():void {" << endl;
-      indent_up();
-    }
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      indent(out) << name << "." << (type->is_list() ? "push" : "add") << "(" << val << ");"
-                  << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}();" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else {
-    throw "compiler error: no const of type " + type->get_name();
-  }
-}
-
-string t_as3_generator::render_const_value(ofstream& out,
-                                           string name,
-                                           t_type* type,
-                                           t_const_value* value) {
-  (void)name;
-  type = get_true_type(type);
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-      render << "(byte)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I16:
-      render << "(short)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << value->get_integer() << "L";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << "(double)" << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << value->get_integer();
-  } else {
-    string t = tmp("tmp");
-    print_const_value(out, t, type, value, true);
-    render << t;
-  }
-
-  return render.str();
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is a class
- * with data members, read(), write(), and an inner Isset class.
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_struct(t_struct* tstruct) {
-  generate_as3_struct(tstruct, false);
-}
-
-/**
- * Exceptions are structs, but they inherit from Exception
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_xception(t_struct* txception) {
-  generate_as3_struct(txception, true);
-}
-
-/**
- * As3 struct definition.
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_struct(t_struct* tstruct, bool is_exception) {
-  // Make output file
-  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".as";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << as3_package();
-
-  scope_up(f_struct);
-  f_struct << endl;
-
-  string imports;
-
-  f_struct << as3_type_imports() << as3_thrift_imports() << as3_thrift_gen_imports(tstruct, imports)
-           << endl;
-
-  if (bindable_ && !is_exception) {
-    f_struct << "import flash.events.Event;" << endl << "import flash.events.EventDispatcher;"
-             << endl << "import mx.events.PropertyChangeEvent;" << endl;
-  }
-
-  generate_as3_struct_definition(f_struct, tstruct, is_exception);
-
-  scope_down(f_struct); // end of package
-  f_struct.close();
-}
-
-/**
- * As3 struct definition. This has various parameters, as it could be
- * generated standalone or inside another class as a helper. If it
- * is a helper than it is a static class.
- *
- * @param tstruct      The struct definition
- * @param is_exception Is this an exception?
- * @param in_class     If inside a class, needs to be static class
- * @param is_result    If this is a result it needs a different writer
- */
-void t_as3_generator::generate_as3_struct_definition(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_exception,
-                                                     bool in_class,
-                                                     bool is_result) {
-  generate_as3_doc(out, tstruct);
-
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-  bool bindable = !is_exception && !in_class && bindable_;
-
-  indent(out) << (in_class ? "" : "public ") << (is_final ? "final " : "") << "class "
-              << tstruct->get_name() << " ";
-
-  if (is_exception) {
-    out << "extends Error ";
-  } else if (bindable) {
-    out << "extends EventDispatcher ";
-  }
-  out << "implements TBase ";
-
-  scope_up(out);
-
-  indent(out) << "private static const STRUCT_DESC:TStruct = new TStruct(\"" << tstruct->get_name()
-              << "\");" << endl;
-
-  // Members are public for -as3, private for -as3bean
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "private static const " << constant_name((*m_iter)->get_name())
-                << "_FIELD_DESC:TField = new TField(\"" << (*m_iter)->get_name() << "\", "
-                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");"
-                << endl;
-  }
-
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_as3_doc(out, *m_iter);
-    indent(out) << "private var _" << (*m_iter)->get_name() + ":" + type_name((*m_iter)->get_type())
-                << ";" << endl;
-
-    indent(out) << "public static const " << upcase_string((*m_iter)->get_name())
-                << ":int = " << (*m_iter)->get_key() << ";" << endl;
-  }
-
-  out << endl;
-
-  // Inner Isset class
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (!type_can_be_null((*m_iter)->get_type())) {
-        indent(out) << "private var __isset_" << (*m_iter)->get_name() << ":Boolean = false;"
-                    << endl;
-      }
-    }
-  }
-
-  out << endl;
-
-  generate_as3_meta_data_map(out, tstruct);
-
-  // Static initializer to populate global class to struct metadata map
-  indent(out) << "{" << endl;
-  indent_up();
-  indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);"
-              << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  // Default constructor
-  indent(out) << "public function " << tstruct->get_name() << "() {" << endl;
-  indent_up();
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if ((*m_iter)->get_value() != NULL) {
-      indent(out) << "this._" << (*m_iter)->get_name() << " = "
-                  << (*m_iter)->get_value()->get_integer() << ";" << endl;
-    }
-  }
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  generate_as3_bean_boilerplate(out, tstruct, bindable);
-  generate_generic_field_getters_setters(out, tstruct);
-  generate_generic_isset_method(out, tstruct);
-
-  generate_as3_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_as3_struct_result_writer(out, tstruct);
-  } else {
-    generate_as3_struct_writer(out, tstruct);
-  }
-  generate_as3_struct_tostring(out, tstruct, bindable);
-  generate_as3_validator(out, tstruct);
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generates a function to read all the fields of the struct.
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_struct_reader(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public function read(iprot:TProtocol):void {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Declare stack tmp variables and read struct header
-  out << indent() << "var field:TField;" << endl << indent() << "iprot.readStructBegin();" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-  scope_up(out);
-
-  // Read beginning field marker
-  indent(out) << "field = iprot.readFieldBegin();" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if (field.type == TType.STOP) { " << endl;
-  indent_up();
-  indent(out) << "break;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  // Switch statement on the field we are reading
-  indent(out) << "switch (field.id)" << endl;
-
-  scope_up(out);
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-
-    generate_deserialize_field(out, *f_iter, "this.");
-    generate_isset_set(out, *f_iter);
-    indent_down();
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
-        << endl << indent() << "}" << endl << indent() << "break;" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  out << indent() << "default:" << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
-      << endl << indent() << "  break;" << endl;
-
-  scope_down(out);
-
-  // Read field end marker
-  indent(out) << "iprot.readFieldEnd();" << endl;
-
-  scope_down(out);
-
-  out << indent() << "iprot.readStructEnd();" << endl << endl;
-
-  // in non-beans style, check for required fields of primitive type
-  // (which can be checked here but not in the general validate method)
-  out << endl << indent() << "// check for required fields of primitive type, which can't be "
-                             "checked in the validate method" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
-      out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent()
-          << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '"
-          << (*f_iter)->get_name()
-          << "' was not found in serialized data! Struct: \" + toString());" << endl << indent()
-          << "}" << endl;
-    }
-  }
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-// generates as3 method to perform various checks
-// (e.g. check that all required fields are set)
-void t_as3_generator::generate_as3_validator(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public function validate():void {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "// check for required fields" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      if (type_can_be_null((*f_iter)->get_type())) {
-        indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
-        indent(out) << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '"
-                    << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());"
-                    << endl;
-        indent(out) << "}" << endl;
-      } else {
-        indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
-                    << "' because it's a primitive and you chose the non-beans generator." << endl;
-      }
-    }
-  }
-
-  // check that fields of type enum have valid values
-  out << indent() << "// check that fields of type enum have valid values" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = (*f_iter);
-    t_type* type = field->get_type();
-    // if field is an enum, check that its value is valid
-    if (type->is_enum()) {
-      indent(out) << "if (" << generate_isset_check(field) << " && !" << get_enum_class_name(type)
-                  << ".VALID_VALUES.contains(" << field->get_name() << ")){" << endl;
-      indent_up();
-      indent(out) << "throw new TProtocolError(TProtocolError.UNKNOWN, \"The field '"
-                  << field->get_name() << "' has been assigned the invalid value \" + "
-                  << field->get_name() << ");" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_struct_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public function write(oprot:TProtocol):void {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl << endl;
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
-      indent_up();
-    }
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
-      indent_up();
-    }
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    if (null_allowed) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    if (could_be_unset) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-  // Write the struct map
-  out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
-      << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct,
- * which is a function result. These fields are only written
- * if they are set in the Isset array, and only one of them
- * can be set at a time.
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public function write(oprot:TProtocol):void {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out << endl << indent() << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
-
-    indent_up();
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}";
-  }
-  // Write the struct map
-  out << endl << indent() << "oprot.writeFieldStop();" << endl << indent()
-      << "oprot.writeStructEnd();" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-void t_as3_generator::generate_reflection_getters(ostringstream& out,
-                                                  t_type* type,
-                                                  string field_name,
-                                                  string cap_name) {
-  (void)type;
-  (void)cap_name;
-  indent(out) << "case " << upcase_string(field_name) << ":" << endl;
-  indent_up();
-  indent(out) << "return this." << field_name << ";" << endl;
-  indent_down();
-}
-
-void t_as3_generator::generate_reflection_setters(ostringstream& out,
-                                                  t_type* type,
-                                                  string field_name,
-                                                  string cap_name) {
-  (void)type;
-  (void)cap_name;
-  indent(out) << "case " << upcase_string(field_name) << ":" << endl;
-  indent_up();
-  indent(out) << "if (value == null) {" << endl;
-  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
-  indent(out) << "} else {" << endl;
-  indent(out) << "  this." << field_name << " = value;" << endl;
-  indent(out) << "}" << endl;
-  indent(out) << "break;" << endl << endl;
-
-  indent_down();
-}
-
-void t_as3_generator::generate_generic_field_getters_setters(std::ofstream& out,
-                                                             t_struct* tstruct) {
-
-  std::ostringstream getter_stream;
-  std::ostringstream setter_stream;
-
-  // build up the bodies of both the getter and setter at once
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    indent_up();
-    generate_reflection_setters(setter_stream, type, field_name, cap_name);
-    generate_reflection_getters(getter_stream, type, field_name, cap_name);
-    indent_down();
-  }
-
-  // create the setter
-  indent(out) << "public function setFieldValue(fieldID:int, value:*):void {" << endl;
-  indent_up();
-
-  indent(out) << "switch (fieldID) {" << endl;
-
-  out << setter_stream.str();
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  // create the getter
-  indent(out) << "public function getFieldValue(fieldID:int):* {" << endl;
-  indent_up();
-
-  indent(out) << "switch (fieldID) {" << endl;
-
-  out << getter_stream.str();
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-
-  indent(out) << "}" << endl;
-
-  indent_down();
-
-  indent(out) << "}" << endl << endl;
-}
-
-// Creates a generic isSet method that takes the field number as argument
-void t_as3_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // create the isSet method
-  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
-                 "value) and false otherwise" << endl;
-  indent(out) << "public function isSet(fieldID:int):Boolean {" << endl;
-  indent_up();
-  indent(out) << "switch (fieldID) {" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a set of As3 Bean boilerplate functions (setters, getters, etc.)
- * for the given struct.
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_bean_boilerplate(ofstream& out,
-                                                    t_struct* tstruct,
-                                                    bool bindable) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    // Simple getter
-    generate_as3_doc(out, field);
-    indent(out) << "public function get " << field_name << "():" << type_name(type) << " {" << endl;
-    indent_up();
-    indent(out) << "return this._" << field_name << ";" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Simple setter
-    generate_as3_doc(out, field);
-    std::string propName = tmp("thriftPropertyChange");
-    if (bindable) {
-      indent(out) << "[Bindable(event=\"" << propName << "\")]" << endl;
-    }
-    indent(out) << "public function set " << field_name << "(" << field_name << ":"
-                << type_name(type) << "):void {" << endl;
-    indent_up();
-    indent(out) << "this._" << field_name << " = " << field_name << ";" << endl;
-    generate_isset_set(out, field);
-
-    if (bindable) {
-      // We have to use a custom event rather than the default, because if you use the default,
-      // the setter only gets called if the value has changed - this means calling
-      // foo.setIntValue(0)
-      // will not cause foo.isIntValueSet() to return true since the value of foo._intValue wasn't
-      // changed
-      // so the setter was never called.
-      indent(out) << "dispatchEvent(new Event(\"" << propName << "\"));" << endl;
-
-      // However, if you just use a custom event, then collections won't be able to detect when
-      // elements
-      // in the collections have changed since they listed for PropertyChangeEvents.  So, we
-      // dispatch both.
-      indent(out) << "dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE));"
-                  << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Unsetter
-    indent(out) << "public function unset" << cap_name << "():void {" << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "this." << field_name << " = null;" << endl;
-    } else {
-      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // isSet method
-    indent(out) << "// Returns true if field " << field_name
-                << " is set (has been assigned a value) and false otherwise" << endl;
-    indent(out) << "public function is" << get_cap_name("set") << cap_name << "():Boolean {"
-                << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "return this." << field_name << " != null;" << endl;
-    } else {
-      indent(out) << "return this.__isset_" << field_name << ";" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates a toString() method for the given struct
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_struct_tostring(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   bool bindable) {
-  // If it's bindable, it extends EventDispatcher so toString is an override.
-  out << indent() << "public " << (bindable ? "override " : "") << "function toString():String {"
-      << endl;
-  indent_up();
-
-  out << indent() << "var ret:String = new String(\"" << tstruct->get_name() << "(\");" << endl;
-  out << indent() << "var first:Boolean = true;" << endl << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
-      indent_up();
-    }
-
-    t_field* field = (*f_iter);
-
-    if (!first) {
-      indent(out) << "if (!first) ret +=  \", \";" << endl;
-    }
-    indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl;
-    bool can_be_null = type_can_be_null(field->get_type());
-    if (can_be_null) {
-      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
-      indent(out) << "  ret += \"null\";" << endl;
-      indent(out) << "} else {" << endl;
-      indent_up();
-    }
-
-    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
-      indent(out) << "  ret += \"BINARY\";" << endl;
-    } else if (field->get_type()->is_enum()) {
-      indent(out) << "var " << field->get_name()
-                  << "_name:String = " << get_enum_class_name(field->get_type())
-                  << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl;
-      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
-      indent(out) << "  ret += " << field->get_name() << "_name;" << endl;
-      indent(out) << "  ret += \" (\";" << endl;
-      indent(out) << "}" << endl;
-      indent(out) << "ret += this." << field->get_name() << ";" << endl;
-      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
-      indent(out) << "  ret += \")\";" << endl;
-      indent(out) << "}" << endl;
-    } else {
-      indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl;
-    }
-
-    if (can_be_null) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    indent(out) << "first = false;" << endl;
-
-    if (could_be_unset) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    first = false;
-  }
-  out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a static map with meta data to store information such as fieldID to
- * fieldName mapping
- *
- * @param tstruct The struct definition
- */
-void t_as3_generator::generate_as3_meta_data_map(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Static Map with fieldID -> FieldMetaData mappings
-  indent(out) << "public static const metaDataMap:Dictionary = new Dictionary();" << endl;
-
-  if (fields.size() > 0) {
-    // Populate map
-    scope_up(out);
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* field = *f_iter;
-      std::string field_name = field->get_name();
-      indent(out) << "metaDataMap[" << upcase_string(field_name) << "] = new FieldMetaData(\""
-                  << field_name << "\", ";
-
-      // Set field requirement type (required, optional, etc.)
-      if (field->get_req() == t_field::T_REQUIRED) {
-        out << "TFieldRequirementType.REQUIRED, ";
-      } else if (field->get_req() == t_field::T_OPTIONAL) {
-        out << "TFieldRequirementType.OPTIONAL, ";
-      } else {
-        out << "TFieldRequirementType.DEFAULT, ";
-      }
-
-      // Create value meta data
-      generate_field_value_meta_data(out, field->get_type());
-      out << ");" << endl;
-    }
-    scope_down(out);
-  }
-}
-
-/**
- * Returns a string with the as3 representation of the given thrift type
- * (e.g. for the type struct it returns "TType.STRUCT")
- */
-std::string t_as3_generator::get_as3_type_string(t_type* type) {
-  if (type->is_list()) {
-    return "TType.LIST";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_enum()) {
-    return "TType.I32";
-  } else if (type->is_typedef()) {
-    return get_as3_type_string(((t_typedef*)type)->get_type());
-  } else if (type->is_base_type()) {
-    switch (((t_base_type*)type)->get_base()) {
-    case t_base_type::TYPE_VOID:
-      return "TType.VOID";
-      break;
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-      break;
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-      break;
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-      break;
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-      break;
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-      break;
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-      break;
-    default:
-      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
-                               + "\" passed to t_as3_generator::get_as3_type_string!");
-      break; // This should never happen!
-    }
-  } else {
-    throw std::runtime_error(
-        "Unknown thrift type \"" + type->get_name()
-        + "\" passed to t_as3_generator::get_as3_type_string!"); // This should never happen!
-  }
-}
-
-void t_as3_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
-  out << endl;
-  indent_up();
-  indent_up();
-  if (type->is_struct() || type->is_xception()) {
-    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type);
-  } else if (type->is_container()) {
-    if (type->is_list()) {
-      indent(out) << "new ListMetaData(TType.LIST, ";
-      t_type* elem_type = ((t_list*)type)->get_elem_type();
-      generate_field_value_meta_data(out, elem_type);
-    } else if (type->is_set()) {
-      indent(out) << "new SetMetaData(TType.SET, ";
-      t_type* elem_type = ((t_list*)type)->get_elem_type();
-      generate_field_value_meta_data(out, elem_type);
-    } else { // map
-      indent(out) << "new MapMetaData(TType.MAP, ";
-      t_type* key_type = ((t_map*)type)->get_key_type();
-      t_type* val_type = ((t_map*)type)->get_val_type();
-      generate_field_value_meta_data(out, key_type);
-      out << ", ";
-      generate_field_value_meta_data(out, val_type);
-    }
-  } else {
-    indent(out) << "new FieldValueMetaData(" << get_as3_type_string(type);
-  }
-  out << ")";
-  indent_down();
-  indent_down();
-}
-
-/**
- * Generates a thrift service. In C++, this comprises an entirely separate
- * header and source file. The header file defines the methods and includes
- * the data types defined in the main header file, and the implementation
- * file contains implementations of the basic printer and default interfaces.
- *
- * @param tservice The service definition
- */
-void t_as3_generator::generate_service(t_service* tservice) {
-  // Make interface file
-  string f_service_name = package_dir_ + "/" + service_name_ + ".as";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << as3_package();
-
-  scope_up(f_service_);
-
-  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
-             << as3_thrift_gen_imports(tservice);
-
-  if (tservice->get_extends() != NULL) {
-    t_type* parent = tservice->get_extends();
-    string parent_namespace = parent->get_program()->get_namespace("as3");
-    if (!parent_namespace.empty() && parent_namespace != package_name_) {
-      f_service_ << "import " << type_name(parent) << ";" << endl;
-    }
-  }
-
-  f_service_ << endl;
-
-  generate_service_interface(tservice);
-
-  scope_down(f_service_);
-  f_service_.close();
-
-  // Now make the implementation/client file
-  f_service_name = package_dir_ + "/" + service_name_ + "Impl.as";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << as3_package();
-
-  scope_up(f_service_);
-
-  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
-             << as3_thrift_gen_imports(tservice);
-
-  if (tservice->get_extends() != NULL) {
-    t_type* parent = tservice->get_extends();
-    string parent_namespace = parent->get_program()->get_namespace("as3");
-    if (!parent_namespace.empty() && parent_namespace != package_name_) {
-      f_service_ << "import " << type_name(parent) << "Impl;" << endl;
-    }
-  }
-
-  f_service_ << endl;
-
-  generate_service_client(tservice);
-  scope_down(f_service_);
-
-  f_service_ << as3_type_imports();
-  f_service_ << as3_thrift_imports();
-  f_service_ << as3_thrift_gen_imports(tservice);
-  if (!package_name_.empty()) {
-    f_service_ << "import " << package_name_ << ".*;" << endl;
-  }
-
-  generate_service_helpers(tservice);
-
-  f_service_.close();
-
-  // Now make the processor/server file
-  f_service_name = package_dir_ + "/" + service_name_ + "Processor.as";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << as3_package();
-
-  scope_up(f_service_);
-
-  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
-             << as3_thrift_gen_imports(tservice) << endl;
-
-  generate_service_server(tservice);
-  scope_down(f_service_);
-
-  f_service_ << as3_type_imports();
-  f_service_ << as3_thrift_imports();
-  f_service_ << as3_thrift_gen_imports(tservice) << endl;
-  if (!package_name_.empty()) {
-    f_service_ << "import " << package_name_ << ".*;" << endl;
-  }
-
-  generate_service_helpers(tservice);
-
-  f_service_.close();
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_as3_generator::generate_service_interface(t_service* tservice) {
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends_iface = " extends " + tservice->get_extends()->get_name();
-  }
-
-  generate_as3_doc(f_service_, tservice);
-  f_service_ << indent() << "public interface " << service_name_ << extends_iface << " {" << endl
-             << endl;
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_as3_doc(f_service_, *f_iter);
-    if (!(*f_iter)->is_oneway()) {
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "//function onError(Error):void;" << endl;
-        indent(f_service_) << "//function onSuccess():void;" << endl;
-      } else {
-        indent(f_service_) << "//function onError(Error):void;" << endl;
-        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype())
-                           << "):void;" << endl;
-      }
-    }
-    indent(f_service_) << function_signature(*f_iter) << ";" << endl << endl;
-  }
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates structs for all the service args and return types
- *
- * @param tservice The service
- */
-void t_as3_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_as3_struct_definition(f_service_, ts, false, true);
-    generate_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_as3_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = tservice->get_extends()->get_name();
-    extends_client = " extends " + extends + "Impl";
-  }
-
-  indent(f_service_) << "public class " << service_name_ << "Impl" << extends_client
-                     << " implements " << service_name_ << " {" << endl;
-  indent_up();
-
-  indent(f_service_) << "public function " << service_name_ << "Impl"
-                     << "(iprot:TProtocol, oprot:TProtocol=null)" << endl;
-  scope_up(f_service_);
-  if (extends.empty()) {
-    f_service_ << indent() << "iprot_ = iprot;" << endl;
-    f_service_ << indent() << "if (oprot == null) {" << endl;
-    indent_up();
-    f_service_ << indent() << "oprot_ = iprot;" << endl;
-    indent_down();
-    f_service_ << indent() << "} else {" << endl;
-    indent_up();
-    f_service_ << indent() << "oprot_ = oprot;" << endl;
-    indent_down();
-    f_service_ << indent() << "}";
-  } else {
-    f_service_ << indent() << "super(iprot, oprot);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected var iprot_:TProtocol;" << endl << indent()
-               << "protected var oprot_:TProtocol;" << endl << endl << indent()
-               << "protected var seqid_:int;" << endl << endl;
-
-    indent(f_service_) << "public function getInputProtocol():TProtocol" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return this.iprot_;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    indent(f_service_) << "public function getOutputProtocol():TProtocol" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return this.oprot_;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    if (!(*f_iter)->is_oneway()) {
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "//function onError(Error):void;" << endl;
-        indent(f_service_) << "//function onSuccess():void;" << endl;
-      } else {
-        indent(f_service_) << "//function onError(Error):void;" << endl;
-        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype())
-                           << "):void;" << endl;
-      }
-    }
-    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
-    scope_up(f_service_);
-
-    // Get the struct of function call params
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    string argsname = (*f_iter)->get_name() + "_args";
-    vector<t_field*>::const_iterator fld_iter;
-    const vector<t_field*>& fields = arg_struct->get_members();
-
-    // Serialize the request
-    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", "
-               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
-               << ", seqid_));" << endl << indent() << "var args:" << argsname << " = new "
-               << argsname << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
-                 << (*fld_iter)->get_name() << ";" << endl;
-    }
-
-    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
-               << "oprot_.writeMessageEnd();" << endl;
-
-    if ((*f_iter)->is_oneway()) {
-      f_service_ << indent() << "oprot_.getTransport().flush();" << endl;
-    } else {
-      f_service_ << indent() << "oprot_.getTransport().flush(function(error:Error):void {" << endl;
-      indent_up();
-      f_service_ << indent() << "try {" << endl;
-      indent_up();
-      string resultname = (*f_iter)->get_name() + "_result";
-      f_service_ << indent() << "if (error != null) {" << endl << indent()
-                 << "  if (onError != null) onError(error);" << endl << indent() << "  return;"
-                 << endl << indent() << "}" << endl << indent()
-                 << "var msg:TMessage = iprot_.readMessageBegin();" << endl << indent()
-                 << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent()
-                 << "  var x:TApplicationError = TApplicationError.read(iprot_);" << endl
-                 << indent() << "  iprot_.readMessageEnd();" << endl << indent()
-                 << "  if (onError != null) onError(x);" << endl << indent() << "  return;" << endl
-                 << indent() << "}" << endl << indent() << "var result :" << resultname << " = new "
-                 << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl
-                 << indent() << "iprot_.readMessageEnd();" << endl;
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl
-                   << indent() << "  if (onSuccess != null) onSuccess(result.success);" << endl
-                   << indent() << "  return;" << endl << indent() << "}" << endl;
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl
-                   << indent() << "  if (onError != null) onError(result." << (*x_iter)->get_name()
-                   << ");" << endl << indent() << "  return;" << endl << indent() << "}" << endl;
-      }
-
-      // If you get here it's an exception, unless a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "if (onSuccess != null) onSuccess();" << endl << indent()
-                   << "return;" << endl;
-      } else {
-
-        f_service_ << indent() << "if (onError != null) onError(new "
-                                  "TApplicationError(TApplicationError.MISSING_RESULT, \""
-                   << (*f_iter)->get_name() << " failed: unknown result\"));" << endl;
-      }
-      indent_down();
-      f_service_ << indent() << "} catch (e:TError) {" << endl << indent()
-                 << "  if (onError != null) onError(e);" << endl << indent() << "}" << endl;
-
-      indent_down();
-      indent(f_service_) << "});" << endl;
-    }
-    // Close function
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl;
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_as3_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  // Extends stuff
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_processor = " extends " + extends + "Processor";
-  }
-
-  // Generate the header portion
-  indent(f_service_) << "public class " << service_name_ << "Processor" << extends_processor
-                     << " implements TProcessor {" << endl;
-  indent_up();
-
-  indent(f_service_) << "public function " << service_name_ << "Processor(iface:" << service_name_
-                     << ")" << endl;
-  scope_up(f_service_);
-  if (!extends.empty()) {
-    f_service_ << indent() << "super(iface);" << endl;
-  }
-  f_service_ << indent() << "iface_ = iface;" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "PROCESS_MAP[\"" << (*f_iter)->get_name()
-               << "\"] = " << (*f_iter)->get_name() << "();" << endl;
-  }
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  f_service_ << indent() << "private var iface_:" << service_name_ << ";" << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected const PROCESS_MAP:Dictionary = new Dictionary();" << endl;
-  }
-
-  f_service_ << endl;
-
-  // Generate the server implementation
-  string override = "";
-  if (tservice->get_extends() != NULL) {
-    override = "override ";
-  }
-  indent(f_service_) << override
-                     << "public function process(iprot:TProtocol, oprot:TProtocol):Boolean" << endl;
-  scope_up(f_service_);
-
-  f_service_ << indent() << "var msg:TMessage = iprot.readMessageBegin();" << endl;
-
-  // TODO(mcslee): validate message, was the seqid etc. legit?
-  // AS- If all method is oneway:
-  // do you have an oprot?
-  // do you you need nullcheck?
-  f_service_
-      << indent() << "var fn:Function = PROCESS_MAP[msg.name];" << endl << indent()
-      << "if (fn == null) {" << endl << indent() << "  TProtocolUtil.skip(iprot, TType.STRUCT);"
-      << endl << indent() << "  iprot.readMessageEnd();" << endl << indent()
-      << "  var x:TApplicationError = new TApplicationError(TApplicationError.UNKNOWN_METHOD, "
-         "\"Invalid method name: '\"+msg.name+\"'\");" << endl << indent()
-      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
-      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
-      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
-      << "  return true;" << endl << indent() << "}" << endl << indent()
-      << "fn.call(this,msg.seqid, iprot, oprot);" << endl;
-
-  f_service_ << indent() << "return true;" << endl;
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl << endl;
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_as3_generator::generate_function_helpers(t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  t_struct result(program_, tfunction->get_name() + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_as3_struct_definition(f_service_, &result, false, true, true);
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_as3_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open class
-  indent(f_service_) << "private function " << tfunction->get_name() << "():Function {" << endl;
-  indent_up();
-
-  // Open function
-  indent(f_service_) << "return function(seqid:int, iprot:TProtocol, oprot:TProtocol):void" << endl;
-  scope_up(f_service_);
-
-  string argsname = tfunction->get_name() + "_args";
-  string resultname = tfunction->get_name() + "_result";
-
-  f_service_ << indent() << "var args:" << argsname << " = new " << argsname << "();" << endl
-             << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();"
-             << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "var result:" << resultname << " = new " << resultname << "();"
-               << endl;
-  }
-
-  // Try block for a function with exceptions
-  if (xceptions.size() > 0) {
-    f_service_ << indent() << "try {" << endl;
-    indent_up();
-  }
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_ << indent();
-  if (tfunction->is_oneway()) {
-    f_service_ << "iface_." << tfunction->get_name() << "(";
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-    f_service_ << ");" << endl;
-  } else {
-    f_service_ << "// sorry this operation is not supported yet" << endl;
-    f_service_ << indent() << "throw new Error(\"This is not yet supported\");" << endl;
-  }
-
-  // Set isset on success field
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()
-      && !type_can_be_null(tfunction->get_returntype())) {
-    f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet")
-               << "(true);" << endl;
-  }
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    indent_down();
-    f_service_ << indent() << "}";
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << " catch (" << (*x_iter)->get_name() << ":"
-                 << type_name((*x_iter)->get_type(), false, false) << ") {" << endl;
-      if (!tfunction->is_oneway()) {
-        indent_up();
-        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
-                   << (*x_iter)->get_name() << ";" << endl;
-        indent_down();
-        f_service_ << indent() << "}";
-      } else {
-        f_service_ << "}";
-      }
-    }
-    f_service_ << " catch (th:Error) {" << endl;
-    indent_up();
-    f_service_ << indent() << "trace(\"Internal error processing " << tfunction->get_name()
-               << "\", th);" << endl << indent()
-               << "var x:TApplicationError = new "
-                  "TApplicationError(TApplicationError.INTERNAL_ERROR, \"Internal error processing "
-               << tfunction->get_name() << "\");" << endl << indent()
-               << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-               << "\", TMessageType.EXCEPTION, seqid));" << endl << indent() << "x.write(oprot);"
-               << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
-               << "oprot.getTransport().flush();" << endl << indent() << "return;" << endl;
-    indent_down();
-    f_service_ << indent() << "}" << endl;
-  }
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "return;" << endl;
-    scope_down(f_service_);
-
-    // Close class
-    indent_down();
-    f_service_ << indent() << "}" << endl << endl;
-    return;
-  }
-
-  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
-             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
-             << "oprot.getTransport().flush();" << endl;
-
-  // Close function
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Close class
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Deserializes a field of any type.
- *
- * @param tfield The field
- * @param prefix The variable name or container for this field
- */
-void t_as3_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    indent(out) << name << " = iprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "readBinary();";
-        } else {
-          out << "readString();";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool();";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte();";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16();";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32();";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64();";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble();";
-        break;
-      default:
-        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32();";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a struct, invokes read()
- */
-void t_as3_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent()
-      << prefix << ".read(iprot);" << endl;
-}
-
-/**
- * Deserializes a container by reading its size and then iterating
- */
-void t_as3_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  string obj;
-
-  if (ttype->is_map()) {
-    obj = tmp("_map");
-  } else if (ttype->is_set()) {
-    obj = tmp("_set");
-  } else if (ttype->is_list()) {
-    obj = tmp("_list");
-  }
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    indent(out) << "var " << obj << ":TMap = iprot.readMapBegin();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "var " << obj << ":TSet = iprot.readSetBegin();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "var " << obj << ":TList = iprot.readListBegin();" << endl;
-  }
-
-  indent(out) << prefix << " = new " << type_name(ttype, false, true)
-              // size the collection correctly
-              << "("
-              << ");" << endl;
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) << "for (var " << i << ":int = 0; " << i << " < " << obj << ".size"
-              << "; "
-              << "++" << i << ")" << endl;
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  scope_down(out);
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "iprot.readMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "iprot.readSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "iprot.readListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_as3_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("_key");
-  string val = tmp("_val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  indent(out) << declare_field(&fkey) << endl;
-  indent(out) << declare_field(&fval) << endl;
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
-}
-
-/**
- * Deserializes a set element
- */
-void t_as3_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  indent(out) << declare_field(&felem) << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".add(" << elem << ");" << endl;
-}
-
-/**
- * Deserializes a list element
- */
-void t_as3_generator::generate_deserialize_list_element(ofstream& out,
-                                                        t_list* tlist,
-                                                        string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  indent(out) << declare_field(&felem) << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".push(" << elem << ");" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_as3_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + tfield->get_name());
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = prefix + tfield->get_name();
-    indent(out) << "oprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "writeBinary(" << name << ");";
-        } else {
-          out << "writeString(" << name << ");";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ");";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ");";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ");";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ");";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ");";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ");";
-        break;
-      default:
-        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32(" << name << ");";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           tfield->get_name().c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_as3_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  out << indent() << prefix << ".write(oprot);" << endl;
-}
-
-/**
- * Serializes a container by writing its size then the elements.
- *
- * @param ttype  The type of container
- * @param prefix String prefix for fields
- */
-void t_as3_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    string iter = tmp("_key");
-    string counter = tmp("_sizeCounter");
-    indent(out) << "var " << counter << ":int = 0;" << endl;
-    indent(out) << "for (var " << iter << ":* in " << prefix << ") {" << endl;
-    indent(out) << "  " << counter << +"++;" << endl;
-    indent(out) << "}" << endl;
-
-    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
-                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));"
-                << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
-                << ", " << prefix << ".size));" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListBegin(new TList("
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
-                << endl;
-  }
-
-  string iter = tmp("elem");
-  if (ttype->is_map()) {
-    indent(out) << "for (var " << iter << ":* in " << prefix << ")";
-  } else if (ttype->is_set()) {
-    indent(out) << "for each (var " << iter << ":* in " << prefix << ".toArray())";
-  } else if (ttype->is_list()) {
-    indent(out) << "for each (var " << iter << ":* in " << prefix << ")";
-  }
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
-  } else if (ttype->is_set()) {
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-  } else if (ttype->is_list()) {
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-  }
-
-  scope_down(out);
-
-  if (ttype->is_map()) {
-    indent(out) << "oprot.writeMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Serializes the members of a map.
- */
-void t_as3_generator::generate_serialize_map_element(ofstream& out,
-                                                     t_map* tmap,
-                                                     string iter,
-                                                     string map) {
-  t_field kfield(tmap->get_key_type(), iter);
-  generate_serialize_field(out, &kfield, "");
-  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
-  generate_serialize_field(out, &vfield, "");
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_as3_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_as3_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Returns a As3 type name
- *
- * @param ttype The type
- * @param container Is the type going inside a container?
- * @return As3 type name, i.e. HashMap<Key,Value>
- */
-string t_as3_generator::type_name(t_type* ttype, bool in_container, bool in_init) {
-  (void)in_init;
-  // In As3 typedefs are just resolved to their real type
-  ttype = get_true_type(ttype);
-  string prefix;
-
-  if (ttype->is_base_type()) {
-    return base_type_name((t_base_type*)ttype, in_container);
-  } else if (ttype->is_enum()) {
-    return "int";
-  } else if (ttype->is_map()) {
-    return "Dictionary";
-  } else if (ttype->is_set()) {
-    return "Set";
-  } else if (ttype->is_list()) {
-    return "Array";
-  }
-
-  // Check for namespacing
-  t_program* program = ttype->get_program();
-  if (program != NULL && program != program_) {
-    string package = program->get_namespace("as3");
-    if (!package.empty()) {
-      return package + "." + ttype->get_name();
-    }
-  }
-
-  return ttype->get_name();
-}
-
-/**
- * Returns the AS3 type that corresponds to the thrift type.
- *
- * @param tbase The base type
- * @param container Is it going in a As3 container?
- */
-string t_as3_generator::base_type_name(t_base_type* type, bool in_container) {
-  (void)in_container;
-  t_base_type::t_base tbase = type->get_base();
-
-  switch (tbase) {
-  case t_base_type::TYPE_VOID:
-    return "void";
-  case t_base_type::TYPE_STRING:
-    if (type->is_binary()) {
-      return "ByteArray";
-    } else {
-      return "String";
-    }
-  case t_base_type::TYPE_BOOL:
-    return "Boolean";
-  case t_base_type::TYPE_I8:
-  case t_base_type::TYPE_I16:
-  case t_base_type::TYPE_I32:
-    return "int";
-  case t_base_type::TYPE_I64:
-    throw "i64 is not yet supported in as3";
-  case t_base_type::TYPE_DOUBLE:
-    return "Number";
-  default:
-    throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
-  }
-}
-
-/**
- * Declares a field, which may include initialization as necessary.
- *
- * @param ttype The type
- */
-string t_as3_generator::declare_field(t_field* tfield, bool init) {
-  // TODO(mcslee): do we ever need to initialize the field?
-  string result = "var " + tfield->get_name() + ":" + type_name(tfield->get_type());
-  if (init) {
-    t_type* ttype = get_true_type(tfield->get_type());
-    if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
-      result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
-    } else if (ttype->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "NO T_VOID CONSTRUCT";
-      case t_base_type::TYPE_STRING:
-        result += " = null";
-        break;
-      case t_base_type::TYPE_BOOL:
-        result += " = false";
-        break;
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        result += " = (double)0";
-        break;
-      }
-
-    } else if (ttype->is_enum()) {
-      result += " = 0";
-    } else if (ttype->is_container()) {
-      result += " = new " + type_name(ttype, false, true) + "()";
-    } else {
-      result += " = new " + type_name(ttype, false, true) + "()";
-      ;
-    }
-  }
-  return result + ";";
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_as3_generator::function_signature(t_function* tfunction, string prefix) {
-  std::string arguments = argument_list(tfunction->get_arglist());
-  if (!tfunction->is_oneway()) {
-    if (arguments != "") {
-      arguments += ", ";
-    }
-    arguments += "onError:Function, onSuccess:Function";
-  }
-
-  std::string result = "function " + prefix + tfunction->get_name() + "(" + arguments + "):void";
-  return result;
-}
-
-/**
- * Renders a comma separated field list, with type names
- */
-string t_as3_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    result += (*f_iter)->get_name() + ":" + type_name((*f_iter)->get_type());
-  }
-  return result;
-}
-
-/**
- * Converts the parse type to a C++ enum string for the given type.
- */
-string t_as3_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "TType.I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_list()) {
-    return "TType.LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-/**
- * Applies the correct style to a string based on the value of nocamel_style_
- */
-std::string t_as3_generator::get_cap_name(std::string name) {
-  name[0] = toupper(name[0]);
-  return name;
-}
-
-string t_as3_generator::constant_name(string name) {
-  string constant_name;
-
-  bool is_first = true;
-  bool was_previous_char_upper = false;
-  for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
-    string::value_type character = (*iter);
-
-    bool is_upper = isupper(character);
-
-    if (is_upper && !is_first && !was_previous_char_upper) {
-      constant_name += '_';
-    }
-    constant_name += toupper(character);
-
-    is_first = false;
-   

<TRUNCATED>

[43/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_delphi_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_delphi_generator.cc b/compiler/cpp/src/generate/t_delphi_generator.cc
deleted file mode 100644
index fece1da..0000000
--- a/compiler/cpp/src/generate/t_delphi_generator.cc
+++ /dev/null
@@ -1,3920 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <cassert>
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <list>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include <cctype>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-class t_delphi_generator : public t_oop_generator {
-public:
-  t_delphi_generator(t_program* program,
-                     const std::map<std::string, std::string>& parsed_options,
-                     const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    indent_impl_ = 0;
-    has_forward = false;
-    has_enum = false;
-    has_const = false;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    ansistr_binary_ = false;
-    register_types_ = false;
-    constprefix_ = false;
-    events_ = false;
-    xmldoc_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("ansistr_binary") == 0) {
-        ansistr_binary_ = true;
-      } else if( iter->first.compare("register_types") == 0) {
-        register_types_ = true;
-      } else if( iter->first.compare("constprefix") == 0) {
-        constprefix_ = true;
-      } else if( iter->first.compare("events") == 0) {
-        events_ = true;
-      } else if( iter->first.compare("xmldoc") == 0) {
-        xmldoc_ = true;
-      } else {
-        throw "unknown option delphi:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-delphi";
-    escape_.clear();
-    escape_['\''] = "''";
-  }
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_forward_declaration(t_struct* tstruct);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-  void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception);
-  void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic);
-
-  void generate_delphi_property(ostream& out,
-                                bool struct_is_exception,
-                                t_field* tfield,
-                                bool isPublic,
-                                std::string fieldPrefix = "");
-  void generate_delphi_isset_reader_definition(ostream& out, t_field* tfield, bool is_xception);
-  void generate_delphi_property_reader_definition(ostream& out,
-                                                  t_field* tfield,
-                                                  bool is_xception_class);
-  void generate_delphi_property_writer_definition(ostream& out,
-                                                  t_field* tfield,
-                                                  bool is_xception_class);
-  void generate_delphi_property_reader_impl(ostream& out,
-                                            std::string cls_prefix,
-                                            std::string name,
-                                            t_type* type,
-                                            t_field* tfield,
-                                            std::string fieldPrefix,
-                                            bool is_xception_class);
-  void generate_delphi_property_writer_impl(ostream& out,
-                                            std::string cls_prefix,
-                                            std::string name,
-                                            t_type* type,
-                                            t_field* tfield,
-                                            std::string fieldPrefix,
-                                            bool is_xception_class,
-                                            bool is_union,
-                                            bool is_xception_factory,
-                                            std::string xception_factroy_name);
-  void generate_delphi_clear_union_value(ostream& out,
-                                         std::string cls_prefix,
-                                         std::string name,
-                                         t_type* type,
-                                         t_field* tfield,
-                                         std::string fieldPrefix,
-                                         bool is_xception_class,
-                                         bool is_union,
-                                         bool is_xception_factory,
-                                         std::string xception_factroy_name);
-  void generate_delphi_isset_reader_impl(ostream& out,
-                                         std::string cls_prefix,
-                                         std::string name,
-                                         t_type* type,
-                                         t_field* tfield,
-                                         std::string fieldPrefix,
-                                         bool is_xception);
-  void generate_delphi_struct_writer_impl(ostream& out,
-                                          std::string cls_prefix,
-                                          t_struct* tstruct,
-                                          bool is_exception);
-  void generate_delphi_struct_result_writer_impl(ostream& out,
-                                                 std::string cls_prefix,
-                                                 t_struct* tstruct,
-                                                 bool is_exception);
-
-  void generate_delphi_struct_tostring_impl(ostream& out,
-                                            std::string cls_prefix,
-                                            t_struct* tstruct,
-                                            bool is_exception,
-                                            bool is_x_factory);
-
-  void add_delphi_uses_list(string unitname);
-
-  void generate_delphi_struct_reader_impl(ostream& out,
-                                          std::string cls_prefix,
-                                          t_struct* tstruct,
-                                          bool is_exception);
-  void generate_delphi_create_exception_impl(ostream& out,
-                                             string cls_prefix,
-                                             t_struct* tstruct,
-                                             bool is_exception);
-
-  bool const_needs_var(t_type* type);
-  void print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value);
-  void print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value);
-  void print_const_value(std::ostream& vars,
-                         std::ostream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value);
-  void initialize_field(std::ostream& vars,
-                        std::ostream& out,
-                        std::string name,
-                        t_type* type,
-                        t_const_value* value);
-  void finalize_field(std::ostream& out,
-                      std::string name,
-                      t_type* type,
-                      t_const_value* value,
-                      std::string cls_nm = "");
-  std::string render_const_value(std::ostream& local_vars,
-                                 std::ostream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-  void print_const_def_value(std::ostream& vars,
-                             std::ostream& out,
-                             std::string name,
-                             t_type* type,
-                             t_const_value* value,
-                             std::string cls_nm = "");
-  std::string make_constants_classname();
-
-  void generate_delphi_struct(t_struct* tstruct, bool is_exception);
-  void generate_delphi_struct_impl(ostream& out,
-                                   std::string cls_prefix,
-                                   t_struct* tstruct,
-                                   bool is_exception,
-                                   bool is_result = false,
-                                   bool is_x_factory = false);
-  void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct);
-  void generate_delphi_struct_type_factory(ostream& out,
-                                           std::string cls_prefix,
-                                           t_struct* tstruct,
-                                           bool is_exception,
-                                           bool is_result = false,
-                                           bool is_x_factory = false);
-  void generate_delphi_struct_type_factory_registration(ostream& out,
-                                                        std::string cls_prefix,
-                                                        t_struct* tstruct,
-                                                        bool is_exception,
-                                                        bool is_result = false,
-                                                        bool is_x_factory = false);
-  void generate_delphi_struct_definition(std::ostream& out,
-                                         t_struct* tstruct,
-                                         bool is_xception = false,
-                                         bool in_class = false,
-                                         bool is_result = false,
-                                         bool is_x_factory = false);
-  void generate_delphi_struct_reader(std::ostream& out, t_struct* tstruct);
-  void generate_delphi_struct_result_writer(std::ostream& out, t_struct* tstruct);
-  void generate_delphi_struct_writer(std::ostream& out, t_struct* tstruct);
-  void generate_delphi_struct_tostring(std::ostream& out, t_struct* tstruct);
-
-  void generate_function_helpers(t_function* tfunction);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* function);
-
-  void generate_deserialize_field(std::ostream& out,
-                                  bool is_xception,
-                                  t_field* tfield,
-                                  std::string prefix,
-                                  std::ostream& local_vars);
-  void generate_deserialize_struct(std::ostream& out,
-                                   t_struct* tstruct,
-                                   std::string name,
-                                   std::string prefix);
-  void generate_deserialize_container(ostream& out,
-                                      bool is_xception,
-                                      t_type* ttype,
-                                      string name,
-                                      std::ostream& local_vars);
-
-  void generate_deserialize_set_element(std::ostream& out,
-                                        bool is_xception,
-                                        t_set* tset,
-                                        std::string prefix,
-                                        std::ostream& local_vars);
-  void generate_deserialize_map_element(std::ostream& out,
-                                        bool is_xception,
-                                        t_map* tmap,
-                                        std::string prefix,
-                                        std::ostream& local_vars);
-  void generate_deserialize_list_element(std::ostream& out,
-                                         bool is_xception,
-                                         t_list* list,
-                                         std::string prefix,
-                                         std::ostream& local_vars);
-
-  void generate_serialize_field(std::ostream& out,
-                                bool is_xception,
-                                t_field* tfield,
-                                std::string prefix,
-                                std::ostream& local_vars);
-  void generate_serialize_struct(std::ostream& out,
-                                 t_struct* tstruct,
-                                 std::string prefix,
-                                 std::ostream& local_vars);
-  void generate_serialize_container(std::ostream& out,
-                                    bool is_xception,
-                                    t_type* ttype,
-                                    std::string prefix,
-                                    std::ostream& local_vars);
-  void generate_serialize_map_element(std::ostream& out,
-                                      bool is_xception,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map,
-                                      std::ostream& local_vars);
-  void generate_serialize_set_element(std::ostream& out,
-                                      bool is_xception,
-                                      t_set* tmap,
-                                      std::string iter,
-                                      std::ostream& local_vars);
-  void generate_serialize_list_element(std::ostream& out,
-                                       bool is_xception,
-                                       t_list* tlist,
-                                       std::string iter,
-                                       std::ostream& local_vars);
-
-  void delphi_type_usings(std::ostream& out);
-  std::string delphi_thrift_usings();
-
-  std::string type_name(t_type* ttype,
-                        bool b_cls = false,
-                        bool b_no_postfix = false,
-                        bool b_exception_factory = false,
-                        bool b_full_exception_factory = false);
-  std::string normalize_clsnm(std::string name,
-                              std::string prefix,
-                              bool b_no_check_keyword = false);
-  std::string make_valid_delphi_identifier(std::string const& fromName);
-  std::string input_arg_prefix(t_type* ttype);
-
-  std::string base_type_name(t_base_type* tbase);
-  std::string declare_field(t_field* tfield,
-                            bool init = false,
-                            std::string prefix = "",
-                            bool is_xception_class = false);
-  std::string function_signature(t_function* tfunction,
-                                 std::string full_cls = "",
-                                 bool is_xception = false);
-  std::string argument_list(t_struct* tstruct);
-  std::string constructor_argument_list(t_struct* tstruct, std::string current_indent);
-  std::string type_to_enum(t_type* ttype);
-  std::string prop_name(t_field* tfield, bool is_xception = false);
-  std::string prop_name(std::string name, bool is_xception = false);
-  std::string constructor_param_name(string name);
-
-  void write_enum(std::string line);
-  void write_forward_decr(std::string line);
-  void write_const(std::string line);
-  void write_struct(std::string line);
-  void write_service(std::string line);
-
-  virtual std::string autogen_comment() {
-    return std::string("(**\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-           + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
-           + " *)\n";
-  }
-
-  string replace_all(string contents, string search, string replace);
-  string xml_encode(string contents);
-  string xmldoc_encode(string contents);
-  string xmlattrib_encode(string contents);
-  void generate_delphi_doc(std::ostream& out, t_field* field);
-  void generate_delphi_doc(std::ostream& out, t_doc* tdoc);
-  void generate_delphi_doc(std::ostream& out, t_function* tdoc);
-  void generate_delphi_docstring_comment(std::ostream& out, string contents);
-
-  bool type_can_be_null(t_type* ttype) {
-    while (ttype->is_typedef()) {
-      ttype = ((t_typedef*)ttype)->get_type();
-    }
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
-  }
-
-private:
-  std::string namespace_name_;
-  std::ostringstream s_forward_decr;
-  std::ostringstream s_enum;
-  std::ostringstream s_const;
-  std::ostringstream s_struct;
-  std::ostringstream s_service;
-  std::ostringstream s_const_impl;
-  std::ostringstream s_struct_impl;
-  std::ostringstream s_service_impl;
-  std::ostringstream s_type_factory_registration;
-  std::ostringstream s_type_factory_funcs;
-  bool has_forward;
-  bool has_enum;
-  bool has_const;
-  std::string namespace_dir_;
-  std::map<std::string, int> delphi_keywords;
-  std::map<std::string, int> delphi_reserved_method;
-  std::map<std::string, int> delphi_reserved_method_exception;
-  std::map<std::string, int> types_known;
-  std::list<t_typedef*> typedefs_pending;
-  std::vector<std::string> uses_list;
-  void create_keywords();
-  bool find_keyword(std::map<std::string, int>& keyword_map, std::string name);
-  std::string normalize_name(std::string name,
-                             bool b_method = false,
-                             bool b_exception_method = false);
-  std::string empty_value(t_type* type);
-  bool is_fully_defined_type(t_type* ttype);
-  void add_defined_type(t_type* ttype);
-  void init_known_types_list();
-  bool is_void(t_type* type);
-  int indent_impl_;
-  bool ansistr_binary_;
-  bool register_types_;
-  bool constprefix_;
-  bool events_;
-  bool xmldoc_;
-  void indent_up_impl() { ++indent_impl_; };
-  void indent_down_impl() { --indent_impl_; };
-  std::string indent_impl() {
-    std::string ind = "";
-    int i;
-    for (i = 0; i < indent_impl_; ++i) {
-      ind += "  ";
-    }
-    return ind;
-  };
-  std::ostream& indent_impl(std::ostream& os) { return os << indent_impl(); };
-};
-
-string t_delphi_generator::replace_all(string contents, string search, string repl) {
-  string str(contents);
-
-  size_t slen = search.length();
-  size_t rlen = repl.length();
-  size_t incr = (rlen > 0) ? rlen : 1;
-
-  if (slen > 0) {
-    size_t found = str.find(search);
-    while ((found != string::npos) && (found < str.length())) {
-      str.replace(found, slen, repl);
-      found = str.find(search, found + incr);
-    }
-  }
-
-  return str;
-}
-
-// XML encoding
-string t_delphi_generator::xml_encode(string contents) {
-  string str(contents);
-
-  // escape the escape
-  str = replace_all(str, "&", "&amp;");
-
-  // other standard XML entities
-  str = replace_all(str, "<", "&lt;");
-  str = replace_all(str, ">", "&gt;");
-
-  return str;
-}
-
-// XML attribute encoding
-string t_delphi_generator::xmlattrib_encode(string contents) {
-  string str(xml_encode(contents));
-
-  // our attribs are enclosed in "
-  str = replace_all(str, "\"", "\\\"");
-
-  return str;
-}
-
-// XML encoding for doc comments
-string t_delphi_generator::xmldoc_encode(string contents) {
-  string str(xml_encode(contents));
-
-  // XMLDoc specific: convert linebreaks into <para>graphs</para>
-  str = replace_all(str, "\r\n", "\r");
-  str = replace_all(str, "\n", "\r");
-  str = replace_all(str, "\r", "</para>\n<para>");
-
-  return str;
-}
-
-void t_delphi_generator::generate_delphi_docstring_comment(ostream& out, string contents) {
-  if (xmldoc_) {
-    generate_docstring_comment(out,
-                               "{$REGION 'XMLDoc'}/// <summary>\n",
-                               "/// ",
-                               "<para>" + contents + "</para>",
-                               "/// </summary>\n{$ENDREGION}\n");
-  }
-}
-
-void t_delphi_generator::generate_delphi_doc(ostream& out, t_field* field) {
-  if (xmldoc_) {
-    if (field->get_type()->is_enum()) {
-      string combined_message = xmldoc_encode(field->get_doc()) + "\n<seealso cref=\""
-                                + xmldoc_encode(type_name(field->get_type())) + "\"/>";
-      generate_delphi_docstring_comment(out, combined_message);
-    } else {
-      generate_delphi_doc(out, (t_doc*)field);
-    }
-  }
-}
-
-void t_delphi_generator::generate_delphi_doc(ostream& out, t_doc* tdoc) {
-  if (tdoc->has_doc() && xmldoc_) {
-    generate_delphi_docstring_comment(out, xmldoc_encode(tdoc->get_doc()));
-  }
-}
-
-void t_delphi_generator::generate_delphi_doc(ostream& out, t_function* tfunction) {
-  if (tfunction->has_doc() && xmldoc_) {
-    stringstream ps;
-    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
-    vector<t_field*>::const_iterator p_iter;
-    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
-      t_field* p = *p_iter;
-      ps << "\n<param name=\"" << xmlattrib_encode(p->get_name()) << "\">";
-      if (p->has_doc()) {
-        std::string str = p->get_doc();
-        str.erase(std::remove(str.begin(), str.end(), '\n'),
-                  str.end()); // remove the newlines that appear from the parser
-        ps << xmldoc_encode(str);
-      }
-      ps << "</param>";
-    }
-    generate_docstring_comment(out,
-                               "{$REGION 'XMLDoc'}",
-                               "/// ",
-                               "<summary><para>" + xmldoc_encode(tfunction->get_doc())
-                               + "</para></summary>" + ps.str(),
-                               "{$ENDREGION}\n");
-  }
-}
-
-bool t_delphi_generator::find_keyword(std::map<std::string, int>& keyword_map, std::string name) {
-  std::string::size_type len = name.length();
-
-  if (len <= 0) {
-    return false;
-  }
-
-  std::string::size_type nlast = name.find_last_of('_');
-
-  if (nlast >= 1) {
-    if (nlast == (len - 1)) {
-      string new_name(name, 0, nlast);
-      return find_keyword(keyword_map, new_name);
-    }
-  }
-  return (keyword_map[name] == 1);
-}
-
-std::string t_delphi_generator::normalize_name(std::string name,
-                                               bool b_method,
-                                               bool b_exception_method) {
-  string tmp(name);
-  std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
-
-  bool b_found = false;
-
-  if (find_keyword(delphi_keywords, tmp)) {
-    b_found = true;
-  } else if (b_method && find_keyword(delphi_reserved_method, tmp)) {
-    b_found = true;
-  } else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) {
-    b_found = true;
-  }
-
-  if (b_found) {
-    return name + "_";
-  } else {
-    return name;
-  }
-}
-
-void t_delphi_generator::create_keywords() {
-  delphi_keywords["and"] = 1;
-  delphi_keywords["end"] = 1;
-  delphi_keywords["interface"] = 1;
-  delphi_keywords["raise"] = 1;
-  delphi_keywords["uses"] = 1;
-  delphi_keywords["array"] = 1;
-  delphi_keywords["except"] = 1;
-  delphi_keywords["is"] = 1;
-  delphi_keywords["record"] = 1;
-  delphi_keywords["var"] = 1;
-  delphi_keywords["as"] = 1;
-  delphi_keywords["exports"] = 1;
-  delphi_keywords["label"] = 1;
-  delphi_keywords["repeat"] = 1;
-  delphi_keywords["while"] = 1;
-  delphi_keywords["asm"] = 1;
-  delphi_keywords["file"] = 1;
-  delphi_keywords["library"] = 1;
-  delphi_keywords["resourcestring"] = 1;
-  delphi_keywords["with"] = 1;
-  delphi_keywords["begin"] = 1;
-  delphi_keywords["finalization"] = 1;
-  delphi_keywords["mod"] = 1;
-  delphi_keywords["set"] = 1;
-  delphi_keywords["xor"] = 1;
-  delphi_keywords["case"] = 1;
-  delphi_keywords["finally"] = 1;
-  delphi_keywords["nil"] = 1;
-  delphi_keywords["shl"] = 1;
-  delphi_keywords["class"] = 1;
-  delphi_keywords["for"] = 1;
-  delphi_keywords["not"] = 1;
-  delphi_keywords["shr"] = 1;
-  delphi_keywords["const"] = 1;
-  delphi_keywords["function"] = 1;
-  delphi_keywords["object"] = 1;
-  delphi_keywords["string"] = 1;
-  delphi_keywords["constructor"] = 1;
-  delphi_keywords["goto"] = 1;
-  delphi_keywords["of"] = 1;
-  delphi_keywords["then"] = 1;
-  delphi_keywords["destructor"] = 1;
-  delphi_keywords["if"] = 1;
-  delphi_keywords["or"] = 1;
-  delphi_keywords["threadvar"] = 1;
-  delphi_keywords["dispinterface"] = 1;
-  delphi_keywords["implementation"] = 1;
-  delphi_keywords["out"] = 1;
-  delphi_keywords["to"] = 1;
-  delphi_keywords["div"] = 1;
-  delphi_keywords["in"] = 1;
-  delphi_keywords["packed"] = 1;
-  delphi_keywords["try"] = 1;
-  delphi_keywords["do"] = 1;
-  delphi_keywords["inherited"] = 1;
-  delphi_keywords["procedure"] = 1;
-  delphi_keywords["type"] = 1;
-  delphi_keywords["downto"] = 1;
-  delphi_keywords["initialization"] = 1;
-  delphi_keywords["program"] = 1;
-  delphi_keywords["unit"] = 1;
-  delphi_keywords["else"] = 1;
-  delphi_keywords["inline"] = 1;
-  delphi_keywords["property"] = 1;
-  delphi_keywords["until"] = 1;
-  delphi_keywords["private"] = 1;
-  delphi_keywords["protected"] = 1;
-  delphi_keywords["public"] = 1;
-  delphi_keywords["published"] = 1;
-  delphi_keywords["automated"] = 1;
-  delphi_keywords["at"] = 1;
-  delphi_keywords["on"] = 1;
-
-  // reserved/predefined variables and types (lowercase!)
-  delphi_keywords["result"] = 1;
-  delphi_keywords["tbytes"] = 1;
-  delphi_keywords["tobject"] = 1;
-  delphi_keywords["tclass"] = 1;
-  delphi_keywords["tinterfacedobject"] = 1;
-
-  delphi_reserved_method["create"] = 1;
-  delphi_reserved_method["free"] = 1;
-  delphi_reserved_method["initinstance"] = 1;
-  delphi_reserved_method["cleanupinstance"] = 1;
-  delphi_reserved_method["classtype"] = 1;
-  delphi_reserved_method["classname"] = 1;
-  delphi_reserved_method["classnameis"] = 1;
-  delphi_reserved_method["classparent"] = 1;
-  delphi_reserved_method["classinfo"] = 1;
-  delphi_reserved_method["instancesize"] = 1;
-  delphi_reserved_method["inheritsfrom"] = 1;
-  delphi_reserved_method["methodaddress"] = 1;
-  delphi_reserved_method["methodaddress"] = 1;
-  delphi_reserved_method["methodname"] = 1;
-  delphi_reserved_method["fieldaddress"] = 1;
-  delphi_reserved_method["fieldaddress"] = 1;
-  delphi_reserved_method["getinterface"] = 1;
-  delphi_reserved_method["getinterfaceentry"] = 1;
-  delphi_reserved_method["getinterfacetable"] = 1;
-  delphi_reserved_method["unitname"] = 1;
-  delphi_reserved_method["equals"] = 1;
-  delphi_reserved_method["gethashcode"] = 1;
-  delphi_reserved_method["tostring"] = 1;
-  delphi_reserved_method["safecallexception"] = 1;
-  delphi_reserved_method["afterconstruction"] = 1;
-  delphi_reserved_method["beforedestruction"] = 1;
-  delphi_reserved_method["dispatch"] = 1;
-  delphi_reserved_method["defaulthandler"] = 1;
-  delphi_reserved_method["newinstance"] = 1;
-  delphi_reserved_method["freeinstance"] = 1;
-  delphi_reserved_method["destroy"] = 1;
-  delphi_reserved_method["read"] = 1;
-  delphi_reserved_method["write"] = 1;
-
-  delphi_reserved_method_exception["setinnerexception"] = 1;
-  delphi_reserved_method_exception["setstackinfo"] = 1;
-  delphi_reserved_method_exception["getstacktrace"] = 1;
-  delphi_reserved_method_exception["raisingexception"] = 1;
-  delphi_reserved_method_exception["createfmt"] = 1;
-  delphi_reserved_method_exception["createres"] = 1;
-  delphi_reserved_method_exception["createresfmt"] = 1;
-  delphi_reserved_method_exception["createhelp"] = 1;
-  delphi_reserved_method_exception["createfmthelp"] = 1;
-  delphi_reserved_method_exception["createreshelp"] = 1;
-  delphi_reserved_method_exception["createresfmthelp"] = 1;
-  delphi_reserved_method_exception["getbaseexception"] = 1;
-  delphi_reserved_method_exception["baseexception"] = 1;
-  delphi_reserved_method_exception["helpcontext"] = 1;
-  delphi_reserved_method_exception["innerexception"] = 1;
-  delphi_reserved_method_exception["message"] = 1;
-  delphi_reserved_method_exception["stacktrace"] = 1;
-  delphi_reserved_method_exception["stackinfo"] = 1;
-  delphi_reserved_method_exception["getexceptionstackinfoproc"] = 1;
-  delphi_reserved_method_exception["getstackinfostringproc"] = 1;
-  delphi_reserved_method_exception["cleanupstackinfoproc"] = 1;
-  delphi_reserved_method_exception["raiseouterexception"] = 1;
-  delphi_reserved_method_exception["throwouterexception"] = 1;
-}
-
-void t_delphi_generator::add_delphi_uses_list(string unitname) {
-  vector<std::string>::const_iterator s_iter;
-  bool found = false;
-  for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
-    if ((*s_iter) == unitname) {
-      found = true;
-      break;
-    }
-  }
-  if (!found) {
-    uses_list.push_back(unitname);
-  }
-}
-
-void t_delphi_generator::init_generator() {
-  indent_impl_ = 0;
-  namespace_name_ = program_->get_namespace("delphi");
-  has_forward = false;
-  has_enum = false;
-  has_const = false;
-  create_keywords();
-  add_delphi_uses_list("Classes");
-  add_delphi_uses_list("SysUtils");
-  add_delphi_uses_list("Generics.Collections");
-  add_delphi_uses_list("Thrift");
-  add_delphi_uses_list("Thrift.Utils");
-  add_delphi_uses_list("Thrift.Collections");
-  add_delphi_uses_list("Thrift.Protocol");
-  add_delphi_uses_list("Thrift.Transport");
-
-  if (register_types_) {
-    add_delphi_uses_list("Thrift.TypeRegistry");
-  }
-
-  init_known_types_list();
-
-  string unitname, nsname;
-  const vector<t_program*>& includes = program_->get_includes();
-  for (size_t i = 0; i < includes.size(); ++i) {
-    unitname = includes[i]->get_name();
-    nsname = includes[i]->get_namespace("delphi");
-    if ("" != nsname) {
-      unitname = nsname;
-    }
-    add_delphi_uses_list(unitname);
-  }
-
-  MKDIR(get_out_dir().c_str());
-}
-
-void t_delphi_generator::close_generator() {
-  std::string unitname = program_name_;
-  if ("" != namespace_name_) {
-    unitname = namespace_name_;
-  }
-
-  for (int i = 0; i < (int)unitname.size(); i++) {
-    if (unitname[i] == ' ') {
-      unitname.replace(i, 1, "_");
-    }
-  }
-
-  std::string f_name = get_out_dir() + "/" + unitname + ".pas";
-  std::ofstream f_all;
-
-  f_all.open(f_name.c_str());
-
-  f_all << autogen_comment() << endl;
-  generate_delphi_doc(f_all, program_);
-  f_all << "unit " << unitname << ";" << endl << endl;
-  f_all << "interface" << endl << endl;
-  f_all << "uses" << endl;
-
-  indent_up();
-
-  vector<std::string>::const_iterator s_iter;
-  for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
-    if (s_iter != uses_list.begin()) {
-      f_all << ",";
-      f_all << endl;
-    }
-    indent(f_all) << *s_iter;
-  }
-
-  f_all << ";" << endl << endl;
-
-  indent_down();
-
-  string tmp_unit(unitname);
-  for (int i = 0; i < (int)tmp_unit.size(); i++) {
-    if (tmp_unit[i] == '.') {
-      tmp_unit.replace(i, 1, "_");
-    }
-  }
-
-  f_all << "const" << endl;
-  indent_up();
-  indent(f_all) << "c" << tmp_unit
-                << "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";"
-                << endl;
-  indent(f_all) << "c" << tmp_unit
-                << "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";"
-                << endl;
-  indent(f_all) << "c" << tmp_unit
-                << "_Option_ConstPrefix    = " << (constprefix_ ? "True" : "False") << ";" << endl;
-  indent(f_all) << "c" << tmp_unit << "_Option_Events         = " << (events_ ? "True" : "False")
-                << ";" << endl;
-  indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc         = " << (xmldoc_ ? "True" : "False")
-                << ";" << endl;
-  indent_down();
-
-  f_all << endl;
-  f_all << "type" << endl;
-  if (has_forward) {
-    f_all << s_forward_decr.str() << endl;
-  }
-  if (has_enum) {
-    indent(f_all) << endl;
-    indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl;
-    f_all << s_enum.str();
-    indent(f_all) << "{$SCOPEDENUMS OFF}" << endl << endl;
-  }
-  f_all << s_struct.str();
-  f_all << s_service.str();
-  f_all << s_const.str();
-  f_all << "implementation" << endl << endl;
-  f_all << s_struct_impl.str();
-  f_all << s_service_impl.str();
-  f_all << s_const_impl.str();
-
-  if (register_types_) {
-    f_all << endl;
-    f_all << "// Type factory methods and registration" << endl;
-    f_all << s_type_factory_funcs.str();
-    f_all << "procedure RegisterTypeFactories;" << endl;
-    f_all << "begin" << endl;
-    f_all << s_type_factory_registration.str();
-    f_all << "end;" << endl;
-  }
-  f_all << endl;
-
-  string constants_class = make_constants_classname();
-
-  f_all << "initialization" << endl;
-  if (has_const) {
-    f_all << "{$IF CompilerVersion < 21.0}  // D2010" << endl;
-    f_all << "  " << constants_class.c_str() << "_Initialize;" << endl;
-    f_all << "{$IFEND}" << endl;
-  }
-  if (register_types_) {
-    f_all << "  RegisterTypeFactories;" << endl;
-  }
-  f_all << endl;
-
-  f_all << "finalization" << endl;
-  if (has_const) {
-    f_all << "{$IF CompilerVersion < 21.0}  // D2010" << endl;
-    f_all << "  " << constants_class.c_str() << "_Finalize;" << endl;
-    f_all << "{$IFEND}" << endl;
-  }
-  f_all << endl << endl;
-
-  f_all << "end." << endl;
-  f_all.close();
-
-  if (!typedefs_pending.empty()) {
-    pwarning(0, "%d typedefs with unresolved type references left:\n", typedefs_pending.size());
-    for (std::list<t_typedef*>::iterator iter = typedefs_pending.begin();
-         typedefs_pending.end() != iter;
-         ++iter) {
-      pwarning(0, "- %s\n", (*iter)->get_symbolic().c_str());
-    }
-  }
-}
-
-void t_delphi_generator::delphi_type_usings(ostream& out) {
-  indent_up();
-  indent(out) << "Classes, SysUtils, Generics.Collections, Thrift.Collections, Thrift.Protocol,"
-              << endl;
-  indent(out) << "Thrift.Transport;" << endl << endl;
-  indent_down();
-}
-
-void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) {
-  // Forward declare struct def
-  has_forward = true;
-  pverbose("forward declaration of %s\n", type_name(tstruct).c_str());
-
-  string what = tstruct->is_xception() ? "class" : "interface";
-
-  indent_up();
-  indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";"
-                         << endl;
-  indent_down();
-
-  add_defined_type(tstruct);
-}
-
-void t_delphi_generator::generate_typedef(t_typedef* ttypedef) {
-  t_type* type = ttypedef->get_type();
-
-  // write now or save for later?
-  if (!is_fully_defined_type(type)) {
-    pverbose("typedef %s: unresolved dependencies found\n", type_name(ttypedef).c_str());
-    typedefs_pending.push_back(ttypedef);
-    return;
-  }
-
-  indent_up();
-  generate_delphi_doc(s_struct, ttypedef);
-  indent(s_struct) << type_name(ttypedef) << " = ";
-
-  // commented out: the benefit is not big enough to risk breaking existing code
-  // bool container = type->is_list() || type->is_map() || type->is_set();
-  // if( ! container)
-  //  s_struct << "type ";  //the "type A = type B" syntax leads to E2574 with generics
-
-  s_struct << type_name(ttypedef->get_type()) << ";" << endl << endl;
-  indent_down();
-
-  add_defined_type(ttypedef);
-}
-
-bool t_delphi_generator::is_fully_defined_type(t_type* ttype) {
-  if ((NULL != ttype->get_program()) && (ttype->get_program() != program_)) {
-    t_scope* scope = ttype->get_program()->scope();
-    if (NULL != scope->get_type(ttype->get_name())) {
-      // printf("type %s found in included scope %s\n", ttype->get_name().c_str(),
-      // ttype->get_program()->get_name().c_str());
-      return true;
-    }
-  }
-
-  if (ttype->is_typedef()) {
-    return (1 == types_known[type_name(ttype)]);
-  }
-
-  if (ttype->is_base_type()) {
-    return (1 == types_known[base_type_name((t_base_type*)ttype)]);
-  } else if (ttype->is_enum()) {
-    return true; // enums are written first, before all other types
-  } else if (ttype->is_map()) {
-    t_map* tmap = (t_map*)ttype;
-    return is_fully_defined_type(tmap->get_key_type())
-           && is_fully_defined_type(tmap->get_val_type());
-  } else if (ttype->is_set()) {
-    t_set* tset = (t_set*)ttype;
-    return is_fully_defined_type(tset->get_elem_type());
-  } else if (ttype->is_list()) {
-    t_list* tlist = (t_list*)ttype;
-    return is_fully_defined_type(tlist->get_elem_type());
-  }
-
-  return (1 == types_known[type_name(ttype)]);
-}
-
-void t_delphi_generator::add_defined_type(t_type* ttype) {
-  // mark as known type
-  types_known[type_name(ttype)] = 1;
-
-  // check all pending typedefs
-  std::list<t_typedef*>::iterator iter;
-  bool more = true;
-  while (more && (!typedefs_pending.empty())) {
-    more = false;
-
-    for (iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) {
-      t_typedef* ttypedef = (*iter);
-      if (is_fully_defined_type(ttypedef->get_type())) {
-        pverbose("typedef %s: all pending references are now resolved\n",
-                 type_name(ttypedef).c_str());
-        typedefs_pending.erase(iter);
-        generate_typedef(ttypedef);
-        more = true;
-        break;
-      }
-    }
-  }
-}
-
-void t_delphi_generator::init_known_types_list() {
-  // known base types
-  types_known[type_name(g_type_string)] = 1;
-  types_known[type_name(g_type_binary)] = 1;
-  types_known[type_name(g_type_bool)] = 1;
-  types_known[type_name(g_type_i8)] = 1;
-  types_known[type_name(g_type_i16)] = 1;
-  types_known[type_name(g_type_i32)] = 1;
-  types_known[type_name(g_type_i64)] = 1;
-  types_known[type_name(g_type_double)] = 1;
-}
-
-void t_delphi_generator::generate_enum(t_enum* tenum) {
-  has_enum = true;
-  indent_up();
-  generate_delphi_doc(s_enum, tenum);
-  indent(s_enum) << type_name(tenum, true, true) << " = "
-                 << "(" << endl;
-  indent_up();
-  vector<t_enum_value*> constants = tenum->get_constants();
-  if (constants.empty()) {
-    indent(s_enum) << "dummy = 0  // empty enums are not allowed";
-  } else {
-    vector<t_enum_value*>::iterator c_iter;
-    for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-      int value = (*c_iter)->get_value();
-      if (c_iter != constants.begin()) {
-        s_enum << ",";
-        s_enum << endl;
-      }
-      generate_delphi_doc(s_enum, *c_iter);
-      indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value;
-    }
-  }
-  s_enum << endl;
-  indent_down();
-  indent(s_enum) << ");" << endl << endl;
-  indent_down();
-}
-
-std::string t_delphi_generator::make_valid_delphi_identifier(std::string const& fromName) {
-  std::string str = fromName;
-  if (str.empty()) {
-    return str;
-  }
-
-  // tests rely on this
-  assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
-
-  // if the first letter is a number, we add an additional underscore in front of it
-  char c = str.at(0);
-  if (('0' <= c) && (c <= '9')) {
-    str = "_" + str;
-  }
-
-  // following chars: letter, number or underscore
-  for (size_t i = 0; i < str.size(); ++i) {
-    c = str.at(i);
-    if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9'))
-        && ('_' != c)) {
-      str.replace(i, 1, "_");
-    }
-  }
-
-  return str;
-}
-
-std::string t_delphi_generator::make_constants_classname() {
-  if (constprefix_) {
-    return make_valid_delphi_identifier("T" + program_name_ + "Constants");
-  } else {
-    return "TConstants"; // compatibility
-  }
-}
-
-void t_delphi_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-
-  has_const = true;
-  string constants_class = make_constants_classname();
-
-  indent_up();
-  indent(s_const) << constants_class.c_str() << " = class" << endl;
-  indent(s_const) << "private" << endl;
-  indent_up();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    if (const_needs_var((*c_iter)->get_type())) {
-      print_private_field(s_const,
-                          normalize_name((*c_iter)->get_name()),
-                          (*c_iter)->get_type(),
-                          (*c_iter)->get_value());
-    }
-  }
-  indent_down();
-  indent(s_const) << "public" << endl;
-  indent_up();
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    generate_delphi_doc(s_const, *c_iter);
-    print_const_prop(s_const,
-                     normalize_name((*c_iter)->get_name()),
-                     (*c_iter)->get_type(),
-                     (*c_iter)->get_value());
-  }
-  indent(s_const) << "{$IF CompilerVersion >= 21.0}" << endl;
-  indent(s_const) << "class constructor Create;" << endl;
-  indent(s_const) << "class destructor Destroy;" << endl;
-  indent(s_const) << "{$IFEND}" << endl;
-  indent_down();
-  indent(s_const) << "end;" << endl << endl;
-  indent_down();
-
-  std::ostringstream vars, code;
-
-  indent_up_impl();
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    initialize_field(vars,
-                     code,
-                     "F" + prop_name((*c_iter)->get_name()),
-                     (*c_iter)->get_type(),
-                     (*c_iter)->get_value());
-  }
-  indent_down_impl();
-
-  indent_impl(s_const_impl) << "{$IF CompilerVersion >= 21.0}" << endl;
-  indent_impl(s_const_impl) << "class constructor " << constants_class.c_str() << ".Create;"
-                            << endl;
-
-  if (!vars.str().empty()) {
-    indent_impl(s_const_impl) << "var" << endl;
-    s_const_impl << vars.str();
-  }
-  indent_impl(s_const_impl) << "begin" << endl;
-  if (!code.str().empty()) {
-    s_const_impl << code.str();
-  }
-  indent_impl(s_const_impl) << "end;" << endl << endl;
-  indent_impl(s_const_impl) << "class destructor " << constants_class.c_str() << ".Destroy;"
-                            << endl;
-  indent_impl(s_const_impl) << "begin" << endl;
-  indent_up_impl();
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    if (const_needs_var((*c_iter)->get_type())) {
-      finalize_field(s_const_impl,
-                     normalize_name((*c_iter)->get_name()),
-                     (*c_iter)->get_type(),
-                     (*c_iter)->get_value());
-    }
-  }
-  indent_impl(s_const_impl) << "inherited;" << endl;
-  indent_down_impl();
-  indent_impl(s_const_impl) << "end;" << endl;
-  indent_impl(s_const_impl) << "{$ELSE}" << endl;
-
-  vars.str("");
-  code.str("");
-
-  indent_up_impl();
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    if (const_needs_var((*c_iter)->get_type())) {
-      initialize_field(vars,
-                       code,
-                       constants_class + ".F" + prop_name((*c_iter)->get_name()),
-                       (*c_iter)->get_type(),
-                       (*c_iter)->get_value());
-    }
-  }
-  indent_down_impl();
-
-  indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Initialize;" << endl;
-  if (!vars.str().empty()) {
-    indent_impl(s_const_impl) << "var" << endl;
-    s_const_impl << vars.str();
-  }
-  indent_impl(s_const_impl) << "begin" << endl;
-  if (!code.str().empty()) {
-    s_const_impl << code.str();
-  }
-  indent_impl(s_const_impl) << "end;" << endl << endl;
-
-  indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Finalize;" << endl;
-  indent_impl(s_const_impl) << "begin" << endl;
-  indent_up_impl();
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    finalize_field(s_const_impl,
-                   normalize_name((*c_iter)->get_name()),
-                   (*c_iter)->get_type(),
-                   (*c_iter)->get_value(),
-                   constants_class);
-  }
-  indent_down_impl();
-  indent_impl(s_const_impl) << "end;" << endl;
-  indent_impl(s_const_impl) << "{$IFEND}" << endl << endl;
-}
-
-void t_delphi_generator::print_const_def_value(std::ostream& vars,
-                                               std::ostream& out,
-                                               string name,
-                                               t_type* type,
-                                               t_const_value* value,
-                                               string cls_nm) {
-
-  string cls_prefix;
-
-  if (cls_nm == "") {
-    cls_prefix = "";
-  } else {
-    cls_prefix = cls_nm + ".";
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(vars, out, name, field_type, v_iter->second);
-      indent_impl(out) << cls_prefix << normalize_name(name) << "."
-                       << prop_name(v_iter->first->get_string(), type->is_xception())
-                       << " := " << val << ";" << endl;
-    }
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(vars, out, name, ktype, v_iter->first);
-      string val = render_const_value(vars, out, name, vtype, v_iter->second);
-      indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]"
-                       << " := " << val << ";" << endl;
-    }
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(vars, out, name, etype, *v_iter);
-      indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << endl;
-    }
-  }
-}
-
-void t_delphi_generator::print_private_field(std::ostream& out,
-                                             string name,
-                                             t_type* type,
-                                             t_const_value* value) {
-  (void)value;
-  indent(out) << "class var F" << name << ": " << type_name(type) << ";" << endl;
-}
-
-bool t_delphi_generator::const_needs_var(t_type* type) {
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
-  return (!truetype->is_base_type());
-}
-
-void t_delphi_generator::print_const_prop(std::ostream& out,
-                                          string name,
-                                          t_type* type,
-                                          t_const_value* value) {
-  (void)value;
-  if (const_needs_var(type)) {
-    indent(out) << "class property " << name << ": " << type_name(type) << " read F" << name << ";"
-                << endl;
-  } else {
-    std::ostringstream vars; // dummy
-    string v2 = render_const_value(vars, out, name, type, value);
-    indent(out) << "const " << name << " = " << v2 << ";" << endl;
-  }
-}
-
-void t_delphi_generator::print_const_value(std::ostream& vars,
-                                           std::ostream& out,
-                                           string name,
-                                           t_type* type,
-                                           t_const_value* value) {
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
-
-  if (truetype->is_base_type()) {
-    // already done
-    // string v2 = render_const_value( vars, out, name, type, value);
-    // indent_impl(out) << name << " := " << v2 << ";" << endl;
-  } else if (truetype->is_enum()) {
-    indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name()
-                     << ";" << endl;
-  } else {
-    string typname;
-    typname = type_name(truetype, true, false, type->is_xception(), type->is_xception());
-    indent_impl(out) << name << " := " << typname << ".Create;" << endl;
-    print_const_def_value(vars, out, name, truetype, value);
-  }
-}
-
-void t_delphi_generator::initialize_field(std::ostream& vars,
-                                          std::ostream& out,
-                                          string name,
-                                          t_type* type,
-                                          t_const_value* value) {
-  print_const_value(vars, out, name, type, value);
-}
-
-void t_delphi_generator::finalize_field(std::ostream& out,
-                                        string name,
-                                        t_type* type,
-                                        t_const_value* value,
-                                        string cls_nm) {
-  (void)out;
-  (void)name;
-  (void)type;
-  (void)value;
-  (void)cls_nm;
-}
-
-string t_delphi_generator::render_const_value(ostream& vars,
-                                              ostream& out,
-                                              string name,
-                                              t_type* type,
-                                              t_const_value* value) {
-  (void)name;
-
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
-
-  std::ostringstream render;
-
-  if (truetype->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << "'" << get_escaped_string(value) << "'";
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "True" : "False");
-      break;
-    case t_base_type::TYPE_I8:
-      render << "ShortInt( " << value->get_integer() << ")";
-      break;
-    case t_base_type::TYPE_I16:
-      render << "SmallInt( " << value->get_integer() << ")";
-      break;
-    case t_base_type::TYPE_I32:
-      render << "LongInt( " << value->get_integer() << ")";
-      break;
-    case t_base_type::TYPE_I64:
-      render << "Int64( " << value->get_integer() << ")";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << value->get_integer() << ".0"; // make it a double constant by adding ".0"
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (truetype->is_enum()) {
-    render << type_name(type, false) << "." << value->get_identifier_name();
-  } else {
-    string t = tmp("tmp");
-    vars << "  " << t << " : " << type_name(type) << ";" << endl;
-    print_const_value(vars, out, t, type, value);
-    render << t;
-  }
-
-  return render.str();
-}
-
-void t_delphi_generator::generate_struct(t_struct* tstruct) {
-  generate_delphi_struct(tstruct, false);
-}
-
-void t_delphi_generator::generate_xception(t_struct* txception) {
-  generate_delphi_struct(txception, true);
-}
-
-void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) {
-  indent_up();
-  generate_delphi_struct_definition(s_struct, tstruct, is_exception);
-  indent_down();
-
-  add_defined_type(tstruct);
-
-  generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception);
-  if (register_types_) {
-    generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception);
-    generate_delphi_struct_type_factory_registration(s_type_factory_registration,
-                                                     "",
-                                                     tstruct,
-                                                     is_exception);
-  }
-}
-
-void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
-                                                     string cls_prefix,
-                                                     t_struct* tstruct,
-                                                     bool is_exception,
-                                                     bool is_result,
-                                                     bool is_x_factory) {
-
-  if (is_exception && (!is_x_factory)) {
-    generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true);
-  }
-
-  string cls_nm;
-
-  string exception_factory_name;
-
-  if (is_exception) {
-    exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
-  }
-
-  if (is_exception) {
-    cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
-  } else {
-    cls_nm = type_name(tstruct, true, false);
-  }
-
-  std::ostringstream vars, code;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  indent_up_impl();
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
-    if ((*m_iter)->get_value() != NULL) {
-      initialize_field(vars,
-                       code,
-                       "F" + prop_name((*m_iter)->get_name(), is_exception),
-                       t,
-                       (*m_iter)->get_value());
-      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;"
-                          << endl;
-      }
-    }
-  }
-  indent_down_impl();
-
-  indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
-                   << "Create;" << endl;
-
-  if (!vars.str().empty()) {
-    out << "var" << endl;
-    out << vars.str();
-  }
-
-  indent_impl(out) << "begin" << endl;
-  indent_up_impl();
-  if (is_exception && (!is_x_factory)) {
-    indent_impl(out) << "inherited Create('');" << endl;
-    indent_impl(out) << "F" << exception_factory_name << " := T" << exception_factory_name
-                     << "Impl.Create;" << endl;
-  } else {
-    indent_impl(out) << "inherited;" << endl;
-  }
-
-  if (!code.str().empty()) {
-    out << code.str();
-  }
-
-  indent_down_impl();
-  indent_impl(out) << "end;" << endl << endl;
-
-  if ((members.size() > 0) && is_exception && (!is_x_factory)) {
-    indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
-                     << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");"
-                     << endl;
-    indent_impl(out) << "begin" << endl;
-    indent_up_impl();
-    indent_impl(out) << "Create;" << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      string propname = prop_name((*m_iter)->get_name(), is_exception);
-      string param_name = constructor_param_name((*m_iter)->get_name());
-      indent_impl(out) << propname << " := " << param_name << ";" << endl;
-    }
-    indent_impl(out) << "UpdateMessageProperty;" << endl;
-    indent_down_impl();
-    indent_impl(out) << "end;" << endl << endl;
-  }
-
-  indent_impl(out) << "destructor " << cls_prefix << cls_nm << "."
-                   << "Destroy;" << endl;
-  indent_impl(out) << "begin" << endl;
-  indent_up_impl();
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
-    finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value());
-  }
-
-  indent_impl(out) << "inherited;" << endl;
-  indent_down_impl();
-  indent_impl(out) << "end;" << endl << endl;
-
-  if (tstruct->is_union()) {
-    indent_impl(out) << "procedure " << cls_prefix << cls_nm << "."
-                     << "ClearUnionValues;" << endl;
-    indent_impl(out) << "begin" << endl;
-    indent_up_impl();
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = (*m_iter)->get_type();
-      while (t->is_typedef()) {
-        t = ((t_typedef*)t)->get_type();
-      }
-
-      generate_delphi_clear_union_value(out,
-                                        cls_prefix,
-                                        cls_nm,
-                                        t,
-                                        *m_iter,
-                                        "F",
-                                        is_exception,
-                                        tstruct->is_union(),
-                                        is_x_factory,
-                                        exception_factory_name);
-    }
-    indent_down_impl();
-    indent_impl(out) << "end;" << endl << endl;
-  }
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
-    generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
-    generate_delphi_property_writer_impl(out,
-                                         cls_prefix,
-                                         cls_nm,
-                                         t,
-                                         *m_iter,
-                                         "F",
-                                         is_exception,
-                                         tstruct->is_union(),
-                                         is_x_factory,
-                                         exception_factory_name);
-    if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-      generate_delphi_isset_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
-    }
-  }
-
-  if ((!is_exception) || is_x_factory) {
-    generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception);
-    if (is_result) {
-      generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception);
-    } else {
-      generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception);
-    }
-  }
-  generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
-
-  if (is_exception && is_x_factory) {
-    generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception);
-  }
-}
-
-void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) {
-  string struct_intf_name = type_name(tstruct);
-  out << "Create_";
-  out << struct_intf_name;
-  out << "_Impl";
-}
-
-void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out,
-                                                             string cls_prefix,
-                                                             t_struct* tstruct,
-                                                             bool is_exception,
-                                                             bool is_result,
-                                                             bool is_x_factory) {
-  (void)cls_prefix;
-  if (is_exception)
-    return;
-  if (is_result)
-    return;
-  if (is_x_factory)
-    return;
-
-  string struct_intf_name = type_name(tstruct);
-  string cls_nm = type_name(tstruct, true, false);
-
-  out << "function ";
-  print_delphi_struct_type_factory_func(out, tstruct);
-  out << ": ";
-  out << struct_intf_name;
-  out << ";" << endl;
-  out << "begin" << endl;
-  indent_up();
-  indent(out) << "Result := " << cls_nm << ".Create;" << endl;
-  indent_down();
-  out << "end;" << endl << endl;
-}
-
-void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out,
-                                                                          string cls_prefix,
-                                                                          t_struct* tstruct,
-                                                                          bool is_exception,
-                                                                          bool is_result,
-                                                                          bool is_x_factory) {
-  (void)cls_prefix;
-  if (is_exception)
-    return;
-  if (is_result)
-    return;
-  if (is_x_factory)
-    return;
-
-  string struct_intf_name = type_name(tstruct);
-
-  indent(out) << "  TypeRegistry.RegisterTypeFactory<" << struct_intf_name << ">(";
-  print_delphi_struct_type_factory_func(out, tstruct);
-  out << ");";
-  out << endl;
-}
-
-void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
-                                                           t_struct* tstruct,
-                                                           bool is_exception,
-                                                           bool in_class,
-                                                           bool is_result,
-                                                           bool is_x_factory) {
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-  string struct_intf_name;
-  string struct_name;
-  string isset_name;
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
-
-  if (is_exception) {
-    struct_intf_name = type_name(tstruct, false, false, true);
-  } else {
-    struct_intf_name = type_name(tstruct);
-  }
-
-  if (is_exception) {
-    struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory);
-  } else {
-    struct_name = type_name(tstruct, true);
-  }
-
-  if ((!is_exception) || is_x_factory) {
-
-    generate_delphi_doc(out, tstruct);
-    indent(out) << struct_intf_name << " = interface(IBase)" << endl;
-    indent_up();
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      generate_delphi_property_reader_definition(out, *m_iter, is_exception);
-      generate_delphi_property_writer_definition(out, *m_iter, is_exception);
-    }
-
-    if (is_x_factory) {
-      out << endl;
-      indent(out) << "// Create Exception Object" << endl;
-      indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl;
-    }
-
-    if (members.size() > 0) {
-      out << endl;
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        generate_property(out, *m_iter, true, is_exception);
-      }
-    }
-
-    if (members.size() > 0) {
-      out << endl;
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-          generate_delphi_isset_reader_definition(out, *m_iter, is_exception);
-        }
-      }
-    }
-
-    if (members.size() > 0) {
-      out << endl;
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-          isset_name = "__isset_" + prop_name(*m_iter, is_exception);
-          indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";"
-                      << endl;
-        }
-      }
-    }
-
-    indent_down();
-    indent(out) << "end;" << endl << endl;
-  }
-
-  generate_delphi_doc(out, tstruct);
-  indent(out) << struct_name << " = ";
-  if (is_final) {
-    out << "sealed ";
-  }
-  out << "class(";
-  if (is_exception && (!is_x_factory)) {
-    out << "TException";
-  } else {
-    out << "TInterfacedObject, IBase, " << struct_intf_name;
-  }
-  out << ")" << endl;
-
-  if (is_exception && (!is_x_factory)) {
-    indent(out) << "public" << endl;
-    indent_up();
-    indent(out) << "type" << endl;
-    indent_up();
-    generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true);
-    indent_down();
-    indent_down();
-  }
-
-  indent(out) << "private" << endl;
-  indent_up();
-
-  if (is_exception && (!is_x_factory)) {
-    indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << endl << endl;
-  }
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << declare_field(*m_iter, false, "F", is_exception) << endl;
-  }
-
-  if (members.size() > 0) {
-    indent(out) << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        isset_name = "F__isset_" + prop_name(*m_iter, is_exception);
-        indent(out) << isset_name << ": Boolean;" << endl;
-      }
-    }
-  }
-
-  indent(out) << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_delphi_property_reader_definition(out, *m_iter, is_exception);
-    generate_delphi_property_writer_definition(out, *m_iter, is_exception);
-  }
-
-  if (tstruct->is_union()) {
-    out << endl;
-    indent(out) << "// Clear values(for union's property setter)" << endl;
-    indent(out) << "procedure ClearUnionValues;" << endl;
-  }
-
-  if (members.size() > 0) {
-    out << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        isset_name = "__isset_" + prop_name(*m_iter, is_exception);
-        indent(out) << "function Get" << isset_name << ": Boolean;" << endl;
-      }
-    }
-  }
-
-  indent_down();
-
-  indent(out) << "public" << endl;
-  indent_up();
-
-  if ((members.size() > 0) && is_exception && (!is_x_factory)) {
-    indent(out) << "constructor Create; overload;" << endl;
-    indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent())
-                << "); overload;" << endl;
-  } else {
-    indent(out) << "constructor Create;" << endl;
-  }
-
-  indent(out) << "destructor Destroy; override;" << endl;
-
-  out << endl;
-  indent(out) << "function ToString: string; override;" << endl;
-
-  if (is_exception && (!is_x_factory)) {
-    out << endl;
-    indent(out) << "// Exception Factory" << endl;
-    indent(out) << "property " << exception_factory_name << ": " << struct_intf_name << " read F"
-                << exception_factory_name << " write F" << exception_factory_name << ";" << endl;
-  }
-
-  if ((!is_exception) || is_x_factory) {
-    out << endl;
-    indent(out) << "// IBase" << endl;
-    indent(out) << "procedure Read( const iprot: IProtocol);" << endl;
-    indent(out) << "procedure Write( const oprot: IProtocol);" << endl;
-  }
-
-  if (is_exception && is_x_factory) {
-    out << endl;
-    indent(out) << "// Create Exception Object" << endl;
-    indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl;
-  }
-
-  if (members.size() > 0) {
-    out << endl;
-    indent(out) << "// Properties" << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      generate_property(out, *m_iter, true, is_exception);
-    }
-  }
-
-  if (members.size() > 0) {
-    out << endl;
-    indent(out) << "// isset" << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        isset_name = "__isset_" + prop_name(*m_iter, is_exception);
-        indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";"
-                    << endl;
-      }
-    }
-  }
-
-  indent_down();
-  indent(out) << "end;" << endl << endl;
-}
-
-void t_delphi_generator::generate_service(t_service* tservice) {
-  indent_up();
-  generate_delphi_doc(s_service, tservice);
-  indent(s_service) << normalize_clsnm(service_name_, "T") << " = class" << endl;
-  indent(s_service) << "public" << endl;
-  indent_up();
-  indent(s_service) << "type" << endl;
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-  indent_down();
-  indent_down();
-  indent(s_service) << "end;" << endl;
-  indent(s_service) << endl;
-  indent_down();
-}
-
-void t_delphi_generator::generate_service_interface(t_service* tservice) {
-  string extends = "";
-  string extends_iface = "";
-
-  indent_up();
-
-  generate_delphi_doc(s_service, tservice);
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends(), true, true);
-    extends_iface = extends + ".Iface";
-    generate_delphi_doc(s_service, tservice);
-    indent(s_service) << "Iface = interface(" << extends_iface << ")" << endl;
-  } else {
-    indent(s_service) << "Iface = interface" << endl;
-  }
-
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_delphi_doc(s_service, *f_iter);
-    indent(s_service) << function_signature(*f_iter) << endl;
-  }
-  indent_down();
-  indent(s_service) << "end;" << endl << endl;
-
-  indent_down();
-}
-
-void t_delphi_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_delphi_struct_definition(s_service, ts, false, true);
-    generate_delphi_struct_impl(s_service_impl,
-                                normalize_clsnm(service_name_, "T") + ".",
-                                ts,
-                                false);
-    generate_function_helpers(*f_iter);
-  }
-}
-
-void t_delphi_generator::generate_service_client(t_service* tservice) {
-  indent_up();
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_client = extends + ".Client, ";
-  }
-
-  generate_delphi_doc(s_service, tservice);
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends(), true, true);
-    extends_client = extends + ".TClient";
-    indent(s_service) << "TClient = class(" << extends_client << ", Iface)" << endl;
-  } else {
-    indent(s_service) << "TClient = class( TInterfacedObject, Iface)" << endl;
-  }
-
-  indent(s_service) << "public" << endl;
-  indent_up();
-
-  indent(s_service) << "constructor Create( prot: IProtocol); overload;" << endl;
-
-  indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T")
-                              << ".TClient.Create( prot: IProtocol);" << endl;
-  indent_impl(s_service_impl) << "begin" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "Create( prot, prot );" << endl;
-  indent_down_impl();
-  indent_impl(s_service_impl) << "end;" << endl << endl;
-
-  indent(s_service)
-      << "constructor Create( const iprot: IProtocol; const oprot: IProtocol); overload;" << endl;
-
-  indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T")
-                              << ".TClient.Create( const iprot: IProtocol; const oprot: IProtocol);"
-                              << endl;
-  indent_impl(s_service_impl) << "begin" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "inherited Create;" << endl;
-  indent_impl(s_service_impl) << "iprot_ := iprot;" << endl;
-  indent_impl(s_service_impl) << "oprot_ := oprot;" << endl;
-  indent_down_impl();
-  indent_impl(s_service_impl) << "end;" << endl << endl;
-
-  indent_down();
-
-  if (extends.empty()) {
-    indent(s_service) << "protected" << endl;
-    indent_up();
-    indent(s_service) << "iprot_: IProtocol;" << endl;
-    indent(s_service) << "oprot_: IProtocol;" << endl;
-    indent(s_service) << "seqid_: Integer;" << endl;
-    indent_down();
-
-    indent(s_service) << "public" << endl;
-    indent_up();
-    indent(s_service) << "property InputProtocol: IProtocol read iprot_;" << endl;
-    indent(s_service) << "property OutputProtocol: IProtocol read oprot_;" << endl;
-    indent_down();
-  }
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-
-  indent(s_service) << "protected" << endl;
-  indent_up();
-  indent(s_service) << "// Iface" << endl;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-    generate_delphi_doc(s_service, *f_iter);
-    indent(s_service) << function_signature(*f_iter) << endl;
-  }
-  indent_down();
-
-  indent(s_service) << "public" << endl;
-  indent_up();
-
-  string full_cls = normalize_clsnm(service_name_, "T") + ".TClient";
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-
-    indent_impl(s_service_impl) << function_signature(*f_iter, full_cls) << endl;
-    indent_impl(s_service_impl) << "begin" << endl;
-    indent_up_impl();
-    indent_impl(s_service_impl) << "send_" << funname << "(";
-
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        s_service_impl << ", ";
-      }
-      s_service_impl << normalize_name((*fld_iter)->get_name());
-    }
-    s_service_impl << ");" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      s_service_impl << indent_impl();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        s_service_impl << "Result := ";
-      }
-      s_service_impl << "recv_" << funname << "();" << endl;
-    }
-
-    indent_down_impl();
-    indent_impl(s_service_impl) << "end;" << endl << endl;
-
-    t_function send_function(g_type_void,
-                             string("send_") + (*f_iter)->get_name(),
-                             (*f_iter)->get_arglist());
-
-    string argsname = (*f_iter)->get_name() + "_args";
-    string args_clsnm = normalize_clsnm(argsname, "T");
-    string args_intfnm = normalize_clsnm(argsname, "I");
-
-    string argsvar = tmp("_args");
-    string msgvar = tmp("_msg");
-
-    indent(s_service) << function_signature(&send_function) << endl;
-    indent_impl(s_service_impl) << function_signature(&send_function, full_cls) << endl;
-    indent_impl(s_service_impl) << "var" << endl;
-    indent_up_impl();
-    indent_impl(s_service_impl) << argsvar << " : " << args_intfnm << ";" << endl;
-    indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.IMessage;" << endl;
-    indent_down_impl();
-    indent_impl(s_service_impl) << "begin" << endl;
-    indent_up_impl();
-
-    indent_impl(s_service_impl) << "seqid_ := seqid_ + 1;" << endl;
-    indent_impl(s_service_impl) << msgvar << " := Thrift.Protocol.TMessageImpl.Create('" << funname
-                                << "', " << ((*f_iter)->is_oneway() ? "TMessageType.Oneway"
-                                                                    : "TMessageType.Call")
-                                << ", seqid_);" << endl;
-
-    indent_impl(s_service_impl) << "oprot_.WriteMessageBegin( " << msgvar << " );" << endl;
-    indent_impl(s_service_impl) << argsvar << " := " << args_clsnm << "Impl.Create();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter)
-                                  << " := " << normalize_name((*fld_iter)->get_name()) << ";"
-                                  << endl;
-    }
-    indent_impl(s_service_impl) << argsvar << ".Write(oprot_);" << endl;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter)
-                                  << " := " << empty_value((*fld_iter)->get_type()) << ";" << endl;
-    }
-
-    indent_impl(s_service_impl) << "oprot_.WriteMessageEnd();" << endl;
-    indent_impl(s_service_impl) << "oprot_.Transport.Flush();" << endl;
-
-    indent_down_impl();
-    indent_impl(s_service_impl) << "end;" << endl << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      string org_resultname = (*f_iter)->get_name() + "_result";
-      string result_clsnm = normalize_clsnm(org_resultname, "T");
-      string result_intfnm = normalize_clsnm(org_resultname, "I");
-
-      t_struct noargs(program_);
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs,
-                               (*f_iter)->get_xceptions());
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-
-      string exceptvar = tmp("_ex");
-      string appexvar = tmp("_ax");
-      string retvar = tmp("_ret");
-
-      indent(s_service) << function_signature(&recv_function) << endl;
-      indent_impl(s_service_impl) << function_signature(&recv_function, full_cls) << endl;
-      indent_impl(s_service_impl) << "var" << endl;
-      indent_up_impl();
-      indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.IMessage;" << endl;
-      if (xceptions.size() > 0) {
-        indent_impl(s_service_impl) << exceptvar << " : Exception;" << endl;
-      }
-      indent_impl(s_service_impl) << appexvar << " : TApplicationException;" << endl;
-      indent_impl(s_service_impl) << retvar << " : " << result_intfnm << ";" << endl;
-
-      indent_down_impl();
-      indent_impl(s_service_impl) << "begin" << endl;
-      indent_up_impl();
-      indent_impl(s_service_impl) << msgvar << " := iprot_.ReadMessageBegin();" << endl;
-      indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then"
-                                  << endl;
-      indent_impl(s_service_impl) << "begin" << endl;
-      indent_up_impl();
-      indent_impl(s_service_impl) << appexvar << " := TApplicationException.Read(iprot_);" << endl;
-      indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
-      indent_impl(s_service_impl) << "raise " << appexvar << ";" << endl;
-      indent_down_impl();
-      indent_impl(s_service_impl) << "end;" << endl;
-
-      indent_impl(s_service_impl) << retvar << " := " << result_clsnm << "Impl.Create();" << endl;
-      indent_impl(s_service_impl) << retvar << ".Read(iprot_);" << endl;
-      indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
-
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then" << endl;
-        indent_impl(s_service_impl) << "begin" << endl;
-        indent_up_impl();
-        indent_impl(s_service_impl) << "Result := " << retvar << ".Success;" << endl;
-        t_type* type = (*f_iter)->get_returntype();
-        if (type->is_struct() || type->is_xception() || type->is_map() || type->is_list()
-            || type->is_set()) {
-          indent_impl(s_service_impl) << retvar << ".Success := nil;" << endl;
-        }
-        indent_impl(s_service_impl) << "Exit;" << endl;
-        indent_down_impl();
-        indent_impl(s_service_impl) << "end;" << endl;
-      }
-
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter)
-                                    << ") then" << endl;
-        indent_impl(s_service_impl) << "begin" << endl;
-        indent_up_impl();
-        indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter)
-                                    << ".CreateException;" << endl;
-        indent_impl(s_service_impl) << "raise " << exceptvar << ";" << endl;
-        indent_down_impl();
-        indent_impl(s_service_impl) << "end;" << endl;
-      }
-
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent_impl(s_service_impl)
-			<< "raise TApplicationExceptionMissingResult.Create('"
-            << (*f_iter)->get_name() << " failed: unknown result');" << endl;
-      }
-
-      indent_down_impl();
-      indent_impl(s_service_impl) << "end;" << endl << endl;
-    }
-  }
-
-  indent_down();
-  indent(s_service) << "end;" << endl << endl;
-}
-
-void t_delphi_generator::generate_service_server(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-
-  string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl";
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends(), true, true);
-    extends_processor = extends + ".TProcessorImpl";
-    indent(s_service) << "TProcessorImpl = class(" << extends_processor << ", IProcessor)" << endl;
-  } else {
-    indent(s_service) << "TProcessorImpl = class( TInterfacedObject, IProcessor)" << endl;
-  }
-
-  indent(s_service) << "public" << endl;
-  indent_up();
-  indent(s_service) << "constructor Create( iface_: Iface );" << endl;
-  indent(s_service) << "destructor Destroy; override;" << endl;
-  indent_down();
-
-  indent_impl(s_service_impl) << "constructor " << full_cls << ".Create( iface_: Iface );" << endl;
-  indent_impl(s_service_impl) << "begin" << endl;
-  indent_up_impl();
-  if (tservice->get_extends() != NULL) {
-    indent_impl(s_service_impl) << "inherited Create( iface_);" << endl;
-  } else {
-    indent_impl(s_service_impl) << "inherited Create;" << endl;
-  }
-  indent_impl(s_service_impl) << "Self.iface_ := iface_;" << endl;
-  if (tservice->get_extends() != NULL) {
-    indent_impl(s_service_impl) << "ASSERT( processMap_ <> nil);  // inherited" << endl;
-  } else {
-    indent_impl(s_service_impl)
-        << "processMap_ := TThriftDictionaryImpl<string, TProcessFunction>.Create;" << endl;
-  }
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    indent_impl(s_service_impl) << "processMap_.AddOrSetValue( '" << (*f_iter)->get_name() << "', "
-                                << (*f_iter)->get_name() << "_Process);" << endl;
-  }
-  indent_down_impl();
-  indent_impl(s_service_impl) << "end;" << endl << endl;
-
-  indent_impl(s_service_impl) << "destructor " << full_cls << ".Destroy;" << endl;
-  indent_impl(s_service_impl) << "begin" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "inherited;" << endl;
-  indent_down_impl();
-  indent_impl(s_service_impl) << "end;" << endl << endl;
-
-  indent(s_service) << "private" << endl;
-  indent_up();
-  indent(s_service) << "iface_: Iface;" << endl;
-  indent_down();
-
-  if (tservice->get_extends() == NULL) {
-    indent(s_service) << "protected" << endl;
-    indent_up();
-    indent(s_service) << "type" << endl;
-    indent_up();
-    indent(s_service) << "TProcessFunction = reference to procedure( seqid: Integer; const iprot: "
-                         "IProtocol; const oprot: IProtocol"
-                      << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
-    indent_down();
-    indent_down();
-    indent(s_service) << "protected" << endl;
-    indent_up();
-    indent(s_service) << "processMap_: IThriftDictionary<string, TProcessFunction>;" << endl;
-    indent_down();
-  }
-
-  indent(s_service) << "public" << endl;
-  indent_up();
-  if (extends.empty()) {
-    indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
-                         "events : IProcessorEvents): Boolean;" << endl;
-  } else {
-    indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
-                         "events : IProcessorEvents): Boolean; reintroduce;" << endl;
-  }
-
-  indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; "
-                                                            "const oprot: IProtocol; const events "
-                                                            ": IProcessorEvents): Boolean;" << endl;
-  ;
-  indent_impl(s_service_impl) << "var" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "msg : Thrift.Protocol.IMessage;" << endl;
-  indent_impl(s_service_impl) << "fn : TProcessFunction;" << endl;
-  indent_impl(s_service_impl) << "x : TApplicationException;" << endl;
-  if (events_) {
-    indent_impl(s_service_impl) << "context : IRequestEvents;" << endl;
-  }
-  indent_down_impl();
-  indent_impl(s_service_impl) << "begin" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "try" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl;
-  indent_impl(s_service_impl) << "fn := nil;" << endl;
-  indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl;
-  indent_impl(s_service_impl) << "or not Assigned(fn) then" << endl;
-  indent_impl(s_service_impl) << "begin" << endl;
-  indent_up_impl();
-  indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl;
-  indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
-  indent_impl(s_service_impl) << "x := "
-								 "TApplicationExceptionUnknownMethod.Create("
-								 "'Invalid method name: ''' + msg.Name + '''');" << endl;
-  indent_impl(s_service_impl)
-      << "msg := Thrift.Protocol.TMessageImpl.Create(msg.Name, TMessageType.Exception, msg.SeqID);"
-      << endl;
-  indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl;
-  indent_impl(s_service_impl) << "x.Write(oprot);" << endl;
-  indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
-  indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
-  indent_impl(s_service_impl) << "Result := True;" << endl;
-  indent_impl(s_service_impl) << "Exit;" << endl;
-  indent_down_impl();
-  indent_impl(s_service_impl) << "end;" << endl;
-  if (events_) {
-    indent_impl(s_service_impl) << "if events <> nil" << endl;
-    indent_impl(s_service_impl) << "then context := events.CreateRequestContext(msg.Name)" << endl;
-    indent_impl(s_service_impl) << "else context := nil;" << endl;
-    indent_impl(s_service_impl) << "try" << endl;
-    indent_up_impl();
-    indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot, context);" << endl;
-    indent_down_impl();
-    indent_impl(s_service_impl) << "finally" << endl;
-    indent_up_impl();
-    indent_impl(s_service_impl) << "if context <> nil then begin" << endl;
-    indent_up_impl();
-    indent_impl(s_service_impl) << "context.CleanupContext;" << endl;
-    indent_impl(s_service_impl) << "context := nil;" << endl;
-    indent_down_impl();
-    indent_impl(s_service_impl) << "end;" << endl;
-    indent_down_impl();
-    indent_impl(s_service_impl) << "end;" << endl;
-  } else {
-    indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot);" << endl;
-  }
-  indent_down_impl();
-  indent_impl(s_service_impl) << "exce

<TRUNCATED>

[26/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_xml_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_xml_generator.cc b/compiler/cpp/src/generate/t_xml_generator.cc
deleted file mode 100644
index 5465b49..0000000
--- a/compiler/cpp/src/generate/t_xml_generator.cc
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <limits>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-
-#include "t_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-using std::stack;
-using std::set;
-
-static const string endl = "\n";
-static const string quot = "\"";
-
-static const string default_ns_prefix = "http://thrift.apache.org/xml/ns/";
-
-/**
- * This generator creates an XML model of the parsed IDL tree, and is designed
- * to make it easy to use this file as the input for other template engines,
- * such as XSLT.  To this end, the generated XML is slightly more verbose than
- * you might expect... for example, references to "id" types (such as structs,
- * unions, etc) always specify the name of the IDL document, even if the type
- * is defined in the same document as the reference.
- */
-class t_xml_generator : public t_generator {
-public:
-  t_xml_generator( t_program* program,
-                   const std::map<std::string, std::string>& parsed_options,
-                   const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    should_merge_includes_ = false;
-    should_use_default_ns_ = true;
-    should_use_namespaces_ = true;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("merge") == 0) {
-        should_merge_includes_ = true;
-      } else if( iter->first.compare("no_default_ns") == 0) {
-        should_use_default_ns_ = false;
-      } else if( iter->first.compare("no_namespaces") == 0) {
-        should_use_namespaces_ = false;
-      } else {
-        throw "unknown option xml:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-xml";
-  }
-
-  virtual ~t_xml_generator() {}
-
-  void init_generator();
-  void close_generator();
-  void generate_program();
-
-  void iterate_program(t_program* program);
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_function(t_function* tfunc);
-  void generate_field(t_field* field);
-
-  void generate_service(t_service* tservice);
-  void generate_struct(t_struct* tstruct);
-
-  void generate_annotations(std::map<std::string, std::string> annotations);
-
-private:
-  bool should_merge_includes_;
-  bool should_use_default_ns_;
-  bool should_use_namespaces_;
-
-  std::ofstream f_xml_;
- 
-  std::set<string> programs_;
-  std::stack<string> elements_;
-  bool top_element_is_empty;
-  bool top_element_is_open;
-
-  string target_namespace(t_program* program);
-  void write_element_start(const string name);
-  void close_top_element();
-  void write_element_end();
-  void write_attribute(string key, string val);
-  void write_int_attribute(string key, int val);
-  string escape_xml_string(const string& input);
-
-  void write_xml_comment(string msg);
-
-  void write_type(t_type* ttype);
-  void write_doc(t_doc* tdoc);
-
-  template <typename T>
-  string number_to_string(T t) {
-    std::ostringstream out;
-    out.imbue(std::locale::classic());
-    out.precision(std::numeric_limits<T>::digits10);
-    out << t;
-    return out.str();
-  }
-
-  template <typename T>
-  void write_number(T n) {
-    f_xml_ << number_to_string(n);
-  }
-
-  template <typename T>
-  void write_element_number(string name, T n) {
-    write_element_string(name, number_to_string(n));
-  }
-
-  string get_type_name(t_type* ttype);
-
-  void generate_constant(t_const* con);
-
-  void write_element_string(string name, string value);
-  void write_value(t_type* tvalue);
-  void write_const_value(t_const_value* value);
-  virtual std::string xml_autogen_comment() {
-    return std::string("\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-           + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n";
-  }
-};
-
-void t_xml_generator::init_generator() {
-  MKDIR(get_out_dir().c_str());
-
-  string f_xml_name = get_out_dir() + program_->get_name() + ".xml";
-  f_xml_.open(f_xml_name.c_str());
-
-  top_element_is_open = false;
-}
-
-string t_xml_generator::target_namespace(t_program* program) {
-  std::map<std::string, std::string> map;
-  std::map<std::string, std::string>::iterator iter;
-  map = program->get_namespace_annotations("xml");
-  if ((iter = map.find("targetNamespace")) != map.end()) {
-    return iter->second;
-  }
-  map = program->get_namespaces();
-  if ((iter = map.find("xml")) != map.end()) {
-    return default_ns_prefix + iter->second;
-  }
-  map = program->get_namespace_annotations("*");
-  if ((iter = map.find("xml.targetNamespace")) != map.end()) {
-    return iter->second;
-  }
-  map = program->get_namespaces();
-  if ((iter = map.find("*")) != map.end()) {
-    return default_ns_prefix + iter->second;
-  }
-  return default_ns_prefix + program->get_name();
-}
-
-void t_xml_generator::write_xml_comment(string msg) {
-  close_top_element();
-  // TODO: indent any EOLs that may occur with msg
-  // TODO: proper msg escaping needed?
-  f_xml_ << indent() << "<!-- " << msg << " -->"  << endl;  
-  top_element_is_empty = false;  
-}
-
-void t_xml_generator::close_top_element() {
-  if( top_element_is_open) {
-    top_element_is_open = false;
-    if (elements_.size() > 0 && top_element_is_empty) {
-      f_xml_ << ">" << endl;
-    }
-  }
-}
-
-void t_xml_generator::write_element_start(string name) {
-  if (should_use_namespaces_ && !should_use_default_ns_) {
-    name = "idl:" + name;
-  }
-  close_top_element();
-  f_xml_ << indent() << "<" << name;
-  elements_.push(name);
-  top_element_is_empty = true;
-  top_element_is_open = true;
-  indent_up();
-}
-
-void t_xml_generator::write_element_end() {
-  indent_down();
-  if (top_element_is_empty && top_element_is_open) {
-    f_xml_ << " />" << endl;
-  } else {
-    f_xml_ << indent() << "</" << elements_.top() << ">" << endl;
-  }
-  top_element_is_empty = false;
-  elements_.pop();
-}
-
-void t_xml_generator::write_attribute(string key, string val) {
-  f_xml_ << " " << key << "=\"" << escape_xml_string(val) << "\"";
-}
-
-void t_xml_generator::write_int_attribute(string key, int val) {
-  write_attribute(key, number_to_string(val));
-}
-
-void t_xml_generator::write_element_string(string name, string val) {
-  if (should_use_namespaces_ && !should_use_default_ns_) {
-    name = "idl:" + name;
-  }
-  close_top_element();
-  top_element_is_empty = false;
-  f_xml_ << indent() 
-    << "<" << name << ">" << escape_xml_string(val) << "</" << name << ">"
-    << endl;
-}
-
-string t_xml_generator::escape_xml_string(const string& input) {
-  std::ostringstream ss;
-  for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
-    switch (*iter) {
-    case '&':
-      ss << "&amp;";
-      break;
-    case '"':
-      ss << "&quot;";
-      break;
-    case '\'':
-      ss << "&apos;";
-      break;
-    case '<':
-      ss << "&lt;";
-      break;
-    case '>':
-      ss << "&gt;";
-      break;
-    default:
-      ss << *iter;
-      break;
-    }
-  }
-  return ss.str();
-}
-
-void t_xml_generator::close_generator() {
-  f_xml_.close();
-}
-
-void t_xml_generator::generate_program() {
-
-  init_generator();
-
-  write_element_start("idl");
-  if (should_use_namespaces_) {
-    if (should_use_default_ns_) {
-      write_attribute("xmlns", "http://thrift.apache.org/xml/idl");
-    }
-    write_attribute("xmlns:idl", "http://thrift.apache.org/xml/idl");
-  }
-
-  write_xml_comment( xml_autogen_comment());
-  
-  iterate_program(program_);
-  
-  write_element_end();
-
-  close_generator();
-
-}
-
-void t_xml_generator::iterate_program(t_program* program) {
-  
-  write_element_start("document");
-  write_attribute("name", program->get_name());
-  if (should_use_namespaces_) {
-    const string targetNamespace = target_namespace(program);
-    write_attribute("targetNamespace", targetNamespace);
-    write_attribute("xmlns:" + program->get_name(), targetNamespace);
-  }
-  write_doc(program);
-
-  const vector<t_program*> includes = program->get_includes();
-  vector<t_program*>::const_iterator inc_it;
-  for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) {
-    write_element_start("include");
-    write_attribute("name", (*inc_it)->get_name());
-    write_element_end();
-  }
-
-  const map<string, string>& namespaces = program->get_namespaces();
-  map<string, string>::const_iterator ns_it;
-  for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) {
-    write_element_start("namespace");
-    write_attribute("name", ns_it->first);
-    write_attribute("value", ns_it->second);
-    generate_annotations(program->get_namespace_annotations(ns_it->first));
-    write_element_end();
-  }
-
-  // TODO: can constants have annotations?
-  vector<t_const*> consts = program->get_consts();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    generate_constant(*c_iter);
-  }
-
-  vector<t_typedef*> typedefs = program->get_typedefs();
-  vector<t_typedef*>::iterator td_iter;
-  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-    generate_typedef(*td_iter);
-  }
-
-  vector<t_enum*> enums = program->get_enums();
-  vector<t_enum*>::iterator en_iter;
-  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-    generate_enum(*en_iter);
-  }
-
-  vector<t_struct*> objects = program->get_objects();
-  vector<t_struct*>::iterator o_iter;
-  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-    if ((*o_iter)->is_xception()) {
-      generate_xception(*o_iter);
-    } else {
-      generate_struct(*o_iter);
-    }
-  }
-
-  vector<t_service*> services = program->get_services();
-  vector<t_service*>::iterator sv_iter;
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    generate_service(*sv_iter);
-  }
-
-  write_element_end();
-
-  if (should_merge_includes_) {
-    programs_.insert(program->get_name());
-    const vector<t_program*> programs = program->get_includes();
-    vector<t_program*>::const_iterator prog_it;
-    for (prog_it = programs.begin(); prog_it != programs.end(); ++prog_it) {
-      if (!programs_.count((*prog_it)->get_name())) {
-        iterate_program(*prog_it);
-      }
-    }
-  }
-
-}
-
-void t_xml_generator::generate_typedef(t_typedef* ttypedef) {
-  write_element_start("typedef");
-  write_attribute("name", ttypedef->get_name());
-  write_doc(ttypedef);
-  write_type(ttypedef->get_true_type());
-  generate_annotations(ttypedef->annotations_);
-  write_element_end();
-  return;
-}
-
-void t_xml_generator::write_type(t_type* ttype) {
-  const string type = get_type_name(ttype);
-  write_attribute("type", type);
-  if (type == "id") {
-    write_attribute("type-module", ttype->get_program()->get_name());
-    write_attribute("type-id", ttype->get_name());
-  } else if (type == "list" || type == "set") {
-    t_type* etype = ((t_list*)ttype)->get_elem_type();
-    write_element_start("elemType");
-    write_type(etype);
-    write_element_end();
-  } else if (type == "map") {
-    t_type* ktype = ((t_map*)ttype)->get_key_type();
-    write_element_start("keyType");
-    write_type(ktype);
-    write_element_end();
-    t_type* vtype = ((t_map*)ttype)->get_val_type();
-    write_element_start("valueType");
-    write_type(vtype);
-    write_element_end();
-  }
-}
-
-void t_xml_generator::write_doc(t_doc* tdoc) {
-  if (tdoc->has_doc()) {
-    string doc = tdoc->get_doc();
-    // for some reason there always seems to be a trailing newline on doc
-    // comments; loop below naively tries to strip off trailing cr/lf
-    int n = 0;
-    for (string::reverse_iterator i = doc.rbegin(); i != doc.rend(); i++,n++) {
-      if (*i != '\n' || *i == '\r') {
-        if (n > 0) {
-          doc.erase(doc.length() - n);
-        }
-        break;
-      }
-    }
-    write_attribute("doc", doc);
-  }
-}
-
-void t_xml_generator::generate_annotations(
-    std::map<std::string, std::string> annotations) {
-  std::map<std::string, std::string>::iterator iter;
-  for (iter = annotations.begin(); iter != annotations.end(); ++iter) {
-    write_element_start("annotation");
-    write_attribute("key", iter->first);
-    write_attribute("value", iter->second);
-    write_element_end();
-  }
-}
-
-void t_xml_generator::generate_constant(t_const* con) {
-  write_element_start("const");
-  write_attribute("name", con->get_name());
-  write_doc(con);
-  write_type(con->get_type());
-  write_const_value(con->get_value());
-  write_element_end();
-}
-
-void t_xml_generator::write_const_value(t_const_value* value) {
-
-  switch (value->get_type()) {
-
-  case t_const_value::CV_IDENTIFIER:
-  case t_const_value::CV_INTEGER:
-    write_element_number("int", value->get_integer());
-    break;
-
-  case t_const_value::CV_DOUBLE:
-    write_element_number("double", value->get_double());
-    break;
-
-  case t_const_value::CV_STRING:
-    write_element_string("string", value->get_string());
-    break;
-
-  case t_const_value::CV_LIST: {
-    write_element_start("list");
-    std::vector<t_const_value*> list = value->get_list();
-    std::vector<t_const_value*>::iterator lit;
-    for (lit = list.begin(); lit != list.end(); ++lit) {
-      write_element_start("entry");
-      write_const_value(*lit);
-      write_element_end();
-    }
-    write_element_end();
-    break;
-  }
-
-  case t_const_value::CV_MAP: {
-    write_element_start("map");
-    std::map<t_const_value*, t_const_value*> map = value->get_map();
-    std::map<t_const_value*, t_const_value*>::iterator mit;
-    for (mit = map.begin(); mit != map.end(); ++mit) {
-      write_element_start("entry");
-      write_element_start("key");
-      write_const_value(mit->first);
-      write_element_end();
-      write_element_start("value");
-      write_const_value(mit->second);
-      write_element_end();
-      write_element_end();
-    }
-    write_element_end();
-    break;
-  }
-
-  default:
-    indent_up();
-    f_xml_ << indent() << "<null />" << endl;
-    indent_down();
-    break;
-  }
-
-}
-
-void t_xml_generator::generate_enum(t_enum* tenum) {
-
-  write_element_start("enum");
-  write_attribute("name", tenum->get_name());
-  write_doc(tenum);
-
-  vector<t_enum_value*> values = tenum->get_constants();
-  vector<t_enum_value*>::iterator val_iter;
-  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
-    t_enum_value* val = (*val_iter);
-    write_element_start("member");
-    write_attribute("name", val->get_name());
-    write_int_attribute("value", val->get_value());
-    write_doc(val);
-    generate_annotations(val->annotations_);
-    write_element_end();
-  }
-
-  generate_annotations(tenum->annotations_);
-
-  write_element_end();
-
-}
-
-void t_xml_generator::generate_struct(t_struct* tstruct) {
-
-  string tagname = "struct";
-  if (tstruct->is_union()) {
-    tagname = "union";
-  } else if (tstruct->is_xception()) {
-    tagname = "exception";
-  }
-
-  write_element_start(tagname);
-  write_attribute("name", tstruct->get_name());
-  write_doc(tstruct);
-  vector<t_field*> members = tstruct->get_members();
-  vector<t_field*>::iterator mem_iter;
-  for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) {
-    write_element_start("field");
-    generate_field(*mem_iter);
-    write_element_end();
-  }
-
-  generate_annotations(tstruct->annotations_);
- 
-  write_element_end();
-
-}
-
-void t_xml_generator::generate_field(t_field* field) {
-  write_attribute("name", field->get_name());
-  write_int_attribute("field-id", field->get_key());
-  write_doc(field); 
-  string requiredness;
-  switch (field->get_req()) {
-  case t_field::T_REQUIRED:
-    requiredness = "required";
-    break;
-  case t_field::T_OPTIONAL:
-    requiredness = "optional";
-    break;
-  default:
-    requiredness = "";
-    break;
-  }
-  if (requiredness != "") {
-    write_attribute("required", requiredness);
-  }
-  write_type(field->get_type());
-  if (field->get_value()) {
-    write_element_start("default");
-    write_const_value(field->get_value());
-    write_element_end();
-  }
-  generate_annotations(field->annotations_);
-}
-
-void t_xml_generator::generate_service(t_service* tservice) {
- 
-  write_element_start("service");
-  write_attribute("name", tservice->get_name());
-
-  if (should_use_namespaces_) {
-    string prog_ns = target_namespace(tservice->get_program());
-    if (*prog_ns.rbegin() != '/') {
-      prog_ns.push_back('/');
-    }
-    const string tns = prog_ns + tservice->get_name();
-    write_attribute("targetNamespace", tns);
-    write_attribute("xmlns:tns", tns);
-  }
- 
-  if (tservice->get_extends()) {
-    const t_service* extends = tservice->get_extends();
-    write_attribute("parent-module", extends->get_program()->get_name());
-    write_attribute("parent-id", extends->get_name());
-  }
-
-  write_doc(tservice);
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator fn_iter = functions.begin();
-  for (; fn_iter != functions.end(); fn_iter++) {
-    generate_function(*fn_iter);
-  }
-  
-  generate_annotations(tservice->annotations_);
-  
-  write_element_end();
-
-}
-
-void t_xml_generator::generate_function(t_function* tfunc) {
- 
-  write_element_start("method");
-
-  write_attribute("name", tfunc->get_name());
-  if (tfunc->is_oneway()) {
-    write_attribute("oneway", "true");
-  }
-
-  write_doc(tfunc);
-
-  write_element_start("returns");
-  write_type(tfunc->get_returntype());
-  write_element_end();
-
-  vector<t_field*> members = tfunc->get_arglist()->get_members();
-  vector<t_field*>::iterator mem_iter = members.begin();
-  for (; mem_iter != members.end(); mem_iter++) {
-    write_element_start("arg");
-    generate_field(*mem_iter);
-    write_element_end();
-  }
- 
-  vector<t_field*> excepts = tfunc->get_xceptions()->get_members();
-  vector<t_field*>::iterator ex_iter = excepts.begin();
-  for (; ex_iter != excepts.end(); ex_iter++) {
-    write_element_start("throws");
-    generate_field(*ex_iter);
-    write_element_end();
-  }
-
-  generate_annotations(tfunc->annotations_);
-  
-  write_element_end();
-
-}
-
-string t_xml_generator::get_type_name(t_type* ttype) {
-  if (ttype->is_list()) {
-    return "list";
-  }
-  if (ttype->is_set()) {
-    return "set";
-  }
-  if (ttype->is_map()) {
-    return "map";
-  }
-  if ((ttype->is_enum()    )|| 
-      (ttype->is_struct()  )|| 
-      (ttype->is_typedef() )|| 
-      (ttype->is_xception())){
-    return "id";
-  }
-  if (ttype->is_base_type()) {
-    t_base_type* tbasetype = (t_base_type*)ttype;
-    if (tbasetype->is_binary() ) {
-      return "binary";
-    }
-    return t_base_type::t_base_name(tbasetype->get_base());
-  }
-  return "(unknown)";
-}
-
-THRIFT_REGISTER_GENERATOR(
-  xml,
-  "XML",
-  "    merge:           Generate output with included files merged\n"
-  "    no_default_ns:   Omit default xmlns and add idl: prefix to all elements\n"
-  "    no_namespaces:   Do not add namespace definitions to the XML model\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_xsd_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc
deleted file mode 100644
index 2de860a..0000000
--- a/compiler/cpp/src/generate/t_xsd_generator.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <fstream>
-#include <iostream>
-#include <sstream>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_generator.h"
-#include "version.h"
-#include "platform.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * XSD generator, creates an XSD for the base types etc.
- *
- */
-class t_xsd_generator : public t_generator {
-public:
-  t_xsd_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option xsd:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-xsd";
-  }
-
-  virtual ~t_xsd_generator() {}
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum) { (void)tenum; }
-
-  void generate_service(t_service* tservice);
-  void generate_struct(t_struct* tstruct);
-
-private:
-  void generate_element(std::ostream& out,
-                        std::string name,
-                        t_type* ttype,
-                        t_struct* attrs = NULL,
-                        bool optional = false,
-                        bool nillable = false,
-                        bool list_element = false);
-
-  std::string ns(std::string in, std::string ns) { return ns + ":" + in; }
-
-  std::string xsd(std::string in) { return ns(in, "xsd"); }
-
-  std::string type_name(t_type* ttype);
-  std::string base_type_name(t_base_type::t_base tbase);
-
-  virtual std::string xml_autogen_comment() {
-    return std::string("<!--\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-           + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
-           + " -->\n";
-  }
-
-  /**
-   * Output xsd/php file
-   */
-  std::ofstream f_xsd_;
-  std::ofstream f_php_;
-
-  /**
-   * Output string stream
-   */
-  std::ostringstream s_xsd_types_;
-};
-
-void t_xsd_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  // Make output file
-  string f_php_name = get_out_dir() + program_->get_name() + "_xsd.php";
-  f_php_.open(f_php_name.c_str());
-
-  f_php_ << "<?php" << endl
-         << autogen_comment() << endl;
-}
-
-void t_xsd_generator::close_generator() {
-  f_php_ << "?>" << endl;
-  f_php_.close();
-}
-
-void t_xsd_generator::generate_typedef(t_typedef* ttypedef) {
-  indent(s_xsd_types_) << "<xsd:simpleType name=\"" << ttypedef->get_name() << "\">" << endl;
-  indent_up();
-  if (ttypedef->get_type()->is_string() && ((t_base_type*)ttypedef->get_type())->is_string_enum()) {
-    indent(s_xsd_types_) << "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\">"
-                         << endl;
-    indent_up();
-    const vector<string>& values = ((t_base_type*)ttypedef->get_type())->get_string_enum_vals();
-    vector<string>::const_iterator v_iter;
-    for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) {
-      indent(s_xsd_types_) << "<xsd:enumeration value=\"" << (*v_iter) << "\" />" << endl;
-    }
-    indent_down();
-    indent(s_xsd_types_) << "</xsd:restriction>" << endl;
-  } else {
-    indent(s_xsd_types_) << "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\" />"
-                         << endl;
-  }
-  indent_down();
-  indent(s_xsd_types_) << "</xsd:simpleType>" << endl << endl;
-}
-
-void t_xsd_generator::generate_struct(t_struct* tstruct) {
-  vector<t_field*>::const_iterator m_iter;
-  const vector<t_field*>& members = tstruct->get_members();
-  bool xsd_all = tstruct->get_xsd_all();
-
-  indent(s_xsd_types_) << "<xsd:complexType name=\"" << tstruct->get_name() << "\">" << endl;
-  indent_up();
-  if (xsd_all) {
-    indent(s_xsd_types_) << "<xsd:all>" << endl;
-  } else {
-    indent(s_xsd_types_) << "<xsd:sequence>" << endl;
-  }
-  indent_up();
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_element(s_xsd_types_,
-                     (*m_iter)->get_name(),
-                     (*m_iter)->get_type(),
-                     (*m_iter)->get_xsd_attrs(),
-                     (*m_iter)->get_xsd_optional() || xsd_all,
-                     (*m_iter)->get_xsd_nillable());
-  }
-
-  indent_down();
-  if (xsd_all) {
-    indent(s_xsd_types_) << "</xsd:all>" << endl;
-  } else {
-    indent(s_xsd_types_) << "</xsd:sequence>" << endl;
-  }
-  indent_down();
-  indent(s_xsd_types_) << "</xsd:complexType>" << endl << endl;
-}
-
-void t_xsd_generator::generate_element(ostream& out,
-                                       string name,
-                                       t_type* ttype,
-                                       t_struct* attrs,
-                                       bool optional,
-                                       bool nillable,
-                                       bool list_element) {
-  string sminOccurs = (optional || list_element) ? " minOccurs=\"0\"" : "";
-  string smaxOccurs = list_element ? " maxOccurs=\"unbounded\"" : "";
-  string soptional = sminOccurs + smaxOccurs;
-  string snillable = nillable ? " nillable=\"true\"" : "";
-
-  if (ttype->is_void() || ttype->is_list()) {
-    indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">" << endl;
-    indent_up();
-    if (attrs == NULL && ttype->is_void()) {
-      indent(out) << "<xsd:complexType />" << endl;
-    } else {
-      indent(out) << "<xsd:complexType>" << endl;
-      indent_up();
-      if (ttype->is_list()) {
-        indent(out) << "<xsd:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" << endl;
-        indent_up();
-        string subname;
-        t_type* subtype = ((t_list*)ttype)->get_elem_type();
-        if (subtype->is_base_type() || subtype->is_container()) {
-          subname = name + "_elt";
-        } else {
-          subname = type_name(subtype);
-        }
-        f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname
-               << "';" << endl;
-        generate_element(out, subname, subtype, NULL, false, false, true);
-        indent_down();
-        indent(out) << "</xsd:sequence>" << endl;
-        indent(out) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl;
-      }
-      if (attrs != NULL) {
-        const vector<t_field*>& members = attrs->get_members();
-        vector<t_field*>::const_iterator a_iter;
-        for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
-          indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\""
-                      << type_name((*a_iter)->get_type()) << "\" />" << endl;
-        }
-      }
-      indent_down();
-      indent(out) << "</xsd:complexType>" << endl;
-    }
-    indent_down();
-    indent(out) << "</xsd:element>" << endl;
-  } else {
-    if (attrs == NULL) {
-      indent(out) << "<xsd:element name=\"" << name << "\""
-                  << " type=\"" << type_name(ttype) << "\"" << soptional << snillable << " />"
-                  << endl;
-    } else {
-      // Wow, all this work for a SIMPLE TYPE with attributes?!?!?!
-      indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">"
-                  << endl;
-      indent_up();
-      indent(out) << "<xsd:complexType>" << endl;
-      indent_up();
-      indent(out) << "<xsd:complexContent>" << endl;
-      indent_up();
-      indent(out) << "<xsd:extension base=\"" << type_name(ttype) << "\">" << endl;
-      indent_up();
-      const vector<t_field*>& members = attrs->get_members();
-      vector<t_field*>::const_iterator a_iter;
-      for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
-        indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\""
-                    << type_name((*a_iter)->get_type()) << "\" />" << endl;
-      }
-      indent_down();
-      indent(out) << "</xsd:extension>" << endl;
-      indent_down();
-      indent(out) << "</xsd:complexContent>" << endl;
-      indent_down();
-      indent(out) << "</xsd:complexType>" << endl;
-      indent_down();
-      indent(out) << "</xsd:element>" << endl;
-    }
-  }
-}
-
-
-void t_xsd_generator::generate_service(t_service* tservice) {
-  // Make output file
-  string f_xsd_name = get_out_dir() + tservice->get_name() + ".xsd";
-  f_xsd_.open(f_xsd_name.c_str());
-
-  string ns = program_->get_namespace("xsd");
-  const std::map<std::string, std::string> annot = program_->get_namespace_annotations("xsd");
-  const std::map<std::string, std::string>::const_iterator uri = annot.find("uri");
-  if (uri != annot.end()) {
-    ns = uri->second;
-  }
-  if (ns.size() > 0) {
-    ns = " targetNamespace=\"" + ns + "\" xmlns=\"" + ns + "\" "
-         + "elementFormDefault=\"qualified\"";
-  }
-
-  // Print the XSD header
-  f_xsd_ << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl
-         << "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" << ns << ">" << endl
-         << xml_autogen_comment()
-         << endl;
-
-  // Print out the type definitions
-  indent(f_xsd_) << s_xsd_types_.str();
-
-  // Keep a list of all the possible exceptions that might get thrown
-  map<string, t_struct*> all_xceptions;
-
-  // List the elements that you might actually get
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string elemname = (*f_iter)->get_name() + "_response";
-    t_type* returntype = (*f_iter)->get_returntype();
-    generate_element(f_xsd_, elemname, returntype);
-    f_xsd_ << endl;
-
-    t_struct* xs = (*f_iter)->get_xceptions();
-    const std::vector<t_field*>& xceptions = xs->get_members();
-    vector<t_field*>::const_iterator x_iter;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      all_xceptions[(*x_iter)->get_name()] = (t_struct*)((*x_iter)->get_type());
-    }
-  }
-
-  map<string, t_struct*>::iterator ax_iter;
-  for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) {
-    generate_element(f_xsd_, ax_iter->first, ax_iter->second);
-  }
-
-  // Close the XSD document
-  f_xsd_ << endl << "</xsd:schema>" << endl;
-  f_xsd_.close();
-}
-
-string t_xsd_generator::type_name(t_type* ttype) {
-  if (ttype->is_typedef()) {
-    return ttype->get_name();
-  }
-
-  if (ttype->is_base_type()) {
-    return xsd(base_type_name(((t_base_type*)ttype)->get_base()));
-  }
-
-  if (ttype->is_enum()) {
-    return xsd("int");
-  }
-
-  if (ttype->is_struct() || ttype->is_xception()) {
-    return ttype->get_name();
-  }
-
-  return "container";
-}
-
-/**
- * Returns the XSD type that corresponds to the thrift type.
- *
- * @param tbase The base type
- * @return Explicit XSD type, i.e. xsd:string
- */
-string t_xsd_generator::base_type_name(t_base_type::t_base tbase) {
-  switch (tbase) {
-  case t_base_type::TYPE_VOID:
-    return "void";
-  case t_base_type::TYPE_STRING:
-    return "string";
-  case t_base_type::TYPE_BOOL:
-    return "boolean";
-  case t_base_type::TYPE_I8:
-    return "byte";
-  case t_base_type::TYPE_I16:
-    return "short";
-  case t_base_type::TYPE_I32:
-    return "int";
-  case t_base_type::TYPE_I64:
-    return "long";
-  case t_base_type::TYPE_DOUBLE:
-    return "decimal";
-  default:
-    throw "compiler error: no XSD base type name for base type " + t_base_type::t_base_name(tbase);
-  }
-}
-
-THRIFT_REGISTER_GENERATOR(xsd, "XSD", "")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/globals.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/globals.h b/compiler/cpp/src/globals.h
deleted file mode 100644
index 961c6ef..0000000
--- a/compiler/cpp/src/globals.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_GLOBALS_H
-#define T_GLOBALS_H
-
-#include <set>
-#include <queue>
-#include <stack>
-#include <vector>
-#include <string>
-
-/**
- * This module contains all the global variables (slap on the wrist) that are
- * shared throughout the program. The reason for this is to facilitate simple
- * interaction between the parser and the rest of the program. Before calling
- * yyparse(), the main.cc program will make necessary adjustments to these
- * global variables such that the parser does the right thing and puts entries
- * into the right containers, etc.
- *
- */
-
-/**
- * Hooray for forward declaration of types!
- */
-
-class t_program;
-class t_scope;
-class t_type;
-
-/**
- * Parsing mode, two passes up in this gin rummy!
- */
-
-enum PARSE_MODE { INCLUDES = 1, PROGRAM = 2 };
-
-/**
- * Strictness level
- */
-extern int g_strict;
-
-/**
- * The master program parse tree. This is accessed from within the parser code
- * to build up the program elements.
- */
-extern t_program* g_program;
-
-/**
- * The scope that we are currently parsing into
- */
-extern t_scope* g_scope;
-
-/**
- * The parent scope to also load symbols into
- */
-extern t_scope* g_parent_scope;
-
-/**
- * The prefix for the parent scope entries
- */
-extern std::string g_parent_prefix;
-
-/**
- * The parsing pass that we are on. We do different things on each pass.
- */
-extern PARSE_MODE g_parse_mode;
-
-/**
- * Global time string, used in formatting error messages etc.
- */
-extern char* g_time_str;
-
-/**
- * The last parsed doctext comment.
- */
-extern char* g_doctext;
-
-/**
- * The location of the last parsed doctext comment.
- */
-extern int g_doctext_lineno;
-
-/**
- * Status of program level doctext candidate
- */
-enum PROGDOCTEXT_STATUS {
-  INVALID = 0,
-  STILL_CANDIDATE = 1,   // the text may or may not be the program doctext
-  ALREADY_PROCESSED = 2, // doctext has been used and is no longer available
-  ABSOLUTELY_SURE = 3,   // this is the program doctext
-  NO_PROGRAM_DOCTEXT = 4 // there is no program doctext
-};
-
-/**
- * The program level doctext. Stored separately to make parsing easier.
- */
-extern char* g_program_doctext_candidate;
-extern int g_program_doctext_lineno;
-extern PROGDOCTEXT_STATUS g_program_doctext_status;
-
-/**
- * Whether or not negative field keys are accepted.
- *
- * When a field does not have a user-specified key, thrift automatically
- * assigns a negative value.  However, this is fragile since changes to the
- * file may unintentionally change the key numbering, resulting in a new
- * protocol that is not backwards compatible.
- *
- * When g_allow_neg_field_keys is enabled, users can explicitly specify
- * negative keys.  This way they can write a .thrift file with explicitly
- * specified keys that is still backwards compatible with older .thrift files
- * that did not specify key values.
- */
-extern int g_allow_neg_field_keys;
-
-/**
- * Whether or not 64-bit constants will generate a warning.
- *
- * Some languages don't support 64-bit constants, but many do, so we can
- * suppress this warning for projects that don't use any non-64-bit-safe
- * languages.
- */
-extern int g_allow_64bit_consts;
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/logging.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/logging.cc b/compiler/cpp/src/logging.cc
deleted file mode 100644
index 2daaaec..0000000
--- a/compiler/cpp/src/logging.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-/**
- * Logging functions copied from main.cc to avoid link errors for plugins
- */
-
-#include "logging.h"
-#include "globals.h"
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-
-// TODO: make plugins accept log options from main compiler
-int g_debug = 0;
-int g_warn = 1;
-int g_verbose = 0;
-
-void pdebug(const char* fmt, ...) {
-  if (g_debug == 0) {
-    return;
-  }
-  va_list args;
-  // printf("[PARSE:%d] ", yylineno);
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-  printf("\n");
-}
-
-void pverbose(const char* fmt, ...) {
-  if (g_verbose == 0) {
-    return;
-  }
-  va_list args;
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-}
-
-void pwarning(int level, const char* fmt, ...) {
-  if (g_warn < level) {
-    return;
-  }
-  va_list args;
-  // printf("[WARNING:%s:%d] ", g_curpath.c_str(), yylineno);
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-  printf("\n");
-}
-
-void failure(const char* fmt, ...) {
-  va_list args;
-  // fprintf(stderr, "[FAILURE:%s:%d] ", g_curpath.c_str(), yylineno);
-  va_start(args, fmt);
-  vfprintf(stderr, fmt, args);
-  va_end(args);
-  printf("\n");
-  exit(1);
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/logging.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/logging.h b/compiler/cpp/src/logging.h
deleted file mode 100644
index ebefbf2..0000000
--- a/compiler/cpp/src/logging.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_LOGGING_H
-#define T_LOGGING_H
-
-extern int g_debug;
-extern int g_warn;
-extern int g_verbose;
-
-/**
- * Parse debugging output, used to print helpful info
- */
-void pdebug(const char* fmt, ...);
-
-/**
- * Parser warning
- */
-void pwarning(int level, const char* fmt, ...);
-
-/**
- * Print verbose output message
- */
-void pverbose(const char* fmt, ...);
-
-/**
- * Failure!
- */
-void failure(const char* fmt, ...);
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/main.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
deleted file mode 100644
index 510d69f..0000000
--- a/compiler/cpp/src/main.cc
+++ /dev/null
@@ -1,1307 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-/**
- * thrift - a lightweight cross-language rpc/serialization tool
- *
- * This file contains the main compiler engine for Thrift, which invokes the
- * scanner/parser to build the thrift object tree. The interface generation
- * code for each language lives in a file by the language name under the
- * generate/ folder, and all parse structures live in parse/
- *
- */
-
-#include <cassert>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-#include <string>
-#include <algorithm>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <limits.h>
-
-#ifdef _WIN32
-#include <windows.h> /* for GetFullPathName */
-#endif
-
-// Careful: must include globals first for extern definitions
-#include "common.h"
-#include "globals.h"
-
-#include "platform.h"
-#include "main.h"
-#include "parse/t_program.h"
-#include "parse/t_scope.h"
-#include "generate/t_generator.h"
-#include "audit/t_audit.h"
-#ifdef THRIFT_ENABLE_PLUGIN
-#include "plugin/plugin_output.h"
-#endif
-
-#include "version.h"
-
-using namespace std;
-
-/**
- * Global program tree
- */
-t_program* g_program;
-
-/**
- * Global scope
- */
-t_scope* g_scope;
-
-/**
- * Parent scope to also parse types
- */
-t_scope* g_parent_scope;
-
-/**
- * Prefix for putting types in parent scope
- */
-string g_parent_prefix;
-
-/**
- * Parsing pass
- */
-PARSE_MODE g_parse_mode;
-
-/**
- * Current directory of file being parsed
- */
-string g_curdir;
-
-/**
- * Current file being parsed
- */
-string g_curpath;
-
-/**
- * Search path for inclusions
- */
-vector<string> g_incl_searchpath;
-
-/**
- * Global debug state
- */
-int g_debug = 0;
-
-/**
- * Strictness level
- */
-int g_strict = 127;
-
-/**
- * Warning level
- */
-int g_warn = 1;
-
-/**
- * Verbose output
- */
-int g_verbose = 0;
-
-/**
- * Global time string
- */
-char* g_time_str;
-
-/**
- * The last parsed doctext comment.
- */
-char* g_doctext;
-
-/**
- * The First doctext comment
- */
-char* g_program_doctext_candidate;
-
-/**
- * Whether or not negative field keys are accepted.
- */
-int g_allow_neg_field_keys;
-
-/**
- * Whether or not 64-bit constants will generate a warning.
- */
-int g_allow_64bit_consts = 0;
-
-/**
- * Flags to control code generation
- */
-bool gen_recurse = false;
-
-/**
- * Flags to control thrift audit
- */
-bool g_audit = false;
-
-/**
- * Flag to control return status
- */
-bool g_return_failure = false;
-bool g_audit_fatal = true;
-bool g_generator_failure = false;
-
-/**
- * Win32 doesn't have realpath, so use fallback implementation in that case,
- * otherwise this just calls through to realpath
- */
-char* saferealpath(const char* path, char* resolved_path) {
-#ifdef _WIN32
-  char buf[MAX_PATH];
-  char* basename;
-  DWORD len = GetFullPathName(path, MAX_PATH, buf, &basename);
-  if (len == 0 || len > MAX_PATH - 1) {
-    strcpy(resolved_path, path);
-  } else {
-    strcpy(resolved_path, buf);
-  }
-
-  // Replace backslashes with forward slashes so the
-  // rest of the code behaves correctly.
-  size_t resolved_len = strlen(resolved_path);
-  for (size_t i = 0; i < resolved_len; i++) {
-    if (resolved_path[i] == '\\') {
-      resolved_path[i] = '/';
-    }
-  }
-  return resolved_path;
-#else
-  return realpath(path, resolved_path);
-#endif
-}
-
-bool check_is_directory(const char* dir_name) {
-#ifdef _WIN32
-  DWORD attributes = ::GetFileAttributesA(dir_name);
-  if (attributes == INVALID_FILE_ATTRIBUTES) {
-    fprintf(stderr,
-            "Output directory %s is unusable: GetLastError() = %ld\n",
-            dir_name,
-            GetLastError());
-    return false;
-  }
-  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
-    fprintf(stderr, "Output directory %s exists but is not a directory\n", dir_name);
-    return false;
-  }
-  return true;
-#else
-  struct stat sb;
-  if (stat(dir_name, &sb) < 0) {
-    fprintf(stderr, "Output directory %s is unusable: %s\n", dir_name, strerror(errno));
-    return false;
-  }
-  if (!S_ISDIR(sb.st_mode)) {
-    fprintf(stderr, "Output directory %s exists but is not a directory\n", dir_name);
-    return false;
-  }
-  return true;
-#endif
-}
-
-/**
- * Report an error to the user. This is called yyerror for historical
- * reasons (lex and yacc expect the error reporting routine to be called
- * this). Call this function to report any errors to the user.
- * yyerror takes printf style arguments.
- *
- * @param fmt C format string followed by additional arguments
- */
-void yyerror(const char* fmt, ...) {
-  va_list args;
-  fprintf(stderr, "[ERROR:%s:%d] (last token was '%s')\n", g_curpath.c_str(), yylineno, yytext);
-
-  va_start(args, fmt);
-  vfprintf(stderr, fmt, args);
-  va_end(args);
-
-  fprintf(stderr, "\n");
-}
-
-/**
- * Prints a debug message from the parser.
- *
- * @param fmt C format string followed by additional arguments
- */
-void pdebug(const char* fmt, ...) {
-  if (g_debug == 0) {
-    return;
-  }
-  va_list args;
-  printf("[PARSE:%d] ", yylineno);
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-  printf("\n");
-}
-
-/**
- * Prints a verbose output mode message
- *
- * @param fmt C format string followed by additional arguments
- */
-void pverbose(const char* fmt, ...) {
-  if (g_verbose == 0) {
-    return;
-  }
-  va_list args;
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-}
-
-/**
- * Prints a warning message
- *
- * @param fmt C format string followed by additional arguments
- */
-void pwarning(int level, const char* fmt, ...) {
-  if (g_warn < level) {
-    return;
-  }
-  va_list args;
-  printf("[WARNING:%s:%d] ", g_curpath.c_str(), yylineno);
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-  printf("\n");
-}
-
-/**
- * Prints a failure message and exits
- *
- * @param fmt C format string followed by additional arguments
- */
-void failure(const char* fmt, ...) {
-  va_list args;
-  fprintf(stderr, "[FAILURE:%s:%d] ", g_curpath.c_str(), yylineno);
-  va_start(args, fmt);
-  vfprintf(stderr, fmt, args);
-  va_end(args);
-  printf("\n");
-  exit(1);
-}
-
-/**
- * Converts a string filename into a thrift program name
- */
-string program_name(string filename) {
-  string::size_type slash = filename.rfind("/");
-  if (slash != string::npos) {
-    filename = filename.substr(slash + 1);
-  }
-  string::size_type dot = filename.rfind(".");
-  if (dot != string::npos) {
-    filename = filename.substr(0, dot);
-  }
-  return filename;
-}
-
-/**
- * Gets the directory path of a filename
- */
-string directory_name(string filename) {
-  string::size_type slash = filename.rfind("/");
-  // No slash, just use the current directory
-  if (slash == string::npos) {
-    return ".";
-  }
-  return filename.substr(0, slash);
-}
-
-/**
- * Finds the appropriate file path for the given filename
- */
-string include_file(string filename) {
-  // Absolute path? Just try that
-  if (filename[0] == '/') {
-    // Realpath!
-    char rp[THRIFT_PATH_MAX];
-    // cppcheck-suppress uninitvar
-    if (saferealpath(filename.c_str(), rp) == NULL) {
-      pwarning(0, "Cannot open include file %s\n", filename.c_str());
-      return std::string();
-    }
-
-    // Stat this file
-    struct stat finfo;
-    if (stat(rp, &finfo) == 0) {
-      return rp;
-    }
-  } else { // relative path, start searching
-    // new search path with current dir global
-    vector<string> sp = g_incl_searchpath;
-    sp.insert(sp.begin(), g_curdir);
-
-    // iterate through paths
-    vector<string>::iterator it;
-    for (it = sp.begin(); it != sp.end(); it++) {
-      string sfilename = *(it) + "/" + filename;
-
-      // Realpath!
-      char rp[THRIFT_PATH_MAX];
-      // cppcheck-suppress uninitvar
-      if (saferealpath(sfilename.c_str(), rp) == NULL) {
-        continue;
-      }
-
-      // Stat this files
-      struct stat finfo;
-      if (stat(rp, &finfo) == 0) {
-        return rp;
-      }
-    }
-  }
-
-  // Uh oh
-  pwarning(0, "Could not find include file %s\n", filename.c_str());
-  return std::string();
-}
-
-/**
- * Clears any previously stored doctext string.
- * Also prints a warning if we are discarding information.
- */
-void clear_doctext() {
-  if (g_doctext != NULL) {
-    pwarning(2, "Uncaptured doctext at on line %d.", g_doctext_lineno);
-  }
-  free(g_doctext);
-  g_doctext = NULL;
-}
-
-/**
- * Reset program doctext information after processing a file
- */
-void reset_program_doctext_info() {
-  if (g_program_doctext_candidate != NULL) {
-    free(g_program_doctext_candidate);
-    g_program_doctext_candidate = NULL;
-  }
-  g_program_doctext_lineno = 0;
-  g_program_doctext_status = INVALID;
-  pdebug("%s", "program doctext set to INVALID");
-}
-
-/**
- * We are sure the program doctext candidate is really the program doctext.
- */
-void declare_valid_program_doctext() {
-  if ((g_program_doctext_candidate != NULL) && (g_program_doctext_status == STILL_CANDIDATE)) {
-    g_program_doctext_status = ABSOLUTELY_SURE;
-    pdebug("%s", "program doctext set to ABSOLUTELY_SURE");
-  } else {
-    g_program_doctext_status = NO_PROGRAM_DOCTEXT;
-    pdebug("%s", "program doctext set to NO_PROGRAM_DOCTEXT");
-  }
-}
-
-/**
- * Cleans up text commonly found in doxygen-like comments
- *
- * Warning: if you mix tabs and spaces in a non-uniform way,
- * you will get what you deserve.
- */
-char* clean_up_doctext(char* doctext) {
-  // Convert to C++ string, and remove Windows's carriage returns.
-  string docstring = doctext;
-  docstring.erase(remove(docstring.begin(), docstring.end(), '\r'), docstring.end());
-
-  // Separate into lines.
-  vector<string> lines;
-  string::size_type pos = string::npos;
-  string::size_type last;
-  while (true) {
-    last = (pos == string::npos) ? 0 : pos + 1;
-    pos = docstring.find('\n', last);
-    if (pos == string::npos) {
-      // First bit of cleaning.  If the last line is only whitespace, drop it.
-      string::size_type nonwhite = docstring.find_first_not_of(" \t", last);
-      if (nonwhite != string::npos) {
-        lines.push_back(docstring.substr(last));
-      }
-      break;
-    }
-    lines.push_back(docstring.substr(last, pos - last));
-  }
-
-  // A very profound docstring.
-  if (lines.empty()) {
-    return NULL;
-  }
-
-  // Clear leading whitespace from the first line.
-  pos = lines.front().find_first_not_of(" \t");
-  lines.front().erase(0, pos);
-
-  // If every nonblank line after the first has the same number of spaces/tabs,
-  // then a star, remove them.
-  bool have_prefix = true;
-  bool found_prefix = false;
-  string::size_type prefix_len = 0;
-  vector<string>::iterator l_iter;
-  for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) {
-    if (l_iter->empty()) {
-      continue;
-    }
-
-    pos = l_iter->find_first_not_of(" \t");
-    if (!found_prefix) {
-      if (pos != string::npos) {
-        if (l_iter->at(pos) == '*') {
-          found_prefix = true;
-          prefix_len = pos;
-        } else {
-          have_prefix = false;
-          break;
-        }
-      } else {
-        // Whitespace-only line.  Truncate it.
-        l_iter->clear();
-      }
-    } else if (l_iter->size() > pos && l_iter->at(pos) == '*' && pos == prefix_len) {
-      // Business as usual.
-    } else if (pos == string::npos) {
-      // Whitespace-only line.  Let's truncate it for them.
-      l_iter->clear();
-    } else {
-      // The pattern has been broken.
-      have_prefix = false;
-      break;
-    }
-  }
-
-  // If our prefix survived, delete it from every line.
-  if (have_prefix) {
-    // Get the star too.
-    prefix_len++;
-    for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) {
-      l_iter->erase(0, prefix_len);
-    }
-  }
-
-  // Now delete the minimum amount of leading whitespace from each line.
-  prefix_len = string::npos;
-  for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) {
-    if (l_iter->empty()) {
-      continue;
-    }
-    pos = l_iter->find_first_not_of(" \t");
-    if (pos != string::npos && (prefix_len == string::npos || pos < prefix_len)) {
-      prefix_len = pos;
-    }
-  }
-
-  // If our prefix survived, delete it from every line.
-  if (prefix_len != string::npos) {
-    for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) {
-      l_iter->erase(0, prefix_len);
-    }
-  }
-
-  // Remove trailing whitespace from every line.
-  for (l_iter = lines.begin(); l_iter != lines.end(); ++l_iter) {
-    pos = l_iter->find_last_not_of(" \t");
-    if (pos != string::npos && pos != l_iter->length() - 1) {
-      l_iter->erase(pos + 1);
-    }
-  }
-
-  // If the first line is empty, remove it.
-  // Don't do this earlier because a lot of steps skip the first line.
-  if (lines.front().empty()) {
-    lines.erase(lines.begin());
-  }
-
-  // Now rejoin the lines and copy them back into doctext.
-  docstring.clear();
-  for (l_iter = lines.begin(); l_iter != lines.end(); ++l_iter) {
-    docstring += *l_iter;
-    docstring += '\n';
-  }
-
-  // assert(docstring.length() <= strlen(doctext));  may happen, see THRIFT-1755
-  if (docstring.length() <= strlen(doctext)) {
-    strcpy(doctext, docstring.c_str());
-  } else {
-    free(doctext); // too short
-    doctext = strdup(docstring.c_str());
-  }
-  return doctext;
-}
-
-/** Set to true to debug docstring parsing */
-static bool dump_docs = false;
-
-/**
- * Dumps docstrings to stdout
- * Only works for top-level definitions and the whole program doc
- * (i.e., not enum constants, struct fields, or functions.
- */
-void dump_docstrings(t_program* program) {
-  string progdoc = program->get_doc();
-  if (!progdoc.empty()) {
-    printf("Whole program doc:\n%s\n", progdoc.c_str());
-  }
-  const vector<t_typedef*>& typedefs = program->get_typedefs();
-  vector<t_typedef*>::const_iterator t_iter;
-  for (t_iter = typedefs.begin(); t_iter != typedefs.end(); ++t_iter) {
-    t_typedef* td = *t_iter;
-    if (td->has_doc()) {
-      printf("typedef %s:\n%s\n", td->get_name().c_str(), td->get_doc().c_str());
-    }
-  }
-  const vector<t_enum*>& enums = program->get_enums();
-  vector<t_enum*>::const_iterator e_iter;
-  for (e_iter = enums.begin(); e_iter != enums.end(); ++e_iter) {
-    t_enum* en = *e_iter;
-    if (en->has_doc()) {
-      printf("enum %s:\n%s\n", en->get_name().c_str(), en->get_doc().c_str());
-    }
-  }
-  const vector<t_const*>& consts = program->get_consts();
-  vector<t_const*>::const_iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    t_const* co = *c_iter;
-    if (co->has_doc()) {
-      printf("const %s:\n%s\n", co->get_name().c_str(), co->get_doc().c_str());
-    }
-  }
-  const vector<t_struct*>& structs = program->get_structs();
-  vector<t_struct*>::const_iterator s_iter;
-  for (s_iter = structs.begin(); s_iter != structs.end(); ++s_iter) {
-    t_struct* st = *s_iter;
-    if (st->has_doc()) {
-      printf("struct %s:\n%s\n", st->get_name().c_str(), st->get_doc().c_str());
-    }
-  }
-  const vector<t_struct*>& xceptions = program->get_xceptions();
-  vector<t_struct*>::const_iterator x_iter;
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-    t_struct* xn = *x_iter;
-    if (xn->has_doc()) {
-      printf("xception %s:\n%s\n", xn->get_name().c_str(), xn->get_doc().c_str());
-    }
-  }
-  const vector<t_service*>& services = program->get_services();
-  vector<t_service*>::const_iterator v_iter;
-  for (v_iter = services.begin(); v_iter != services.end(); ++v_iter) {
-    t_service* sv = *v_iter;
-    if (sv->has_doc()) {
-      printf("service %s:\n%s\n", sv->get_name().c_str(), sv->get_doc().c_str());
-    }
-  }
-}
-
-/**
- * Emits a warning on list<byte>, binary type is typically a much better choice.
- */
-void check_for_list_of_bytes(t_type* list_elem_type) {
-  if ((g_parse_mode == PROGRAM) && (list_elem_type != NULL) && list_elem_type->is_base_type()) {
-    t_base_type* tbase = (t_base_type*)list_elem_type;
-    if (tbase->get_base() == t_base_type::TYPE_I8) {
-      pwarning(1, "Consider using the more efficient \"binary\" type instead of \"list<byte>\".");
-    }
-  }
-}
-
-static bool g_byte_warning_emitted = false;
-
-/**
- * Emits a one-time warning on byte type, promoting the new i8 type instead
- */
-void emit_byte_type_warning() {
-  if (!g_byte_warning_emitted) {
-    pwarning(1,
-             "The \"byte\" type is a compatibility alias for \"i8\". Use \"i8\" to emphasize the "
-             "signedness of this type.\n");
-    g_byte_warning_emitted = true;
-  }
-}
-
-/**
- * Prints deprecation notice for old NS declarations that are no longer supported
- * If new_form is NULL, old_form is assumed to be a language identifier, such as "cpp"
- * If new_form is not NULL, both arguments are used exactly as given
- */
-void error_unsupported_namespace_decl(const char* old_form, const char* new_form) {
-  const char* remainder = "";
-  if( new_form == NULL) {
-    new_form = old_form;
-    remainder = "_namespace";
-  }
-  failure("Unsupported declaration '%s%s'. Use 'namespace %s' instead.", old_form, remainder, new_form);
-}
-
-/**
- * Prints the version number
- */
-void version() {
-  printf("Thrift version %s\n", THRIFT_VERSION);
-}
-
-/**
- * Display the usage message and then exit with an error code.
- */
-void usage() {
-  fprintf(stderr, "Usage: thrift [options] file\n\n");
-  fprintf(stderr, "Use thrift -help for a list of options\n");
-  exit(1);
-}
-
-/**
- * Diplays the help message and then exits with an error code.
- */
-void help() {
-  fprintf(stderr, "Usage: thrift [options] file\n");
-  fprintf(stderr, "Options:\n");
-  fprintf(stderr, "  -version    Print the compiler version\n");
-  fprintf(stderr, "  -o dir      Set the output directory for gen-* packages\n");
-  fprintf(stderr, "               (default: current directory)\n");
-  fprintf(stderr, "  -out dir    Set the ouput location for generated files.\n");
-  fprintf(stderr, "               (no gen-* folder will be created)\n");
-  fprintf(stderr, "  -I dir      Add a directory to the list of directories\n");
-  fprintf(stderr, "                searched for include directives\n");
-  fprintf(stderr, "  -nowarn     Suppress all compiler warnings (BAD!)\n");
-  fprintf(stderr, "  -strict     Strict compiler warnings on\n");
-  fprintf(stderr, "  -v[erbose]  Verbose mode\n");
-  fprintf(stderr, "  -r[ecurse]  Also generate included files\n");
-  fprintf(stderr, "  -debug      Parse debug trace to stdout\n");
-  fprintf(stderr,
-          "  --allow-neg-keys  Allow negative field keys (Used to "
-          "preserve protocol\n");
-  fprintf(stderr, "                compatibility with older .thrift files)\n");
-  fprintf(stderr, "  --allow-64bit-consts  Do not print warnings about using 64-bit constants\n");
-  fprintf(stderr, "  --gen STR   Generate code with a dynamically-registered generator.\n");
-  fprintf(stderr, "                STR has the form language[:key1=val1[,key2[,key3=val3]]].\n");
-  fprintf(stderr, "                Keys and values are options passed to the generator.\n");
-  fprintf(stderr, "                Many options will not require values.\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Options related to audit operation\n");
-  fprintf(stderr, "   --audit OldFile   Old Thrift file to be audited with 'file'\n");
-  fprintf(stderr, "  -Iold dir    Add a directory to the list of directories\n");
-  fprintf(stderr, "                searched for include directives for old thrift file\n");
-  fprintf(stderr, "  -Inew dir    Add a directory to the list of directories\n");
-  fprintf(stderr, "                searched for include directives for new thrift file\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Available generators (and options):\n");
-
-  t_generator_registry::gen_map_t gen_map = t_generator_registry::get_generator_map();
-  t_generator_registry::gen_map_t::iterator iter;
-  for (iter = gen_map.begin(); iter != gen_map.end(); ++iter) {
-    fprintf(stderr,
-            "  %s (%s):\n",
-            iter->second->get_short_name().c_str(),
-            iter->second->get_long_name().c_str());
-    fprintf(stderr, "%s", iter->second->get_documentation().c_str());
-  }
-  exit(1);
-}
-
-/**
- * You know, when I started working on Thrift I really thought it wasn't going
- * to become a programming language because it was just a generator and it
- * wouldn't need runtime type information and all that jazz. But then we
- * decided to add constants, and all of a sudden that means runtime type
- * validation and inference, except the "runtime" is the code generator
- * runtime.
- */
-void validate_const_rec(std::string name, t_type* type, t_const_value* value) {
-  if (type->is_void()) {
-    throw "type error: cannot declare a void const: " + name;
-  }
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      if (value->get_type() != t_const_value::CV_STRING) {
-        throw "type error: const \"" + name + "\" was declared as string";
-      }
-      break;
-    case t_base_type::TYPE_BOOL:
-      if (value->get_type() != t_const_value::CV_INTEGER) {
-        throw "type error: const \"" + name + "\" was declared as bool";
-      }
-      break;
-    case t_base_type::TYPE_I8:
-      if (value->get_type() != t_const_value::CV_INTEGER) {
-        throw "type error: const \"" + name + "\" was declared as byte";
-      }
-      break;
-    case t_base_type::TYPE_I16:
-      if (value->get_type() != t_const_value::CV_INTEGER) {
-        throw "type error: const \"" + name + "\" was declared as i16";
-      }
-      break;
-    case t_base_type::TYPE_I32:
-      if (value->get_type() != t_const_value::CV_INTEGER) {
-        throw "type error: const \"" + name + "\" was declared as i32";
-      }
-      break;
-    case t_base_type::TYPE_I64:
-      if (value->get_type() != t_const_value::CV_INTEGER) {
-        throw "type error: const \"" + name + "\" was declared as i64";
-      }
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() != t_const_value::CV_INTEGER
-          && value->get_type() != t_const_value::CV_DOUBLE) {
-        throw "type error: const \"" + name + "\" was declared as double";
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase) + name;
-    }
-  } else if (type->is_enum()) {
-    if (value->get_type() != t_const_value::CV_IDENTIFIER) {
-      throw "type error: const \"" + name + "\" was declared as enum";
-    }
-
-    // see if there's a dot in the identifier
-    std::string name_portion = value->get_identifier_name();
-
-    const vector<t_enum_value*>& enum_values = ((t_enum*)type)->get_constants();
-    vector<t_enum_value*>::const_iterator c_iter;
-    bool found = false;
-
-    for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
-      if ((*c_iter)->get_name() == name_portion) {
-        found = true;
-        break;
-      }
-    }
-    if (!found) {
-      throw "type error: const " + name + " was declared as type " + type->get_name()
-          + " which is an enum, but " + value->get_identifier()
-          + " is not a valid value for that enum";
-    }
-  } else if (type->is_struct() || type->is_xception()) {
-    if (value->get_type() != t_const_value::CV_MAP) {
-      throw "type error: const \"" + name + "\" was declared as struct/xception";
-    }
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      if (v_iter->first->get_type() != t_const_value::CV_STRING) {
-        throw "type error: " + name + " struct key must be string";
-      }
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-
-      validate_const_rec(name + "." + v_iter->first->get_string(), field_type, v_iter->second);
-    }
-  } else if (type->is_map()) {
-    t_type* k_type = ((t_map*)type)->get_key_type();
-    t_type* v_type = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      validate_const_rec(name + "<key>", k_type, v_iter->first);
-      validate_const_rec(name + "<val>", v_type, v_iter->second);
-    }
-  } else if (type->is_list() || type->is_set()) {
-    t_type* e_type;
-    if (type->is_list()) {
-      e_type = ((t_list*)type)->get_elem_type();
-    } else {
-      e_type = ((t_set*)type)->get_elem_type();
-    }
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      validate_const_rec(name + "<elem>", e_type, *v_iter);
-    }
-  }
-}
-
-/**
- * Check simple identifier names
- * It's easier to do it this way instead of rewriting the whole grammar etc.
- */
-void validate_simple_identifier(const char* identifier) {
-  string name(identifier);
-  if (name.find(".") != string::npos) {
-    yyerror("Identifier %s can't have a dot.", identifier);
-    exit(1);
-  }
-}
-
-/**
- * Check the type of the parsed const information against its declared type
- */
-void validate_const_type(t_const* c) {
-  validate_const_rec(c->get_name(), c->get_type(), c->get_value());
-}
-
-/**
- * Check the type of a default value assigned to a field.
- */
-void validate_field_value(t_field* field, t_const_value* cv) {
-  validate_const_rec(field->get_name(), field->get_type(), cv);
-}
-
-/**
- * Check that all the elements of a throws block are actually exceptions.
- */
-bool validate_throws(t_struct* throws) {
-  const vector<t_field*>& members = throws->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (!t_generator::get_true_type((*m_iter)->get_type())->is_xception()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/**
- * Skips UTF-8 BOM if there is one
- */
-bool skip_utf8_bom(FILE* f) {
-
-  // pretty straightforward, but works
-  if (fgetc(f) == 0xEF) {
-    if (fgetc(f) == 0xBB) {
-      if (fgetc(f) == 0xBF) {
-        return true;
-      }
-    }
-  }
-
-  rewind(f);
-  return false;
-}
-
-/**
- * Parses a program
- */
-void parse(t_program* program, t_program* parent_program) {
-  // Get scope file path
-  string path = program->get_path();
-
-  // Set current dir global, which is used in the include_file function
-  g_curdir = directory_name(path);
-  g_curpath = path;
-
-  // Open the file
-  // skip UTF-8 BOM if there is one
-  yyin = fopen(path.c_str(), "r");
-  if (yyin == 0) {
-    failure("Could not open input file: \"%s\"", path.c_str());
-  }
-  if (skip_utf8_bom(yyin))
-    pverbose("Skipped UTF-8 BOM at %s\n", path.c_str());
-
-  // Create new scope and scan for includes
-  pverbose("Scanning %s for includes\n", path.c_str());
-  g_parse_mode = INCLUDES;
-  g_program = program;
-  g_scope = program->scope();
-  try {
-    yylineno = 1;
-    if (yyparse() != 0) {
-      failure("Parser error during include pass.");
-    }
-  } catch (string x) {
-    failure(x.c_str());
-  }
-  fclose(yyin);
-
-  // Recursively parse all the include programs
-  vector<t_program*>& includes = program->get_includes();
-  vector<t_program*>::iterator iter;
-  for (iter = includes.begin(); iter != includes.end(); ++iter) {
-    parse(*iter, program);
-  }
-
-  // reset program doctext status before parsing a new file
-  reset_program_doctext_info();
-
-  // Parse the program file
-  g_parse_mode = PROGRAM;
-  g_program = program;
-  g_scope = program->scope();
-  g_parent_scope = (parent_program != NULL) ? parent_program->scope() : NULL;
-  g_parent_prefix = program->get_name() + ".";
-  g_curpath = path;
-
-  // Open the file
-  // skip UTF-8 BOM if there is one
-  yyin = fopen(path.c_str(), "r");
-  if (yyin == 0) {
-    failure("Could not open input file: \"%s\"", path.c_str());
-  }
-  if (skip_utf8_bom(yyin))
-    pverbose("Skipped UTF-8 BOM at %s\n", path.c_str());
-
-  pverbose("Parsing %s for types\n", path.c_str());
-  yylineno = 1;
-  try {
-    if (yyparse() != 0) {
-      failure("Parser error during types pass.");
-    }
-  } catch (string x) {
-    failure(x.c_str());
-  }
-  fclose(yyin);
-}
-
-/**
- * Generate code
- */
-void generate(t_program* program, const vector<string>& generator_strings) {
-  // Oooohh, recursive code generation, hot!!
-  if (gen_recurse) {
-    const vector<t_program*>& includes = program->get_includes();
-    for (size_t i = 0; i < includes.size(); ++i) {
-      // Propagate output path from parent to child programs
-      includes[i]->set_out_path(program->get_out_path(), program->is_out_path_absolute());
-
-      generate(includes[i], generator_strings);
-    }
-  }
-
-  // Generate code!
-  try {
-    pverbose("Program: %s\n", program->get_path().c_str());
-
-    if (dump_docs) {
-      dump_docstrings(program);
-    }
-
-    vector<string>::const_iterator iter;
-    for (iter = generator_strings.begin(); iter != generator_strings.end(); ++iter) {
-      t_generator* generator = t_generator_registry::get_generator(program, *iter);
-
-      if (generator == NULL) {
-#ifdef THRIFT_ENABLE_PLUGIN
-        switch (plugin_output::delegateToPlugin(program, *iter)) {
-          case plugin_output::PLUGIN_NOT_FOUND:
-            pwarning(1, "Unable to get a generator for \"%s\".\n", iter->c_str());
-            g_generator_failure = true;
-            break;
-          case plugin_output::PLUGIN_FAILURE:
-            pwarning(1, "Plugin generator for \"%s\" failed.\n", iter->c_str());
-            g_generator_failure = true;
-            break;
-          case plugin_output::PLUGIN_SUCCEESS:
-            break;
-          default:
-            assert(false);
-            break;
-        }
-#else
-        pwarning(1, "Unable to get a generator for \"%s\".\n", iter->c_str());
-        g_generator_failure = true;
-#endif
-      } else if (generator) {
-        pverbose("Generating \"%s\"\n", iter->c_str());
-        generator->generate_program();
-        delete generator;
-      }
-    }
-  } catch (string s) {
-    failure("Error: %s\n", s.c_str());
-  } catch (const char* exc) {
-    failure("Error: %s\n", exc);
-  }
-}
-
-void audit(t_program* new_program,
-           t_program* old_program,
-           string new_thrift_include_path,
-           string old_thrift_include_path) {
-  vector<string> temp_incl_searchpath = g_incl_searchpath;
-  if (!old_thrift_include_path.empty()) {
-    g_incl_searchpath.push_back(old_thrift_include_path);
-  }
-
-  parse(old_program, NULL);
-
-  g_incl_searchpath = temp_incl_searchpath;
-  if (!new_thrift_include_path.empty()) {
-    g_incl_searchpath.push_back(new_thrift_include_path);
-  }
-
-  parse(new_program, NULL);
-
-  compare_namespace(new_program, old_program);
-  compare_services(new_program->get_services(), old_program->get_services());
-  compare_enums(new_program->get_enums(), old_program->get_enums());
-  compare_structs(new_program->get_structs(), old_program->get_structs());
-  compare_structs(new_program->get_xceptions(), old_program->get_xceptions());
-  compare_consts(new_program->get_consts(), old_program->get_consts());
-}
-
-/**
- * Parse it up.. then spit it back out, in pretty much every language. Alright
- * not that many languages, but the cool ones that we care about.
- */
-int main(int argc, char** argv) {
-  int i;
-  std::string out_path;
-  bool out_path_is_absolute = false;
-
-  // Setup time string
-  time_t now = time(NULL);
-  g_time_str = ctime(&now);
-
-  // Check for necessary arguments, you gotta have at least a filename and
-  // an output language flag
-  if (argc < 2) {
-    usage();
-  }
-
-  vector<string> generator_strings;
-  string old_thrift_include_path;
-  string new_thrift_include_path;
-  string old_input_file;
-
-  // Set the current path to a dummy value to make warning messages clearer.
-  g_curpath = "arguments";
-
-  // Hacky parameter handling... I didn't feel like using a library sorry!
-  for (i = 1; i < argc - 1; i++) {
-    char* arg;
-
-    arg = strtok(argv[i], " ");
-    while (arg != NULL) {
-      // Treat double dashes as single dashes
-      if (arg[0] == '-' && arg[1] == '-') {
-        ++arg;
-      }
-
-      if (strcmp(arg, "-help") == 0) {
-        help();
-      } else if (strcmp(arg, "-version") == 0) {
-        version();
-        exit(0);
-      } else if (strcmp(arg, "-debug") == 0) {
-        g_debug = 1;
-      } else if (strcmp(arg, "-nowarn") == 0) {
-        g_warn = 0;
-      } else if (strcmp(arg, "-strict") == 0) {
-        g_strict = 255;
-        g_warn = 2;
-      } else if (strcmp(arg, "-v") == 0 || strcmp(arg, "-verbose") == 0) {
-        g_verbose = 1;
-      } else if (strcmp(arg, "-r") == 0 || strcmp(arg, "-recurse") == 0) {
-        gen_recurse = true;
-      } else if (strcmp(arg, "-allow-neg-keys") == 0) {
-        g_allow_neg_field_keys = true;
-      } else if (strcmp(arg, "-allow-64bit-consts") == 0) {
-        g_allow_64bit_consts = true;
-      } else if (strcmp(arg, "-gen") == 0) {
-        arg = argv[++i];
-        if (arg == NULL) {
-          fprintf(stderr, "Missing generator specification\n");
-          usage();
-        }
-        generator_strings.push_back(arg);
-      } else if (strcmp(arg, "-I") == 0) {
-        // An argument of "-I\ asdf" is invalid and has unknown results
-        arg = argv[++i];
-
-        if (arg == NULL) {
-          fprintf(stderr, "Missing Include directory\n");
-          usage();
-        }
-        g_incl_searchpath.push_back(arg);
-      } else if ((strcmp(arg, "-o") == 0) || (strcmp(arg, "-out") == 0)) {
-        out_path_is_absolute = (strcmp(arg, "-out") == 0) ? true : false;
-        arg = argv[++i];
-        if (arg == NULL) {
-          fprintf(stderr, "-o: missing output directory\n");
-          usage();
-        }
-        out_path = arg;
-
-#ifdef _WIN32
-        // strip out trailing \ on Windows
-        std::string::size_type last = out_path.length() - 1;
-        if (out_path[last] == '\\') {
-          out_path.erase(last);
-        }
-#endif
-        if (!check_is_directory(out_path.c_str()))
-          return -1;
-      } else if (strcmp(arg, "-audit") == 0) {
-        g_audit = true;
-        arg = argv[++i];
-        if (arg == NULL) {
-          fprintf(stderr, "Missing old thrift file name for audit operation\n");
-          usage();
-        }
-        char old_thrift_file_rp[THRIFT_PATH_MAX];
-
-        // cppcheck-suppress uninitvar
-        if (saferealpath(arg, old_thrift_file_rp) == NULL) {
-          failure("Could not open input file with realpath: %s", arg);
-        }
-        old_input_file = string(old_thrift_file_rp);
-      } else if (strcmp(arg, "-audit-nofatal") == 0) {
-        g_audit_fatal = false;
-      } else if (strcmp(arg, "-Iold") == 0) {
-        arg = argv[++i];
-        if (arg == NULL) {
-          fprintf(stderr, "Missing Include directory for old thrift file\n");
-          usage();
-        }
-        old_thrift_include_path = string(arg);
-      } else if (strcmp(arg, "-Inew") == 0) {
-        arg = argv[++i];
-        if (arg == NULL) {
-          fprintf(stderr, "Missing Include directory for new thrift file\n");
-          usage();
-        }
-        new_thrift_include_path = string(arg);
-      } else {
-        fprintf(stderr, "Unrecognized option: %s\n", arg);
-        usage();
-      }
-
-      // Tokenize more
-      arg = strtok(NULL, " ");
-    }
-  }
-
-  // display help
-  if ((strcmp(argv[argc - 1], "-help") == 0) || (strcmp(argv[argc - 1], "--help") == 0)) {
-    help();
-  }
-
-  // if you're asking for version, you have a right not to pass a file
-  if ((strcmp(argv[argc - 1], "-version") == 0) || (strcmp(argv[argc - 1], "--version") == 0)) {
-    version();
-    exit(0);
-  }
-
-  // Initialize global types
-  initGlobals();
-
-  if (g_audit) {
-    // Audit operation
-
-    if (old_input_file.empty()) {
-      fprintf(stderr, "Missing file name of old thrift file for audit\n");
-      usage();
-    }
-
-    char new_thrift_file_rp[THRIFT_PATH_MAX];
-    if (argv[i] == NULL) {
-      fprintf(stderr, "Missing file name of new thrift file for audit\n");
-      usage();
-    }
-    // cppcheck-suppress uninitvar
-    if (saferealpath(argv[i], new_thrift_file_rp) == NULL) {
-      failure("Could not open input file with realpath: %s", argv[i]);
-    }
-    string new_input_file(new_thrift_file_rp);
-
-    t_program new_program(new_input_file);
-    t_program old_program(old_input_file);
-
-    audit(&new_program, &old_program, new_thrift_include_path, old_thrift_include_path);
-
-  } else {
-    // Generate options
-
-    // You gotta generate something!
-    if (generator_strings.empty()) {
-      fprintf(stderr, "No output language(s) specified\n");
-      usage();
-    }
-
-    // Real-pathify it
-    char rp[THRIFT_PATH_MAX];
-    if (argv[i] == NULL) {
-      fprintf(stderr, "Missing file name\n");
-      usage();
-    }
-    // cppcheck-suppress uninitvar
-    if (saferealpath(argv[i], rp) == NULL) {
-      failure("Could not open input file with realpath: %s", argv[i]);
-    }
-    string input_file(rp);
-
-    // Instance of the global parse tree
-    t_program* program = new t_program(input_file);
-    if (out_path.size()) {
-      program->set_out_path(out_path, out_path_is_absolute);
-    }
-
-    // Compute the cpp include prefix.
-    // infer this from the filename passed in
-    string input_filename = argv[i];
-    string include_prefix;
-
-    string::size_type last_slash = string::npos;
-    if ((last_slash = input_filename.rfind("/")) != string::npos) {
-      include_prefix = input_filename.substr(0, last_slash);
-    }
-
-    program->set_include_prefix(include_prefix);
-
-    // Parse it!
-    parse(program, NULL);
-
-    // The current path is not really relevant when we are doing generation.
-    // Reset the variable to make warning messages clearer.
-    g_curpath = "generation";
-    // Reset yylineno for the heck of it.  Use 1 instead of 0 because
-    // That is what shows up during argument parsing.
-    yylineno = 1;
-
-    // Generate it!
-    generate(program, generator_strings);
-    delete program;
-  }
-
-  // Clean up. Who am I kidding... this program probably orphans heap memory
-  // all over the place, but who cares because it is about to exit and it is
-  // all referenced and used by this wacky parse tree up until now anyways.
-  clearGlobals();
-
-  // Finished
-  if (g_return_failure && g_audit_fatal) {
-    exit(2);
-  }
-  if (g_generator_failure) {
-    exit(3);
-  }
-  // Finished
-  return 0;
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/main.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/main.h b/compiler/cpp/src/main.h
deleted file mode 100644
index b0af5a7..0000000
--- a/compiler/cpp/src/main.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_MAIN_H
-#define T_MAIN_H
-
-#include <string>
-#include <cstdio>
-
-#include "logging.h"
-
-#include "parse/t_const.h"
-#include "parse/t_field.h"
-
-/**
- * Defined in the flex library
- */
-
-extern "C" { int yylex(void); }
-
-int yyparse(void);
-
-/**
- * Expected to be defined by Flex/Bison
- */
-void yyerror(const char* fmt, ...);
-
-/**
- * Check simple identifier names
- */
-void validate_simple_identifier(const char* identifier);
-
-/**
- * Check constant types
- */
-void validate_const_type(t_const* c);
-
-/**
- * Check constant types
- */
-void validate_field_value(t_field* field, t_const_value* cv);
-
-/**
- * Check members of a throws block
- */
-bool validate_throws(t_struct* throws);
-
-/**
- * Converts a string filename into a thrift program name
- */
-std::string program_name(std::string filename);
-
-/**
- * Gets the directory path of a filename
- */
-std::string directory_name(std::string filename);
-
-/**
- * Get the absolute path for an include file
- */
-std::string include_file(std::string filename);
-
-/**
- * Clears any previously stored doctext string.
- */
-void clear_doctext();
-
-/**
- * Cleans up text commonly found in doxygen-like comments
- */
-char* clean_up_doctext(char* doctext);
-
-/**
- * We are sure the program doctext candidate is really the program doctext.
- */
-void declare_valid_program_doctext();
-
-/**
- * Emits a warning on list<byte>, binary type is typically a much better choice.
- */
-void check_for_list_of_bytes(t_type* list_elem_type);
-
-/**
- * Emits a one-time warning on byte type, promoting the new i8 type instead
- */
-void emit_byte_type_warning();
-
-/**
- * Prints deprecation notice for old NS declarations that are no longer supported
- * If new_form is NULL, old_form is assumed to be a language identifier, such as "cpp"
- * If new_form is not NULL, both arguments are used exactly as given
- */
-void error_unsupported_namespace_decl(const char* old_form, const char* new_form = NULL);
-
-/**
- * Flex utilities
- */
-
-extern int yylineno;
-extern char yytext[];
-extern std::FILE* yyin;
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/parse/parse.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/parse.cc b/compiler/cpp/src/parse/parse.cc
deleted file mode 100644
index 81a557b..0000000
--- a/compiler/cpp/src/parse/parse.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include "t_type.h"
-#include "t_typedef.h"
-
-#include "main.h"
-
-t_type* t_type::get_true_type() {
-  t_type* type = this;
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
-  return type;
-}
-
-const t_type* t_type::get_true_type() const {
-  const t_type* type = this;
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
-  return type;
-}


[09/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_java_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc
new file mode 100644
index 0000000..8b3c326
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc
@@ -0,0 +1,5323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <cassert>
+#include <ctime>
+
+#include <sstream>
+#include <string>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <stdexcept>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::setfill;
+using std::setw;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Java code generator.
+ *
+ */
+class t_java_generator : public t_oop_generator {
+public:
+  t_java_generator(t_program* program,
+                   const std::map<std::string, std::string>& parsed_options,
+                   const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    bean_style_ = false;
+    android_style_ = false;
+    private_members_ = false;
+    nocamel_style_ = false;
+    fullcamel_style_ = false;
+    android_legacy_ = false;
+    sorted_containers_ = false;
+    java5_ = false;
+    reuse_objects_ = false;
+    use_option_type_ = false;
+    undated_generated_annotations_  = false;
+    suppress_generated_annotations_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("beans") == 0) {
+        bean_style_ = true;
+      } else if( iter->first.compare("android") == 0) {
+        android_style_ = true;
+      } else if( iter->first.compare("private-members") == 0) {
+        private_members_ = true;
+      } else if( iter->first.compare("nocamel") == 0) {
+        nocamel_style_ = true;
+      } else if( iter->first.compare("fullcamel") == 0) {
+        fullcamel_style_ = true;
+      } else if( iter->first.compare("android_legacy") == 0) {
+        android_legacy_ = true;
+      } else if( iter->first.compare("sorted_containers") == 0) {
+        sorted_containers_ = true;
+      } else if( iter->first.compare("java5") == 0) {
+        java5_ = true;
+      } else if( iter->first.compare("reuse-objects") == 0) {
+        reuse_objects_ = true;
+      } else if( iter->first.compare("option_type") == 0) {
+        use_option_type_ = true;
+      } else if( iter->first.compare("generated_annotations") == 0) {
+        if( iter->second.compare("undated") == 0) {
+          undated_generated_annotations_  = true;
+        } else if(iter->second.compare("suppress") == 0) {
+          suppress_generated_annotations_ = true;
+        } else {
+          throw "unknown option java:" + iter->first + "=" + iter->second;
+        }
+      } else {
+        throw "unknown option java:" + iter->first;
+      }
+    }
+
+    if (java5_) {
+      android_legacy_ = true;
+    }
+
+    out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_union(t_struct* tunion);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ofstream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false);
+  std::string render_const_value(std::ofstream& out, t_type* type, t_const_value* value);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_java_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_java_struct_definition(std::ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false,
+                                       bool in_class = false,
+                                       bool is_result = false);
+  void generate_java_struct_parcelable(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_java_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_write_object(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_read_object(std::ofstream& out, t_struct* tstruct);
+  void generate_java_meta_data_map(std::ofstream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  std::string get_java_type_string(t_type* type);
+  void generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct);
+  void generate_reflection_setters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_reflection_getters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
+  void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
+
+  void generate_function_helpers(t_function* tfunction);
+  std::string as_camel_case(std::string name, bool ucfirst = true);
+  std::string get_rpc_method_name(std::string name);
+  std::string get_cap_name(std::string name);
+  std::string generate_isset_check(t_field* field);
+  std::string generate_isset_check(std::string field);
+  void generate_isset_set(ofstream& out, t_field* field, std::string prefix);
+  std::string isset_field_id(t_field* field);
+
+  void generate_service_interface(t_service* tservice);
+  void generate_service_async_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_async_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_service_async_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+  void generate_process_async_function(t_service* tservice, t_function* tfunction);
+
+  void generate_java_union(t_struct* tstruct);
+  void generate_union_constructor(ofstream& out, t_struct* tstruct);
+  void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
+  void generate_union_is_set_methods(ofstream& out, t_struct* tstruct);
+  void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
+  void generate_check_type(ofstream& out, t_struct* tstruct);
+  void generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct);
+  void generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct);
+  void generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct);
+  void generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct);
+  void generate_get_field_desc(ofstream& out, t_struct* tstruct);
+  void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
+  void generate_get_field_name(ofstream& out, t_struct* tstruct);
+
+  void generate_union_comparisons(ofstream& out, t_struct* tstruct);
+  void generate_union_hashcode(ofstream& out, t_struct* tstruct);
+
+  void generate_scheme_map(ofstream& out, t_struct* tstruct);
+  void generate_standard_writer(ofstream& out, t_struct* tstruct, bool is_result);
+  void generate_standard_reader(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct, bool is_result);
+
+  void generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct);
+
+  void generate_java_scheme_lookup(ofstream& out);
+
+  void generate_javax_generated_annotation(ofstream& out);
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool has_metadata = true);
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out,
+                                      t_type* ttype,
+                                      std::string prefix = "",
+                                      bool has_metadata = true);
+
+  void generate_deserialize_set_element(std::ofstream& out,
+                                        t_set* tset,
+                                        std::string prefix = "",
+                                        std::string obj = "",
+                                        bool has_metadata = true);
+
+  void generate_deserialize_map_element(std::ofstream& out,
+                                        t_map* tmap,
+                                        std::string prefix = "",
+                                        std::string obj = "",
+                                        bool has_metadata = true);
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "",
+                                         std::string obj = "",
+                                         bool has_metadata = true);
+
+  void generate_serialize_field(std::ofstream& out,
+                                t_field* tfield,
+                                std::string prefix = "",
+                                bool has_metadata = true);
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out,
+                                    t_type* ttype,
+                                    std::string prefix = "",
+                                    bool has_metadata = true);
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map,
+                                      bool has_metadata = true);
+
+  void generate_serialize_set_element(std::ofstream& out,
+                                      t_set* tmap,
+                                      std::string iter,
+                                      bool has_metadata = true);
+
+  void generate_serialize_list_element(std::ofstream& out,
+                                       t_list* tlist,
+                                       std::string iter,
+                                       bool has_metadata = true);
+
+  void generate_deep_copy_container(std::ofstream& out,
+                                    std::string source_name_p1,
+                                    std::string source_name_p2,
+                                    std::string result_name,
+                                    t_type* type);
+  void generate_deep_copy_non_container(std::ofstream& out,
+                                        std::string source_name,
+                                        std::string dest_name,
+                                        t_type* type);
+
+  enum isset_type { ISSET_NONE, ISSET_PRIMITIVE, ISSET_BITSET };
+  isset_type needs_isset(t_struct* tstruct, std::string* outPrimitiveType = NULL);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string java_package();
+  std::string java_type_imports();
+  std::string java_suppressions();
+  std::string type_name(t_type* ttype,
+                        bool in_container = false,
+                        bool in_init = false,
+                        bool skip_generic = false,
+                        bool force_namespace = false);
+  std::string base_type_name(t_base_type* tbase, bool in_container = false);
+  std::string declare_field(t_field* tfield, bool init = false, bool comment = false);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string function_signature_async(t_function* tfunction,
+                                       bool use_base_method = false,
+                                       std::string prefix = "");
+  std::string argument_list(t_struct* tstruct, bool include_types = true);
+  std::string async_function_call_arglist(t_function* tfunc,
+                                          bool use_base_method = true,
+                                          bool include_types = true);
+  std::string async_argument_list(t_function* tfunct,
+                                  t_struct* tstruct,
+                                  t_type* ttype,
+                                  bool include_types = false);
+  std::string type_to_enum(t_type* ttype);
+  void generate_struct_desc(ofstream& out, t_struct* tstruct);
+  void generate_field_descs(ofstream& out, t_struct* tstruct);
+  void generate_field_name_constants(ofstream& out, t_struct* tstruct);
+
+  std::string make_valid_java_filename(std::string const& fromName);
+  std::string make_valid_java_identifier(std::string const& fromName);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()
+           || ttype->is_enum();
+  }
+
+  bool is_deprecated(const std::map<std::string, std::string>& annotations) {
+    return annotations.find("deprecated") != annotations.end();
+  }
+
+  std::string constant_name(std::string name);
+
+private:
+  /**
+   * File streams
+   */
+
+  std::string package_name_;
+  std::ofstream f_service_;
+  std::string package_dir_;
+
+  bool bean_style_;
+  bool android_style_;
+  bool private_members_;
+  bool nocamel_style_;
+  bool fullcamel_style_;
+  bool android_legacy_;
+  bool java5_;
+  bool sorted_containers_;
+  bool reuse_objects_;
+  bool use_option_type_;
+  bool undated_generated_annotations_;
+  bool suppress_generated_annotations_;
+
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_java_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  package_name_ = program_->get_namespace("java");
+
+  string dir = package_name_;
+  string subdir = get_out_dir();
+  string::size_type loc;
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  package_dir_ = subdir;
+}
+
+/**
+ * Packages the generated file
+ *
+ * @return String of the package, i.e. "package org.apache.thriftdemo;"
+ */
+string t_java_generator::java_package() {
+  if (!package_name_.empty()) {
+    return string("package ") + package_name_ + ";\n\n";
+  }
+  return "";
+}
+
+/**
+ * Prints standard java imports
+ *
+ * @return List of imports for Java types that are used in here
+ */
+string t_java_generator::java_type_imports() {
+  string hash_builder;
+  string tree_set_and_map;
+  string annotation_generated;
+
+  string option;
+  if (sorted_containers_) {
+    tree_set_and_map = string() + "import java.util.TreeSet;\n" + "import java.util.TreeMap;\n";
+  }
+
+  if (use_option_type_) {
+    option = string() + "import org.apache.thrift.Option;\n";
+  }
+
+  // android does not support @Generated Annotation
+  if (!suppress_generated_annotations_) {
+    annotation_generated = string() + "import javax.annotation.Generated;\n";
+  }
+
+  return string() + hash_builder + "import org.apache.thrift.scheme.IScheme;\n"
+         + "import org.apache.thrift.scheme.SchemeFactory;\n"
+         + "import org.apache.thrift.scheme.StandardScheme;\n\n"
+         + "import org.apache.thrift.scheme.TupleScheme;\n"
+         + "import org.apache.thrift.protocol.TTupleProtocol;\n"
+         + "import org.apache.thrift.protocol.TProtocolException;\n"
+         + "import org.apache.thrift.EncodingUtils;\n"
+         + option
+         + "import org.apache.thrift.server.AbstractNonblockingServer.*;\n"
+         + "import java.util.List;\n" + "import java.util.ArrayList;\n" + "import java.util.Map;\n"
+         + "import java.util.HashMap;\n" + "import java.util.EnumMap;\n" + "import java.util.Set;\n"
+         + "import java.util.HashSet;\n" + "import java.util.EnumSet;\n" + tree_set_and_map
+         + "import java.util.Collections;\n" + "import java.util.BitSet;\n"
+         + "import java.nio.ByteBuffer;\n"
+         + "import java.util.Arrays;\n" + annotation_generated
+         + "import org.slf4j.Logger;\n" + "import org.slf4j.LoggerFactory;\n\n";
+}
+
+string t_java_generator::java_suppressions() {
+  return "@SuppressWarnings({\"cast\", \"rawtypes\", \"serial\", \"unchecked\", \"unused\"})\n";
+}
+
+/**
+ * Nothing in Java
+ */
+void t_java_generator::close_generator() {
+}
+
+/**
+ * Generates a typedef. This is not done in Java, since it does
+ * not support arbitrary name replacements, and it'd be a wacky waste
+ * of overhead to make wrapper classes.
+ *
+ * @param ttypedef The type definition
+ */
+void t_java_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Enums are a class with a set of static constants.
+ *
+ * @param tenum The enumeration
+ */
+void t_java_generator::generate_enum(t_enum* tenum) {
+  bool is_deprecated = this->is_deprecated(tenum->annotations_);
+  // Make output file
+  string f_enum_name = package_dir_ + "/" + make_valid_java_filename(tenum->get_name()) + ".java";
+  ofstream f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  // Comment and package it
+  f_enum << autogen_comment() << java_package() << endl;
+
+  // Add java imports
+  f_enum << string() + "import java.util.Map;\n" + "import java.util.HashMap;\n"
+            + "import org.apache.thrift.TEnum;" << endl << endl;
+
+  generate_java_doc(f_enum, tenum);
+  if (is_deprecated) {
+    indent(f_enum) << "@Deprecated" << endl;
+  }
+  indent(f_enum) << "public enum " << tenum->get_name() << " implements org.apache.thrift.TEnum ";
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  bool first = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+
+    if (first) {
+      first = false;
+    } else {
+      f_enum << "," << endl;
+    }
+
+    generate_java_doc(f_enum, *c_iter);
+    if (this->is_deprecated((*c_iter)->annotations_)) {
+      indent(f_enum) << "@Deprecated" << endl;
+    }
+    indent(f_enum) << (*c_iter)->get_name() << "(" << value << ")";
+  }
+  f_enum << ";" << endl << endl;
+
+  // Field for thriftCode
+  indent(f_enum) << "private final int value;" << endl << endl;
+
+  indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl;
+  indent(f_enum) << "  this.value = value;" << endl;
+  indent(f_enum) << "}" << endl << endl;
+
+  indent(f_enum) << "/**" << endl;
+  indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL."
+                 << endl;
+  indent(f_enum) << " */" << endl;
+  indent(f_enum) << "public int getValue() {" << endl;
+  indent(f_enum) << "  return value;" << endl;
+  indent(f_enum) << "}" << endl << endl;
+
+  indent(f_enum) << "/**" << endl;
+  indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL."
+                 << endl;
+  indent(f_enum) << " * @return null if the value is not found." << endl;
+  indent(f_enum) << " */" << endl;
+  indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl;
+
+  indent_up();
+
+  indent(f_enum) << "switch (value) {" << endl;
+  indent_up();
+
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "case " << value << ":" << endl;
+    indent(f_enum) << "  return " << (*c_iter)->get_name() << ";" << endl;
+  }
+
+  indent(f_enum) << "default:" << endl;
+  indent(f_enum) << "  return null;" << endl;
+
+  indent_down();
+
+  indent(f_enum) << "}" << endl;
+
+  indent_down();
+
+  indent(f_enum) << "}" << endl;
+
+  scope_down(f_enum);
+
+  f_enum.close();
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_java_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  string f_consts_name = package_dir_ + '/' + make_valid_java_filename(program_name_)
+                         + "Constants.java";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  // Print header
+  f_consts << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
+
+  f_consts << "public class " << make_valid_java_identifier(program_name_) << "Constants {" << endl
+           << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    generate_java_doc(f_consts, (*c_iter));
+    print_const_value(f_consts,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value(),
+                      false);
+  }
+  indent_down();
+  indent(f_consts) << "}" << endl;
+  f_consts.close();
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+void t_java_generator::print_const_value(std::ofstream& out,
+                                         string name,
+                                         t_type* type,
+                                         t_const_value* value,
+                                         bool in_static,
+                                         bool defval) {
+  type = get_true_type(type);
+
+  indent(out);
+  if (!defval) {
+    out << (in_static ? "" : "public static final ") << type_name(type) << " ";
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, type, value);
+    out << name << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl;
+  } else if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    out << name << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "static {" << endl;
+      indent_up();
+    }
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, field_type, v_iter->second);
+      indent(out) << name << ".";
+      std::string cap_name = get_cap_name(v_iter->first->get_string());
+      out << "set" << cap_name << "(" << val << ");" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    out << name << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "static {" << endl;
+      indent_up();
+    }
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, ktype, v_iter->first);
+      string val = render_const_value(out, vtype, v_iter->second);
+      indent(out) << name << ".put(" << key << ", " << val << ");" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "static {" << endl;
+      indent_up();
+    }
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, etype, *v_iter);
+      indent(out) << name << ".add(" << val << ");" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_java_generator::render_const_value(ofstream& out, t_type* type, t_const_value* value) {
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+      render << "(byte)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I16:
+      render << "(short)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "L";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << "(double)" << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    std::string namespace_prefix = type->get_program()->get_namespace("java");
+    if (namespace_prefix.length() > 0) {
+      namespace_prefix += ".";
+    }
+    render << namespace_prefix << value->get_identifier_with_parent();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This will be a org.apache.thrift.TBase
+ * implementor.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_struct(t_struct* tstruct) {
+  if (tstruct->is_union()) {
+    generate_java_union(tstruct);
+  } else {
+    generate_java_struct(tstruct, false);
+  }
+}
+
+/**
+ * Exceptions are structs, but they inherit from Exception
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_xception(t_struct* txception) {
+  generate_java_struct(txception, true);
+}
+
+/**
+ * Java struct definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_struct(t_struct* tstruct, bool is_exception) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name())
+                         + ".java";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
+
+  generate_java_struct_definition(f_struct, tstruct, is_exception);
+  f_struct.close();
+}
+
+/**
+ * Java union definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_union(t_struct* tstruct) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name())
+                         + ".java";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
+
+  generate_java_doc(f_struct, tstruct);
+
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+  bool is_deprecated = this->is_deprecated(tstruct->annotations_);
+
+  if (is_deprecated) {
+    indent(f_struct) << "@Deprecated" << endl;
+  }
+  indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
+                   << " extends org.apache.thrift.TUnion<" << tstruct->get_name() << ", "
+                   << tstruct->get_name() << "._Fields> ";
+
+  scope_up(f_struct);
+
+  generate_struct_desc(f_struct, tstruct);
+  generate_field_descs(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_field_name_constants(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_java_meta_data_map(f_struct, tstruct);
+
+  generate_union_constructor(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_abstract_methods(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_java_struct_field_by_id(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_getters_and_setters(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_is_set_methods(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_comparisons(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_hashcode(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_java_struct_write_object(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_java_struct_read_object(f_struct, tstruct);
+
+  f_struct << endl;
+
+  scope_down(f_struct);
+
+  f_struct.close();
+}
+
+void t_java_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  indent(out) << "public " << type_name(tstruct) << "() {" << endl;
+  indent_up();
+  bool default_value = false;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* type = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL) {
+      indent(out) << "super(_Fields." << constant_name((*m_iter)->get_name()) << ", "
+                  << render_const_value(out, type, (*m_iter)->get_value()) << ");" << endl;
+      default_value = true;
+      break;
+    }
+  }
+  if (default_value == false) {
+    indent(out) << "super();" << endl;
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "public " << type_name(tstruct) << "(_Fields setField, Object value) {" << endl;
+  indent(out) << "  super(setField, value);" << endl;
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {"
+              << endl;
+  indent(out) << "  super(other);" << endl;
+  indent(out) << "}" << endl;
+
+  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
+  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
+  indent(out) << "}" << endl << endl;
+
+  // generate "constructors" for each field
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* type = (*m_iter)->get_type();
+    indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "("
+                << type_name(type) << " value) {" << endl;
+    indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl;
+    indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl;
+    indent(out) << "  return x;" << endl;
+    indent(out) << "}" << endl << endl;
+
+    if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
+      indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name()
+                  << "(byte[] value) {" << endl;
+      indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();"
+                  << endl;
+      indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name())
+                  << "(ByteBuffer.wrap(Arrays.copyOf(value, value.length)));" << endl;
+      indent(out) << "  return x;" << endl;
+      indent(out) << "}" << endl << endl;
+    }
+  }
+}
+
+void t_java_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  bool first = true;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if (first) {
+      first = false;
+    } else {
+      out << endl;
+    }
+
+    t_field* field = (*m_iter);
+    t_type* type = field->get_type();
+    std::string cap_name = get_cap_name(field->get_name());
+    bool is_deprecated = this->is_deprecated(field->annotations_);
+
+    generate_java_doc(out, field);
+    if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
+      if (is_deprecated) {
+        indent(out) << "@Deprecated" << endl;
+      }
+      indent(out) << "public byte[] get" << cap_name << "() {" << endl;
+      indent(out) << "  set" << cap_name << "(org.apache.thrift.TBaseHelper.rightSize(buffer"
+                  << get_cap_name("for") << cap_name << "()));" << endl;
+      indent(out) << "  ByteBuffer b = buffer" << get_cap_name("for") << cap_name << "();" << endl;
+      indent(out) << "  return b == null ? null : b.array();" << endl;
+      indent(out) << "}" << endl;
+
+      out << endl;
+
+      indent(out) << "public ByteBuffer buffer" << get_cap_name("for")
+                  << get_cap_name(field->get_name()) << "() {" << endl;
+      indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
+                  << endl;
+      indent(out)
+          << "    return org.apache.thrift.TBaseHelper.copyBinary((ByteBuffer)getFieldValue());"
+          << endl;
+      indent(out) << "  } else {" << endl;
+      indent(out) << "    throw new RuntimeException(\"Cannot get field '" << field->get_name()
+                  << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
+                  << endl;
+      indent(out) << "  }" << endl;
+      indent(out) << "}" << endl;
+    } else {
+      if (is_deprecated) {
+        indent(out) << "@Deprecated" << endl;
+      }
+      indent(out) << "public " << type_name(field->get_type()) << " get"
+                  << get_cap_name(field->get_name()) << "() {" << endl;
+      indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
+                  << endl;
+      indent(out) << "    return (" << type_name(field->get_type(), true) << ")getFieldValue();"
+                  << endl;
+      indent(out) << "  } else {" << endl;
+      indent(out) << "    throw new RuntimeException(\"Cannot get field '" << field->get_name()
+                  << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
+                  << endl;
+      indent(out) << "  }" << endl;
+      indent(out) << "}" << endl;
+    }
+
+    out << endl;
+
+    generate_java_doc(out, field);
+    if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
+      if (is_deprecated) {
+        indent(out) << "@Deprecated" << endl;
+      }
+      indent(out) << "public void set" << get_cap_name(field->get_name()) << "(byte[] value) {"
+                  << endl;
+      indent(out) << "  set" << get_cap_name(field->get_name())
+                  << "(ByteBuffer.wrap(Arrays.copyOf(value, value.length)));" << endl;
+      indent(out) << "}" << endl;
+
+      out << endl;
+    }
+    if (is_deprecated) {
+      indent(out) << "@Deprecated" << endl;
+    }
+    indent(out) << "public void set" << get_cap_name(field->get_name()) << "("
+                << type_name(field->get_type()) << " value) {" << endl;
+    if (type_can_be_null(field->get_type())) {
+      indent(out) << "  if (value == null) throw new NullPointerException();" << endl;
+    }
+    indent(out) << "  setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl;
+    indent(out) << "  value_ = value;" << endl;
+    indent(out) << "}" << endl;
+  }
+}
+
+void t_java_generator::generate_union_is_set_methods(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  bool first = true;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if (first) {
+      first = false;
+    } else {
+      out << endl;
+    }
+
+    std::string field_name = (*m_iter)->get_name();
+
+    indent(out) << "public boolean is" << get_cap_name("set") << get_cap_name(field_name) << "() {"
+                << endl;
+    indent_up();
+    indent(out) << "return setField_ == _Fields." << constant_name(field_name) << ";" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+void t_java_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
+  generate_check_type(out, tstruct);
+  out << endl;
+  generate_standard_scheme_read_value(out, tstruct);
+  out << endl;
+  generate_standard_scheme_write_value(out, tstruct);
+  out << endl;
+  generate_tuple_scheme_read_value(out, tstruct);
+  out << endl;
+  generate_tuple_scheme_write_value(out, tstruct);
+  out << endl;
+  generate_get_field_desc(out, tstruct);
+  out << endl;
+  generate_get_struct_desc(out, tstruct);
+  out << endl;
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected _Fields enumForId(short id) {" << endl;
+  indent(out) << "  return _Fields.findByThriftIdOrThrow(id);" << endl;
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out)
+      << "protected void checkType(_Fields setField, Object value) throws ClassCastException {"
+      << endl;
+  indent_up();
+
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent(out) << "  if (value instanceof " << type_name(field->get_type(), true, false, true)
+                << ") {" << endl;
+    indent(out) << "    break;" << endl;
+    indent(out) << "  }" << endl;
+    indent(out) << "  throw new ClassCastException(\"Was expecting value of type "
+                << type_name(field->get_type(), true, false) << " for field '" << field->get_name()
+                << "', but got \" + value.getClass().getSimpleName());" << endl;
+    // do the real check here
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol "
+                 "iprot, org.apache.thrift.protocol.TField field) throws "
+                 "org.apache.thrift.TException {" << endl;
+
+  indent_up();
+
+  indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl;
+  indent(out) << "if (setField != null) {" << endl;
+  indent_up();
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {"
+                << endl;
+    indent_up();
+    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";"
+                << endl;
+    generate_deserialize_field(out, field, "");
+    indent(out) << "return " << field->get_name() << ";" << endl;
+    indent_down();
+    indent(out) << "} else {" << endl;
+    indent(out) << "  org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl;
+    indent(out) << "  return null;" << endl;
+    indent(out) << "}" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalStateException(\"setField wasn't null, but didn't match any "
+                 "of the case statements!\");" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "} else {" << endl;
+  indent_up();
+  indent(out) << "org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl;
+  indent(out) << "return null;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected void standardSchemeWriteValue(org.apache.thrift.protocol.TProtocol "
+                 "oprot) throws org.apache.thrift.TException {" << endl;
+
+  indent_up();
+
+  indent(out) << "switch (setField_) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = ("
+                << type_name(field->get_type(), true, false) << ")value_;" << endl;
+    generate_serialize_field(out, field, "");
+    indent(out) << "return;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + "
+                 "setField_);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected Object tupleSchemeReadValue(org.apache.thrift.protocol.TProtocol "
+                 "iprot, short fieldID) throws org.apache.thrift.TException {" << endl;
+
+  indent_up();
+
+  indent(out) << "_Fields setField = _Fields.findByThriftId(fieldID);" << endl;
+  indent(out) << "if (setField != null) {" << endl;
+  indent_up();
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";"
+                << endl;
+    generate_deserialize_field(out, field, "");
+    indent(out) << "return " << field->get_name() << ";" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalStateException(\"setField wasn't null, but didn't match any "
+                 "of the case statements!\");" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "} else {" << endl;
+  indent_up();
+  indent(out) << "throw new TProtocolException(\"Couldn't find a field with field id \" + fieldID);"
+              << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected void tupleSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) "
+                 "throws org.apache.thrift.TException {" << endl;
+
+  indent_up();
+
+  indent(out) << "switch (setField_) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = ("
+                << type_name(field->get_type(), true, false) << ")value_;" << endl;
+    generate_serialize_field(out, field, "");
+    indent(out) << "return;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + "
+                 "setField_);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {"
+              << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent(out) << "  return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl;
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "@Override" << endl;
+  indent(out) << "protected org.apache.thrift.protocol.TStruct getStructDesc() {" << endl;
+  indent(out) << "  return STRUCT_DESC;" << endl;
+  indent(out) << "}" << endl;
+}
+
+void t_java_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
+  // equality
+  indent(out) << "public boolean equals(Object other) {" << endl;
+  indent(out) << "  if (other instanceof " << tstruct->get_name() << ") {" << endl;
+  indent(out) << "    return equals((" << tstruct->get_name() << ")other);" << endl;
+  indent(out) << "  } else {" << endl;
+  indent(out) << "    return false;" << endl;
+  indent(out) << "  }" << endl;
+  indent(out) << "}" << endl;
+
+  out << endl;
+
+  indent(out) << "public boolean equals(" << tstruct->get_name() << " other) {" << endl;
+  indent(out) << "  return other != null && getSetField() == other.getSetField() && "
+                 "getFieldValue().equals(other.getFieldValue());" << endl;
+  indent(out) << "}" << endl;
+  out << endl;
+
+  indent(out) << "@Override" << endl;
+  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
+  indent(out) << "  int lastComparison = org.apache.thrift.TBaseHelper.compareTo(getSetField(), "
+                 "other.getSetField());" << endl;
+  indent(out) << "  if (lastComparison == 0) {" << endl;
+  indent(out) << "    return org.apache.thrift.TBaseHelper.compareTo(getFieldValue(), "
+                 "other.getFieldValue());" << endl;
+  indent(out) << "  }" << endl;
+  indent(out) << "  return lastComparison;" << endl;
+  indent(out) << "}" << endl;
+  out << endl;
+}
+
+void t_java_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "@Override" << endl;
+  indent(out) << "public int hashCode() {" << endl;
+  indent(out) << "  List<Object> list = new ArrayList<Object>();" << endl;
+  indent(out) << "  list.add(this.getClass().getName());" << endl;
+  indent(out) << "  org.apache.thrift.TFieldIdEnum setField = getSetField();" << endl;
+  indent(out) << "  if (setField != null) {" << endl;
+  indent(out) << "    list.add(setField.getThriftFieldId());" << endl;
+  indent(out) << "    Object value = getFieldValue();" << endl;
+  indent(out) << "    if (value instanceof org.apache.thrift.TEnum) {" << endl;
+  indent(out) << "      list.add(((org.apache.thrift.TEnum)getFieldValue()).getValue());" << endl;
+  indent(out) << "    } else {" << endl;
+  indent(out) << "      list.add(value);" << endl;
+  indent(out) << "    }" << endl;
+  indent(out) << "  }" << endl;
+  indent(out) << "  return list.hashCode();" << endl;
+  indent(out) << "}";
+}
+
+/**
+ * Java struct definition. This has various parameters, as it could be
+ * generated standalone or inside another class as a helper. If it
+ * is a helper than it is a static class.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param in_class     If inside a class, needs to be static class
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_java_generator::generate_java_struct_definition(ofstream& out,
+                                                       t_struct* tstruct,
+                                                       bool is_exception,
+                                                       bool in_class,
+                                                       bool is_result) {
+  generate_java_doc(out, tstruct);
+
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+  bool is_deprecated = this->is_deprecated(tstruct->annotations_);
+
+  if (!in_class && !suppress_generated_annotations_) {
+    generate_javax_generated_annotation(out);
+  }
+
+  if (is_deprecated) {
+    indent(out) << "@Deprecated" << endl;
+  }
+  indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class "
+              << tstruct->get_name() << " ";
+
+  if (is_exception) {
+    out << "extends org.apache.thrift.TException ";
+  }
+  out << "implements org.apache.thrift.TBase<" << tstruct->get_name() << ", " << tstruct->get_name()
+      << "._Fields>, java.io.Serializable, Cloneable, Comparable<" << tstruct->get_name() << ">";
+
+  if (android_style_) {
+    out << ", android.os.Parcelable";
+  }
+
+  out << " ";
+
+  scope_up(out);
+
+  generate_struct_desc(out, tstruct);
+
+  // Members are public for -java, private for -javabean
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << endl;
+
+  generate_field_descs(out, tstruct);
+
+  out << endl;
+
+  generate_scheme_map(out, tstruct);
+
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if (bean_style_ || private_members_) {
+      indent(out) << "private ";
+    } else {
+      generate_java_doc(out, *m_iter);
+      indent(out) << "public ";
+    }
+    out << declare_field(*m_iter, false, true) << endl;
+  }
+
+  out << endl;
+
+  if (android_style_) {
+    generate_java_struct_parcelable(out, tstruct);
+  }
+
+  generate_field_name_constants(out, tstruct);
+
+  // isset data
+  if (members.size() > 0) {
+    out << endl;
+
+    indent(out) << "// isset id assignments" << endl;
+
+    int i = 0;
+    int optionals = 0;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
+        optionals++;
+      }
+      if (!type_can_be_null((*m_iter)->get_type())) {
+        indent(out) << "private static final int " << isset_field_id(*m_iter) << " = " << i << ";"
+                    << endl;
+        i++;
+      }
+    }
+
+    std::string primitiveType;
+    switch (needs_isset(tstruct, &primitiveType)) {
+    case ISSET_NONE:
+      break;
+    case ISSET_PRIMITIVE:
+      indent(out) << "private " << primitiveType << " __isset_bitfield = 0;" << endl;
+      break;
+    case ISSET_BITSET:
+      indent(out) << "private BitSet __isset_bit_vector = new BitSet(" << i << ");" << endl;
+      break;
+    }
+
+    if (optionals > 0) {
+      std::string output_string = "private static final _Fields optionals[] = {";
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
+          output_string = output_string + "_Fields." + constant_name((*m_iter)->get_name()) + ",";
+        }
+      }
+      indent(out) << output_string.substr(0, output_string.length() - 1) << "};" << endl;
+    }
+  }
+
+  generate_java_meta_data_map(out, tstruct);
+
+  bool all_optional_members = true;
+
+  // Default constructor
+  indent(out) << "public " << tstruct->get_name() << "() {" << endl;
+  indent_up();
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL) {
+      print_const_value(out,
+                        "this." + (*m_iter)->get_name(),
+                        t,
+                        (*m_iter)->get_value(),
+                        true,
+                        true);
+    }
+    if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+      all_optional_members = false;
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  if (!members.empty() && !all_optional_members) {
+    // Full constructor for all fields
+    indent(out) << "public " << tstruct->get_name() << "(" << endl;
+    indent_up();
+    bool first = true;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+        if (!first) {
+          out << "," << endl;
+        }
+        first = false;
+        indent(out) << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
+      }
+    }
+    out << ")" << endl;
+    indent_down();
+    indent(out) << "{" << endl;
+    indent_up();
+    indent(out) << "this();" << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+        t_type* type = get_true_type((*m_iter)->get_type());
+        if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
+          indent(out) << "this." << (*m_iter)->get_name()
+                      << " = org.apache.thrift.TBaseHelper.copyBinary(" << (*m_iter)->get_name()
+                      << ");" << endl;
+        } else {
+          indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";"
+                      << endl;
+        }
+        generate_isset_set(out, (*m_iter), "");
+      }
+    }
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+
+  // copy constructor
+  indent(out) << "/**" << endl;
+  indent(out) << " * Performs a deep copy on <i>other</i>." << endl;
+  indent(out) << " */" << endl;
+  indent(out) << "public " << tstruct->get_name() << "(" << tstruct->get_name() << " other) {"
+              << endl;
+  indent_up();
+
+  switch (needs_isset(tstruct)) {
+  case ISSET_NONE:
+    break;
+  case ISSET_PRIMITIVE:
+    indent(out) << "__isset_bitfield = other.__isset_bitfield;" << endl;
+    break;
+  case ISSET_BITSET:
+    indent(out) << "__isset_bit_vector.clear();" << endl;
+    indent(out) << "__isset_bit_vector.or(other.__isset_bit_vector);" << endl;
+    break;
+  }
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+    std::string field_name = field->get_name();
+    t_type* type = field->get_type()->get_true_type();
+    bool can_be_null = type_can_be_null(type);
+
+    if (can_be_null) {
+      indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl;
+      indent_up();
+    }
+
+    if (type->is_container()) {
+      generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type);
+      indent(out) << "this." << field_name << " = __this__" << field_name << ";" << endl;
+    } else {
+      indent(out) << "this." << field_name << " = ";
+      generate_deep_copy_non_container(out, "other." + field_name, field_name, type);
+      out << ";" << endl;
+    }
+
+    if (can_be_null) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // clone method, so that you can deep copy an object when you don't know its class.
+  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
+  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
+  indent(out) << "}" << endl << endl;
+
+  generate_java_struct_clear(out, tstruct);
+
+  generate_java_bean_boilerplate(out, tstruct);
+  generate_generic_field_getters_setters(out, tstruct);
+  generate_generic_isset_method(out, tstruct);
+
+  generate_java_struct_equality(out, tstruct);
+  generate_java_struct_compare_to(out, tstruct);
+  generate_java_struct_field_by_id(out, tstruct);
+
+  generate_java_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_java_struct_result_writer(out, tstruct);
+  } else {
+    generate_java_struct_writer(out, tstruct);
+  }
+  generate_java_struct_tostring(out, tstruct);
+  generate_java_validator(out, tstruct);
+
+  generate_java_struct_write_object(out, tstruct);
+  generate_java_struct_read_object(out, tstruct);
+
+  generate_java_struct_standard_scheme(out, tstruct, is_result);
+  generate_java_struct_tuple_scheme(out, tstruct);
+  generate_java_scheme_lookup(out);
+
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * generates parcelable interface implementation
+ */
+void t_java_generator::generate_java_struct_parcelable(ofstream& out, t_struct* tstruct) {
+  string tname = tstruct->get_name();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << indent() << "@Override" << endl << indent()
+      << "public void writeToParcel(android.os.Parcel out, int flags) {" << endl;
+  indent_up();
+  string bitsetPrimitiveType = "";
+  switch (needs_isset(tstruct, &bitsetPrimitiveType)) {
+  case ISSET_NONE:
+    break;
+  case ISSET_PRIMITIVE:
+    indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl;
+    if (bitsetPrimitiveType == "byte") {
+      indent(out) << "out.writeByte(__isset_bitfield);" << endl;
+    } else if (bitsetPrimitiveType == "short") {
+      indent(out) << "out.writeInt(new Short(__isset_bitfield).intValue());" << endl;
+    } else if (bitsetPrimitiveType == "int") {
+      indent(out) << "out.writeInt(__isset_bitfield);" << endl;
+    } else if (bitsetPrimitiveType == "long") {
+      indent(out) << "out.writeLong(__isset_bitfield);" << endl;
+    }
+    out << endl;
+    break;
+  case ISSET_BITSET:
+    indent(out) << "//BitSet" << endl;
+    indent(out) << "out.writeSerializable(__isset_bit_vector);" << endl;
+    out << endl;
+    break;
+  }
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    string name = (*m_iter)->get_name();
+
+    if (t->is_struct()) {
+      indent(out) << "out.writeParcelable(" << name << ", flags);" << endl;
+    } else if (type_name(t) == "float") {
+      indent(out) << "out.writeFloat(" << name << ");" << endl;
+    } else if (t->is_enum()) {
+      indent(out) << "out.writeInt(" << name << " != null ? " << name << ".getValue() : -1);" << endl;
+    } else if (t->is_list()) {
+      if (((t_list*)t)->get_elem_type()->get_true_type()->is_struct()) {
+        indent(out) << "out.writeTypedList(" << name << ");" << endl;
+      } else {
+        indent(out) << "out.writeList(" << name << ");" << endl;
+      }
+    } else if (t->is_map()) {
+      indent(out) << "out.writeMap(" << name << ");" << endl;
+    } else if (t->is_base_type()) {
+      if (((t_base_type*)t)->is_binary()) {
+        indent(out) << "out.writeInt(" << name << "!=null ? 1 : 0);" << endl;
+        indent(out) << "if(" << name << " != null) { " << endl;
+        indent_up();
+        indent(out) << "out.writeByteArray(" << name << ".array(), " << name << ".position() + "
+                    << name << ".arrayOffset(), " << name << ".limit() - " << name
+                    << ".position() );" << endl;
+        scope_down(out);
+      } else {
+        switch (((t_base_type*)t)->get_base()) {
+        case t_base_type::TYPE_I16:
+          indent(out) << "out.writeInt(new Short(" << name << ").intValue());" << endl;
+          break;
+        case t_base_type::TYPE_I32:
+          indent(out) << "out.writeInt(" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_I64:
+          indent(out) << "out.writeLong(" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_BOOL:
+          indent(out) << "out.writeInt(" << name << " ? 1 : 0);" << endl;
+          break;
+        case t_base_type::TYPE_I8:
+          indent(out) << "out.writeByte(" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_DOUBLE:
+          indent(out) << "out.writeDouble(" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_STRING:
+          indent(out) << "out.writeString(" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_VOID:
+          break;
+        }
+      }
+    }
+  }
+  scope_down(out);
+  out << endl;
+
+  out << indent() << "@Override" << endl << indent() << "public int describeContents() {" << endl;
+  indent_up();
+  out << indent() << "return 0;" << endl;
+  scope_down(out);
+  out << endl;
+
+  indent(out) << "public " << tname << "(android.os.Parcel in) {" << endl;
+  indent_up();
+  // read in the required bitfield
+  switch (needs_isset(tstruct, &bitsetPrimitiveType)) {
+  case ISSET_NONE:
+    break;
+  case ISSET_PRIMITIVE:
+    indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl;
+    if (bitsetPrimitiveType == "byte") {
+      indent(out) << "__isset_bitfield = in.readByte();" << endl;
+    } else if (bitsetPrimitiveType == "short") {
+      indent(out) << "__isset_bitfield = (short) in.readInt();" << endl;
+    } else if (bitsetPrimitiveType == "int") {
+      indent(out) << "__isset_bitfield = in.readInt();" << endl;
+    } else if (bitsetPrimitiveType == "long") {
+      indent(out) << "__isset_bitfield = in.readLong();" << endl;
+    }
+    out << endl;
+    break;
+  case ISSET_BITSET:
+    indent(out) << "//BitSet" << endl;
+    indent(out) << "__isset_bit_vector = (BitSet) in.readSerializable();" << endl;
+    out << endl;
+    break;
+  }
+  // read all the fields
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    string name = (*m_iter)->get_name();
+    string prefix = "this." + name;
+
+    if (t->is_struct()) {
+      indent(out) << prefix << "= in.readParcelable(" << tname << ".class.getClassLoader());"
+                  << endl;
+    } else if (t->is_enum()) {
+      indent(out) << prefix << " = " << type_name(t) << ".findByValue(in.readInt());" << endl;
+    } else if (t->is_list()) {
+      t_list* list = (t_list*)t;
+      indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl;
+      if (list->get_elem_type()->get_true_type()->is_struct()) {
+        indent(out) << "in.readTypedList(" << prefix << ", " << type_name(list->get_elem_type())
+                    << ".CREATOR);" << endl;
+      } else {
+        indent(out) << "in.readList(" << prefix << ", " << tname << ".class.getClassLoader());"
+                    << endl;
+      }
+    } else if (t->is_map()) {
+      indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl;
+      indent(out) << " in.readMap(" << prefix << ", " << tname << ".class.getClassLoader());"
+                  << endl;
+    } else if (type_name(t) == "float") {
+      indent(out) << prefix << " = in.readFloat();" << endl;
+    } else if (t->is_base_type()) {
+      t_base_type* bt = (t_base_type*)t;
+      if (bt->is_binary()) {
+        indent(out) << "if(in.readInt()==1) {" << endl;
+        indent_up();
+        indent(out) << prefix << " = ByteBuffer.wrap(in.createByteArray());" << endl;
+        scope_down(out);
+      } else {
+        switch (bt->get_base()) {
+        case t_base_type::TYPE_I16:
+          indent(out) << prefix << " = (short) in.readInt();" << endl;
+          break;
+        case t_base_type::TYPE_I32:
+          indent(out) << prefix << " = in.readInt();" << endl;
+          break;
+        case t_base_type::TYPE_I64:
+          indent(out) << prefix << " = in.readLong();" << endl;
+          break;
+        case t_base_type::TYPE_BOOL:
+          indent(out) << prefix << " = (in.readInt()==1);" << endl;
+          break;
+        case t_base_type::TYPE_I8:
+          indent(out) << prefix << " = in.readByte();" << endl;
+          break;
+        case t_base_type::TYPE_DOUBLE:
+          indent(out) << prefix << " = in.readDouble();" << endl;
+          break;
+        case t_base_type::TYPE_STRING:
+          indent(out) << prefix << "= in.readString();" << endl;
+          break;
+        case t_base_type::TYPE_VOID:
+          break;
+        }
+      }
+    }
+  }
+
+  scope_down(out);
+  out << endl;
+
+  indent(out) << "public static final android.os.Parcelable.Creator<" << tname
+              << "> CREATOR = new android.os.Parcelable.Creator<" << tname << ">() {" << endl;
+  indent_up();
+
+  indent(out) << "@Override" << endl << indent() << "public " << tname << "[] newArray(int size) {"
+              << endl;
+  indent_up();
+  indent(out) << "return new " << tname << "[size];" << endl;
+  scope_down(out);
+  out << endl;
+
+  indent(out) << "@Override" << endl << indent() << "public " << tname
+              << " createFromParcel(android.os.Parcel in) {" << endl;
+  indent_up();
+  indent(out) << "return new " << tname << "(in);" << endl;
+  scope_down(out);
+
+  indent_down();
+  indent(out) << "};" << endl;
+  out << endl;
+}
+
+/**
+ * Generates equals methods and a hashCode method for a structure.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_struct_equality(ofstream& out, t_struct* tstruct) {
+  out << indent() << "@Override" << endl << indent() << "public boolean equals(Object that) {"
+      << endl;
+  indent_up();
+  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl
+      << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent()
+      << "  return this.equals((" << tstruct->get_name() << ")that);" << endl << indent()
+      << "return false;" << endl;
+  scope_down(out);
+  out << endl;
+
+  out << indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl;
+  indent_up();
+  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    out << endl;
+
+    t_type* t = get_true_type((*m_iter)->get_type());
+    // Most existing Thrift code does not use isset or optional/required,
+    // so we treat "default" fields as required.
+    bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
+    bool can_be_null = type_can_be_null(t);
+    string name = (*m_iter)->get_name();
+
+    string this_present = "true";
+    string that_present = "true";
+    string unequal;
+
+    if (is_optional || can_be_null) {
+      this_present += " && this." + generate_isset_check(*m_iter);
+      that_present += " && that." + generate_isset_check(*m_iter);
+    }
+
+    out << indent() << "boolean this_present_" << name << " = " << this_present << ";" << endl
+        << indent() << "boolean that_present_" << name << " = " << that_present << ";" << endl
+        << indent() << "if ("
+        << "this_present_" << name << " || that_present_" << name << ") {" << endl;
+    indent_up();
+    out << indent() << "if (!("
+        << "this_present_" << name << " && that_present_" << name << "))" << endl << indent()
+        << "  return false;" << endl;
+
+    if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
+      unequal = "!this." + name + ".equals(that." + name + ")";
+    } else if (can_be_null) {
+      unequal = "!this." + name + ".equals(that." + name + ")";
+    } else {
+      unequal = "this." + name + " != that." + name;
+    }
+
+    out << indent() << "if (" << unequal << ")" << endl << indent() << "  return false;" << endl;
+
+    scope_down(out);
+  }
+  out << endl;
+  indent(out) << "return true;" << endl;
+  scope_down(out);
+  out << endl;
+
+  const int MUL = 8191; // HashCode multiplier
+  const int B_YES = 131071;
+  const int B_NO = 524287;
+  out << indent() << "@Override" << endl << indent() << "public int hashCode() {" << endl;
+  indent_up();
+  indent(out) << "int hashCode = 1;" << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    out << endl;
+
+    t_type* t = get_true_type((*m_iter)->get_type());
+    bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
+    bool can_be_null = type_can_be_null(t);
+    string name = (*m_iter)->get_name();
+
+    if (is_optional || can_be_null) {
+      indent(out) << "hashCode = hashCode * " << MUL << " + ((" << generate_isset_check(*m_iter)
+                  << ") ? " << B_YES << " : " << B_NO << ");" << endl;
+    }
+
+    if (is_optional || can_be_null) {
+      indent(out) << "if (" + generate_isset_check(*m_iter) + ")" << endl;
+      indent_up();
+    }
+
+    if (t->is_enum()) {
+      indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".getValue();" << endl;
+    } else if (t->is_base_type()) {
+      switch(((t_base_type*)t)->get_base()) {
+      case t_base_type::TYPE_STRING:
+        indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".hashCode();" << endl;
+        break;
+      case t_base_type::TYPE_BOOL:
+        indent(out) << "hashCode = hashCode * " << MUL << " + ((" << name << ") ? "
+                    << B_YES << " : " << B_NO << ");" << endl;
+        break;
+      case t_base_type::TYPE_I8:
+        indent(out) << "hashCode = hashCode * " << MUL << " + (int) (" << name << ");" << endl;
+        break;
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+        indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ";" << endl;
+        break;
+      case t_base_type::TYPE_I64:
+      case t_base_type::TYPE_DOUBLE:
+        indent(out) << "hashCode = hashCode * " << MUL << " + org.apache.thrift.TBaseHelper.hashCode(" << name << ");" << endl;
+        break;
+      case t_base_type::TYPE_VOID:
+        throw std::logic_error("compiler error: a struct field cannot be void");
+      default:
+        throw std::logic_error("compiler error: the following base type has no hashcode generator: " +
+               t_base_type::t_base_name(((t_base_type*)t)->get_base()));
+      }
+    } else {
+      indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".hashCode();" << endl;
+    }
+
+    if (is_optional || can_be_null) {
+      indent_down();
+    }
+  }
+
+  out << endl;
+  indent(out) << "return hashCode;" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_java_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
+  indent(out) << "@Override" << endl;
+  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
+  indent_up();
+
+  indent(out) << "if (!getClass().equals(other.getClass())) {" << endl;
+  indent(out) << "  return getClass().getName().compareTo(other.getClass().getName());" << endl;
+  indent(out) << "}" << endl;
+  out << endl;
+
+  indent(out) << "int lastComparison = 0;" << endl;
+  out << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = *m_iter;
+    indent(out) << "lastComparison = Boolean.valueOf(" << generate_isset_check(field)
+                << ").compareTo(other." << generate_isset_check(field) << ");" << endl;
+    indent(out) << "if (lastComparison != 0) {" << endl;
+    indent(out) << "  return lastComparison;" << endl;
+    indent(out) << "}" << endl;
+
+    indent(out) << "if (" << generate_isset_check(field) << ") {" << endl;
+    indent(out) << "  lastComparison = org.apache.thrift.TBaseHelper.compareTo(this."
+                << field->get_name() << ", other." << field->get_name() << ");" << endl;
+    indent(out) << "  if (lastComparison != 0) {" << endl;
+    indent(out) << "    return lastComparison;" << endl;
+    indent(out) << "  }" << endl;
+    indent(out) << "}" << endl;
+  }
+
+  indent(out) << "return 0;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_struct_reader(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws "
+                 "org.apache.thrift.TException {" << endl;
+  indent_up();
+  indent(out) << "scheme(iprot).read(iprot, this);" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+// generates java method to perform various checks
+// (e.g. check that all required fields are set)
+void t_java_generator::generate_java_validator(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public void validate() throws org.apache.thrift.TException {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      if (bean_style_) {
+        out << indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl << indent()
+            << "  throw new org.apache.thrift.protocol.TProtocolException(\"Required field '"
+            << (*f_iter)->get_name() << "' is unset! Struct:\" + toString());" << endl << indent()
+            << "}" << endl << endl;
+      } else {
+        if (type_can_be_null((*f_iter)->get_type())) {
+          indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
+          indent(out)
+              << "  throw new org.apache.thrift.protocol.TProtocolException(\"Required field '"
+              << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl;
+          indent(out) << "}" << endl;
+        } else {
+          indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
+                      << "' because it's a primitive and you chose the non-beans generator."
+                      << endl;
+        }
+      }
+    }
+  }
+
+  out << indent() << "// check for sub-struct validity" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_type* type = (*f_iter)->get_type();
+    if (type->is_struct() && !((t_struct*)type)->is_union()) {
+      out << indent() << "if (" << (*f_iter)->get_name() << " != null) {" << endl;
+      out << indent() << "  " << (*f_iter)->get_name() << ".validate();" << endl;
+      out << indent() << "}" << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_struct_writer(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws "
+                 "org.apache.thrift.TException {" << endl;
+  indent_up();
+  indent(out) << "scheme(oprot).write(oprot, this);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct,
+ * which is a function result. These fields are only written
+ * if they are set in the Isset array, and only one of them
+ * can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws "
+                 "org.apache.thrift.TException {" << endl;
+  indent_up();
+  indent(out) << "scheme(oprot).write(oprot, this);" << endl;
+
+  indent_down();
+  indent(out) << "  }" << endl << endl;
+}
+
+void t_java_generator::generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "public _Fields fieldForId(int fieldId) {" << endl;
+  indent(out) << "  return _Fields.findByThriftId(fieldId);" << endl;
+  indent(out) << "}" << endl << endl;
+}
+
+void t_java_generator::generate_reflection_getters(ostringstream& out,
+                                                   t_type* type,
+                                                   string field_name,
+                                                   string cap_name) {
+  indent(out) << "case " << constant_name(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "return " << (type->is_bool() ? "is" : "get") << cap_name << "();" << endl << endl;
+  indent_down();
+}
+
+void t_java_generator::generate_reflection_setters(ostringstream& out,
+                                                   t_type* type,
+                                                   string field_name,
+                                                   string cap_name) {
+  const bool is_binary = type->is_base_type() && ((t_base_type*)type)->is_binary();
+  indent(out) << "case " << constant_name(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "if (value == null) {" << endl;
+  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
+  indent(out) << "} else {" << endl;
+  if (is_binary) {
+    indent_up();
+    indent(out) << "if (value instanceof byte[]) {" << endl;
+    indent(out) << "  set" << cap_name << "((byte[])value);" << endl;
+    indent(out) << "} else {" << endl;
+  }
+  indent(out) << "  set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl;
+  if (is_binary) {
+    indent(out) << "}" << endl;
+    indent_down();
+  }
+  indent(out) << "}" << endl;
+  indent(out) << "break;" << endl << endl;
+
+  indent_down();
+}
+
+void t_java_generator::generate_generic_field_getters_setters(std::ofstream& out,
+                                                              t_struct* tstruct) {
+  std::ostringstream getter_stream;
+  std::ostringstream setter_stream;
+
+  // build up the bodies of both the getter and setter at once
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    indent_up();
+    generate_reflection_setters(setter_stream, type, field_name, cap_name);
+    generate_reflection_getters(getter_stream, type, field_name, cap_name);
+    indent_down();
+  }
+
+  // create the setter
+
+  indent(out) << "public void setFieldValue(_Fields field, Object value) {" << endl;
+  indent(out) << "  switch (field) {" << endl;
+  out << setter_stream.str();
+  indent(out) << "  }" << endl;
+  indent(out) << "}" << endl << endl;
+
+  // create the getter
+  indent(out) << "public Object getFieldValue(_Fields field) {" << endl;
+  indent_up();
+  indent(out) << "switch (field) {" << endl;
+  out << getter_stream.str();
+  indent(out) << "}" << endl;
+  indent(out) << "throw new IllegalStateException();" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+// Creates a generic isSet method that takes the field number as argument
+void t_java_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // create the isSet method
+  indent(out) << "/** Returns true if field corresponding to fieldID is set (has been assigned a "
+                 "value) and false otherwise */" << endl;
+  indent(out) << "public boolean isSet(_Fields field) {" << endl;
+  indent_up();
+  indent(out) << "if (field == null) {" << endl;
+  indent(out) << "  throw new IllegalArgumentException();" << endl;
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "switch (field) {" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
+    indent_down();
+  }
+
+  indent(out) << "}" << endl;
+  indent(out) << "throw new IllegalStateException();" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
+ * for the given struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_java_generator::generate_java_bean_boilerplate(ofstream& out, t_struct* tstruct) {
+  isset_type issetType = needs_isset(tstruct);
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+    bool optional = use_option_type_ && field->get_req() == t_field::T_OPTIONAL;
+    bool is_deprecated = this->is_deprecated(field->annotations_);
+
+    if (type->is_container()) {
+      // Method to return the size of the collection
+      if (optional) {
+        if (is_deprecated) {
+          indent(out) << "@Deprecated" << endl;
+        }
+        indent(out) << "public Option<Integer> get" << cap_name;
+        out << get_cap_name("size() {") << endl;
+
+        indent_up();
+        indent(out) << "if (this." << field_name << " == null) {" << endl;
+        indent_up();
+        indent(out) << "return Option.none();" << endl;
+        indent_down();
+        indent(out) << "} else {" << endl;
+        indent_up();
+        indent(out) << "return Option.some(this." << field_name << ".size());" << endl;
+        indent_down();
+        indent(out) << "}" << endl;
+        indent_down();
+        indent(out) << "}" << endl << endl;
+      } else {
+        if (is_deprecated) {
+          indent(out) << "@Deprecated" << endl;
+        }
+        indent(out) << "public int get" << cap_name;
+        out << get_cap_name("size() {") << endl;
+
+        indent_up();
+        indent(out) << "return (this." << field_name << " == null) ? 0 : "
+                    << "this." << field_name << ".size();" << endl;
+        indent_down();
+        indent(out) << "}" << endl << endl;
+      }
+    }
+
+    if (type->is_set() || type->is_list()) {
+      t_type* element_type;
+      if (type->is_set()) {
+        element_type = ((t_set*)type)->get_elem_type();
+      } else {
+        element_type = ((t_list*)type)->get_elem_type();
+      }
+
+      // Iterator getter for sets and lists
+      if (optional) {
+        if (is_deprecated) {
+          indent(out) << "@Deprecated" << endl;
+        }
+        indent(out) << "public Option<java.util.Iterator<" << type_name(element_type, true, false)
+                    << ">> get" << cap_name;
+        out << get_cap_name("iterator() {") << endl;
+
+        indent_up();
+        indent(out) << "if (this." << field_name << " == null) {" << endl;
+        indent_up();
+        indent(out) << "return Option.none();" << endl;
+        indent_down();
+        indent(out) << "} else {" << endl;
+        indent_up();
+        indent(out) << "return Option.some(this." << field_name << ".iterator());" << endl;
+        indent_down();
+        indent(out) << "}" << endl;
+        indent_down();
+        indent(out) << "}" << endl << endl;
+      } else {
+        if (is_deprecated) {
+          indent(out) << "@Deprecated" << endl;
+        }
+        indent(out) << "public java.util.Iterator<" << type_name(element_type, true, false)
+                    << "> get" << cap_name;
+        out << get_cap_name("iterator() {") << endl;
+
+        indent_up();
+        indent(out) << "return (this." << field_name << " == null) ? null : "
+                    << "this." << field_name << ".iterator();" << endl;
+        indent_down();
+        indent(out) << "}" << endl << endl;
+      }
+
+      // Add to set or list, create if the set/list is null
+      if (is_deprecated) {
+        indent(out) << "@Deprecated" << endl;
+      }
+      indent(out) << "public void add" << get_cap_name("to");
+      out << cap_name << "(" << type_name(element_type) << " elem) {" << endl;
+
+      indent_up();
+      indent(out) << "if (this." << field_name << " == null) {" << endl;
+      indent_up();
+      indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();"
+                  << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+      indent(out) << "thi

<TRUNCATED>

[02/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_py_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc
new file mode 100644
index 0000000..6401c28
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc
@@ -0,0 +1,2625 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+#include <algorithm>
+#include "thrift/platform.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Python code generator.
+ *
+ */
+class t_py_generator : public t_generator {
+public:
+  t_py_generator(t_program* program,
+                 const std::map<std::string, std::string>& parsed_options,
+                 const std::string& option_string)
+    : t_generator(program) {
+    std::map<std::string, std::string>::const_iterator iter;
+
+
+    gen_newstyle_ = true;
+    gen_utf8strings_ = true;
+    gen_dynbase_ = false;
+    gen_slots_ = false;
+    gen_tornado_ = false;
+    gen_twisted_ = false;
+    gen_dynamic_ = false;
+    coding_ = "";
+    gen_dynbaseclass_ = "";
+    gen_dynbaseclass_exc_ = "";
+    gen_dynbaseclass_frozen_ = "";
+    import_dynbase_ = "";
+    package_prefix_ = "";
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("new_style") == 0) {
+        pwarning(0, "new_style is enabled by default, so the option will be removed in the near future.\n");
+      } else if( iter->first.compare("old_style") == 0) {
+        gen_newstyle_ = false;
+        pwarning(0, "old_style is deprecated and may be removed in the future.\n");
+      } else if( iter->first.compare("utf8strings") == 0) {
+        pwarning(0, "utf8strings is enabled by default, so the option will be removed in the near future.\n");
+      } else if( iter->first.compare("no_utf8strings") == 0) {
+        gen_utf8strings_ = false;
+      } else if( iter->first.compare("slots") == 0) {
+        gen_slots_ = true;
+      } else if( iter->first.compare("package_prefix") == 0) {
+        package_prefix_ = iter->second;
+      } else if( iter->first.compare("dynamic") == 0) {
+        gen_dynamic_ = true;
+        gen_newstyle_ = false; // dynamic is newstyle
+        if( gen_dynbaseclass_.empty()) {
+          gen_dynbaseclass_ = "TBase";
+        }
+        if( gen_dynbaseclass_frozen_.empty()) {
+          gen_dynbaseclass_frozen_ = "TFrozenBase";
+        }
+        if( gen_dynbaseclass_exc_.empty()) {
+          gen_dynbaseclass_exc_ = "TExceptionBase";
+        }
+        if( import_dynbase_.empty()) {
+          import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TTransport\n";
+        }
+      } else if( iter->first.compare("dynbase") == 0) {
+        gen_dynbase_ = true;
+        gen_dynbaseclass_ = (iter->second);
+      } else if( iter->first.compare("dynfrozen") == 0) {
+        gen_dynbaseclass_frozen_ = (iter->second);
+      } else if( iter->first.compare("dynexc") == 0) {
+        gen_dynbaseclass_exc_ = (iter->second);
+      } else if( iter->first.compare("dynimport") == 0) {
+        gen_dynbase_ = true;
+        import_dynbase_ = (iter->second);
+      } else if( iter->first.compare("twisted") == 0) {
+        gen_twisted_ = true;
+      } else if( iter->first.compare("tornado") == 0) {
+        gen_tornado_ = true;
+      } else if( iter->first.compare("coding") == 0) {
+        coding_ = iter->second;
+      } else {
+        throw "unknown option py:" + iter->first;
+      }
+    }
+
+    if (gen_twisted_ && gen_tornado_) {
+      throw "at most one of 'twisted' and 'tornado' are allowed";
+    }
+
+    copy_options_ = option_string;
+
+    if (gen_twisted_) {
+      out_dir_base_ = "gen-py.twisted";
+    } else if (gen_tornado_) {
+      out_dir_base_ = "gen-py.tornado";
+    } else {
+      out_dir_base_ = "gen-py";
+    }
+  }
+
+  virtual std::string indent_str() const {
+    return "    ";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+  /**
+   * Struct generation code
+   */
+
+  void generate_py_struct(t_struct* tstruct, bool is_exception);
+  void generate_py_struct_definition(std::ofstream& out,
+                                     t_struct* tstruct,
+                                     bool is_xception = false);
+  void generate_py_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_py_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_py_struct_required_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_py_function_helpers(t_function* tfunction);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_remote(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "");
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_python_docstring(std::ofstream& out, t_struct* tstruct);
+
+  void generate_python_docstring(std::ofstream& out, t_function* tfunction);
+
+  void generate_python_docstring(std::ofstream& out,
+                                 t_doc* tdoc,
+                                 t_struct* tstruct,
+                                 const char* subheader);
+
+  void generate_python_docstring(std::ofstream& out, t_doc* tdoc);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string py_autogen_comment();
+  std::string py_imports();
+  std::string render_includes();
+  std::string declare_argument(t_field* tfield);
+  std::string render_field_default_value(t_field* tfield);
+  std::string type_name(t_type* ttype);
+  std::string function_signature(t_function* tfunction, bool interface = false);
+  std::string argument_list(t_struct* tstruct,
+                            std::vector<std::string>* pre = NULL,
+                            std::vector<std::string>* post = NULL);
+  std::string type_to_enum(t_type* ttype);
+  std::string type_to_spec_args(t_type* ttype);
+
+  static bool is_valid_namespace(const std::string& sub_namespace) {
+    return sub_namespace == "twisted";
+  }
+
+  static std::string get_real_py_module(const t_program* program, bool gen_twisted, std::string package_dir="") {
+    if (gen_twisted) {
+      std::string twisted_module = program->get_namespace("py.twisted");
+      if (!twisted_module.empty()) {
+        return twisted_module;
+      }
+    }
+
+    std::string real_module = program->get_namespace("py");
+    if (real_module.empty()) {
+      return program->get_name();
+    }
+    return package_dir + real_module;
+  }
+
+  static bool is_immutable(t_type* ttype) {
+    return ttype->annotations_.find("python.immutable") != ttype->annotations_.end();
+  }
+
+private:
+
+  /**
+   * True if we should generate new-style classes.
+   */
+  bool gen_newstyle_;
+
+  /**
+  * True if we should generate dynamic style classes.
+  */
+  bool gen_dynamic_;
+
+  bool gen_dynbase_;
+  std::string gen_dynbaseclass_;
+  std::string gen_dynbaseclass_frozen_;
+  std::string gen_dynbaseclass_exc_;
+
+  std::string import_dynbase_;
+
+  bool gen_slots_;
+
+  std::string copy_options_;
+
+  /**
+   * True if we should generate Twisted-friendly RPC services.
+   */
+  bool gen_twisted_;
+
+  /**
+   * True if we should generate code for use with Tornado
+   */
+  bool gen_tornado_;
+
+  /**
+   * True if strings should be encoded using utf-8.
+   */
+  bool gen_utf8strings_;
+
+  /**
+   * specify generated file encoding
+   * eg. # -*- coding: utf-8 -*-
+   */
+  string coding_;
+
+  string package_prefix_;
+
+  /**
+   * File streams
+   */
+
+  std::ofstream f_types_;
+  std::ofstream f_consts_;
+  std::ofstream f_service_;
+
+  std::string package_dir_;
+  std::string module_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_py_generator::init_generator() {
+  // Make output directory
+  string module = get_real_py_module(program_, gen_twisted_);
+  package_dir_ = get_out_dir();
+  module_ = module;
+  while (true) {
+    // TODO: Do better error checking here.
+    MKDIR(package_dir_.c_str());
+    std::ofstream init_py((package_dir_ + "/__init__.py").c_str(), std::ios_base::app);
+    init_py.close();
+    if (module.empty()) {
+      break;
+    }
+    string::size_type pos = module.find('.');
+    if (pos == string::npos) {
+      package_dir_ += "/";
+      package_dir_ += module;
+      module.clear();
+    } else {
+      package_dir_ += "/";
+      package_dir_ += module.substr(0, pos);
+      module.erase(0, pos + 1);
+    }
+  }
+
+  // Make output file
+  string f_types_name = package_dir_ + "/" + "ttypes.py";
+  f_types_.open(f_types_name.c_str());
+
+  string f_consts_name = package_dir_ + "/" + "constants.py";
+  f_consts_.open(f_consts_name.c_str());
+
+  string f_init_name = package_dir_ + "/__init__.py";
+  ofstream f_init;
+  f_init.open(f_init_name.c_str());
+  f_init << "__all__ = ['ttypes', 'constants'";
+  vector<t_service*> services = program_->get_services();
+  vector<t_service*>::iterator sv_iter;
+  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+    f_init << ", '" << (*sv_iter)->get_name() << "'";
+  }
+  f_init << "]" << endl;
+  f_init.close();
+
+  // Print header
+  f_types_ << py_autogen_comment() << endl
+           << py_imports() << endl
+           << render_includes() << endl
+           << "from thrift.transport import TTransport" << endl
+           << import_dynbase_;
+
+  f_consts_ <<
+    py_autogen_comment() << endl <<
+    py_imports() << endl <<
+    "from .ttypes import *" << endl;
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_py_generator::render_includes() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  for (size_t i = 0; i < includes.size(); ++i) {
+    result += "import " + get_real_py_module(includes[i], gen_twisted_, package_prefix_) + ".ttypes\n";
+  }
+  return result;
+}
+
+/**
+ * Autogen'd comment
+ */
+string t_py_generator::py_autogen_comment() {
+  string coding;
+  if (!coding_.empty()) {
+      coding = "# -*- coding: " + coding_ + " -*-\n";
+  }
+  return coding + std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+         + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n"
+         + "#  options string: " + copy_options_ + "\n" + "#\n";
+}
+
+/**
+ * Prints standard thrift imports
+ */
+string t_py_generator::py_imports() {
+  ostringstream ss;
+  ss << "from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, "
+        "TApplicationException"
+     << endl
+     << "from thrift.protocol.TProtocol import TProtocolException";
+  if (gen_utf8strings_) {
+    ss << endl << "import sys";
+  }
+  return ss.str();
+}
+
+/**
+ * Closes the type files
+ */
+void t_py_generator::close_generator() {
+  // Close types file
+  f_types_.close();
+  f_consts_.close();
+}
+
+/**
+ * Generates a typedef. This is not done in Python, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_py_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Generates code for an enumerated type. Done using a class to scope
+ * the values.
+ *
+ * @param tenum The enumeration
+ */
+void t_py_generator::generate_enum(t_enum* tenum) {
+  std::ostringstream to_string_mapping, from_string_mapping;
+
+  f_types_ << endl << endl << "class " << tenum->get_name() << (gen_newstyle_ ? "(object)" : "")
+           << (gen_dynamic_ ? "(" + gen_dynbaseclass_ + ")" : "") << ":" << endl;
+  indent_up();
+  generate_python_docstring(f_types_, tenum);
+
+  to_string_mapping << indent() << "_VALUES_TO_NAMES = {" << endl;
+  from_string_mapping << indent() << "_NAMES_TO_VALUES = {" << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_types_) << (*c_iter)->get_name() << " = " << value << endl;
+
+    // Dictionaries to/from string names of enums
+    to_string_mapping << indent() << indent() << value << ": \""
+                      << escape_string((*c_iter)->get_name()) << "\"," << endl;
+    from_string_mapping << indent() << indent() << '"' << escape_string((*c_iter)->get_name())
+                        << "\": " << value << ',' << endl;
+  }
+  to_string_mapping << indent() << "}" << endl;
+  from_string_mapping << indent() << "}" << endl;
+
+  indent_down();
+  f_types_ << endl;
+  f_types_ << to_string_mapping.str() << endl << from_string_mapping.str();
+}
+
+/**
+ * Generate a constant value
+ */
+void t_py_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  indent(f_consts_) << name << " = " << render_const_value(type, value);
+  f_consts_ << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_py_generator::render_const_value(t_type* type, t_const_value* value) {
+  type = get_true_type(type);
+  std::ostringstream out;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "True" : "False");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    out << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << type_name(type) << "(**{" << endl;
+    indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      indent(out) << render_const_value(g_type_string, v_iter->first) << ": "
+          << render_const_value(field_type, v_iter->second) << "," << endl;
+    }
+    indent_down();
+    indent(out) << "})";
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    if (is_immutable(type)) {
+      out << "TFrozenDict(";
+    }
+    out << "{" << endl;
+    indent_up();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      indent(out) << render_const_value(ktype, v_iter->first) << ": "
+          << render_const_value(vtype, v_iter->second) << "," << endl;
+    }
+    indent_down();
+    indent(out) << "}";
+    if (is_immutable(type)) {
+      out << ")";
+    }
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    if (type->is_set()) {
+      if (is_immutable(type)) {
+        out << "frozen";
+      }
+      out << "set(";
+    }
+    if (is_immutable(type) || type->is_set()) {
+      out << "(" << endl;
+    } else {
+      out << "[" << endl;
+    }
+    indent_up();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      indent(out) << render_const_value(etype, *v_iter) << "," << endl;
+    }
+    indent_down();
+    if (is_immutable(type) || type->is_set()) {
+      indent(out) << ")";
+    } else {
+      indent(out) << "]";
+    }
+    if (type->is_set()) {
+      out << ")";
+    }
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+
+  return out.str();
+}
+
+/**
+ * Generates a python struct
+ */
+void t_py_generator::generate_struct(t_struct* tstruct) {
+  generate_py_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_py_generator::generate_xception(t_struct* txception) {
+  generate_py_struct(txception, true);
+}
+
+/**
+ * Generates a python struct
+ */
+void t_py_generator::generate_py_struct(t_struct* tstruct, bool is_exception) {
+  generate_py_struct_definition(f_types_, tstruct, is_exception);
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_py_generator::generate_py_struct_definition(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   bool is_exception) {
+  const vector<t_field*>& members = tstruct->get_members();
+  const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << endl << endl << "class " << tstruct->get_name();
+  if (is_exception) {
+    if (gen_dynamic_) {
+      out << "(" << gen_dynbaseclass_exc_ << ")";
+    } else {
+      out << "(TException)";
+    }
+  } else if (gen_dynamic_) {
+    if (is_immutable(tstruct)) {
+      out << "(" << gen_dynbaseclass_frozen_ << ")";
+    } else  {
+      out << "(" << gen_dynbaseclass_ << ")";
+    }
+  } else if (gen_newstyle_) {
+    out << "(object)";
+  }
+  out << ":" << endl;
+  indent_up();
+  generate_python_docstring(out, tstruct);
+
+  out << endl;
+
+  /*
+     Here we generate the structure specification for the fastbinary codec.
+     These specifications have the following structure:
+     thrift_spec -> tuple of item_spec
+     item_spec -> None | (tag, type_enum, name, spec_args, default)
+     tag -> integer
+     type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ...
+     name -> string_literal
+     default -> None  # Handled by __init__
+     spec_args -> None  # For simple types
+                | (type_enum, spec_args)  # Value type for list/set
+                | (type_enum, spec_args, type_enum, spec_args)
+                  # Key and value for map
+                | (class_name, spec_args_ptr) # For struct/exception
+     class_name -> identifier  # Basically a pointer to the class
+     spec_args_ptr -> expression  # just class_name.spec_args
+
+     TODO(dreiss): Consider making this work for structs with negative tags.
+  */
+
+  if (gen_slots_) {
+    indent(out) << "__slots__ = (" << endl;
+    indent_up();
+    for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
+      indent(out) << "'" << (*m_iter)->get_name() << "'," << endl;
+    }
+    indent_down();
+    indent(out) << ")" << endl << endl;
+  }
+
+  // TODO(dreiss): Look into generating an empty tuple instead of None
+  // for structures with no members.
+  // TODO(dreiss): Test encoding of structs where some inner structs
+  // don't have thrift_spec.
+  if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) {
+    indent(out) << "thrift_spec = (" << endl;
+    indent_up();
+
+    int sorted_keys_pos = 0;
+    for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
+
+      for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) {
+        indent(out) << "None,  # " << sorted_keys_pos << endl;
+      }
+
+      indent(out) << "(" << (*m_iter)->get_key() << ", " << type_to_enum((*m_iter)->get_type())
+                  << ", "
+                  << "'" << (*m_iter)->get_name() << "'"
+                  << ", " << type_to_spec_args((*m_iter)->get_type()) << ", "
+                  << render_field_default_value(*m_iter) << ", "
+                  << "),"
+                  << "  # " << sorted_keys_pos << endl;
+
+      sorted_keys_pos++;
+    }
+
+    indent_down();
+    indent(out) << ")" << endl;
+  } else {
+    indent(out) << "thrift_spec = None" << endl;
+  }
+
+  if (members.size() > 0) {
+    out << endl;
+    out << indent() << "def __init__(self,";
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      // This fills in default values, as opposed to nulls
+      out << " " << declare_argument(*m_iter) << ",";
+    }
+
+    out << "):" << endl;
+
+    indent_up();
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      // Initialize fields
+      t_type* type = (*m_iter)->get_type();
+      if (!type->is_base_type() && !type->is_enum() && (*m_iter)->get_value() != NULL) {
+        indent(out) << "if " << (*m_iter)->get_name() << " is "
+                    << "self.thrift_spec[" << (*m_iter)->get_key() << "][4]:" << endl;
+        indent_up();
+        indent(out) << (*m_iter)->get_name() << " = " << render_field_default_value(*m_iter)
+                    << endl;
+        indent_down();
+      }
+
+      if (is_immutable(tstruct)) {
+        if (gen_newstyle_ || gen_dynamic_) {
+          indent(out) << "super(" << tstruct->get_name() << ", self).__setattr__('"
+                      << (*m_iter)->get_name() << "', " << (*m_iter)->get_name() << ")" << endl;
+        } else {
+          indent(out) << "self.__dict__['" << (*m_iter)->get_name()
+                      << "'] = " << (*m_iter)->get_name() << endl;
+        }
+      } else {
+        indent(out) << "self." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << endl;
+      }
+    }
+
+    indent_down();
+  }
+
+  if (is_immutable(tstruct)) {
+    out << endl;
+    out << indent() << "def __setattr__(self, *args):" << endl
+        << indent() << indent_str() << "raise TypeError(\"can't modify immutable instance\")" << endl
+        << endl;
+    out << indent() << "def __delattr__(self, *args):" << endl
+        << indent() << indent_str() << "raise TypeError(\"can't modify immutable instance\")" << endl
+        << endl;
+
+    // Hash all of the members in order, and also hash in the class
+    // to avoid collisions for stuff like single-field structures.
+    out << indent() << "def __hash__(self):" << endl
+        << indent() << indent_str() << "return hash(self.__class__) ^ hash((";
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << "self." << (*m_iter)->get_name() << ", ";
+    }
+
+    out << "))" << endl;
+  }
+
+  if (!gen_dynamic_) {
+    out << endl;
+    generate_py_struct_reader(out, tstruct);
+    generate_py_struct_writer(out, tstruct);
+  }
+
+  // For exceptions only, generate a __str__ method. This is
+  // because when raised exceptions are printed to the console, __repr__
+  // isn't used. See python bug #5882
+  if (is_exception) {
+    out << endl;
+    out << indent() << "def __str__(self):" << endl
+        << indent() << indent_str() << "return repr(self)" << endl;
+  }
+
+  if (!gen_slots_) {
+    out << endl;
+    // Printing utilities so that on the command line thrift
+    // structs look pretty like dictionaries
+    indent(out) << "def __repr__(self):" << endl;
+    indent_up();
+    out << indent() << "L = ['%s=%r' % (key, value)" << endl
+        << indent() << "     for key, value in self.__dict__.items()]" << endl
+        << indent() << "return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl
+        << endl;
+    indent_down();
+
+    // Equality and inequality methods that compare by value
+    out << indent() << "def __eq__(self, other):" << endl;
+    indent_up();
+    out << indent() << "return isinstance(other, self.__class__) and "
+                       "self.__dict__ == other.__dict__" << endl;
+    indent_down();
+    out << endl;
+
+    out << indent() << "def __ne__(self, other):" << endl;
+    indent_up();
+
+    out << indent() << "return not (self == other)" << endl;
+    indent_down();
+  } else if (!gen_dynamic_) {
+    out << endl;
+    // no base class available to implement __eq__ and __repr__ and __ne__ for us
+    // so we must provide one that uses __slots__
+    indent(out) << "def __repr__(self):" << endl;
+    indent_up();
+    out << indent() << "L = ['%s=%r' % (key, getattr(self, key))" << endl
+        << indent() << "     for key in self.__slots__]" << endl
+        << indent() << "return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl
+        << endl;
+    indent_down();
+
+    // Equality method that compares each attribute by value and type, walking __slots__
+    out << indent() << "def __eq__(self, other):" << endl;
+    indent_up();
+    out << indent() << "if not isinstance(other, self.__class__):" << endl
+        << indent() << indent_str() << "return False" << endl
+        << indent() << "for attr in self.__slots__:" << endl
+        << indent() << indent_str() << "my_val = getattr(self, attr)" << endl
+        << indent() << indent_str() << "other_val = getattr(other, attr)" << endl
+        << indent() << indent_str() << "if my_val != other_val:" << endl
+        << indent() << indent_str() << indent_str() << "return False" << endl
+        << indent() << "return True" << endl
+        << endl;
+    indent_down();
+
+    out << indent() << "def __ne__(self, other):" << endl
+        << indent() << indent_str() << "return not (self == other)" << endl;
+  }
+  indent_down();
+}
+
+/**
+ * Generates the read method for a struct
+ */
+void t_py_generator::generate_py_struct_reader(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (is_immutable(tstruct)) {
+    out << indent() << "@classmethod" << endl << indent() << "def read(cls, iprot):" << endl;
+  } else {
+    indent(out) << "def read(self, iprot):" << endl;
+  }
+  indent_up();
+
+  const char* id = is_immutable(tstruct) ? "cls" : "self";
+
+  indent(out) << "if iprot._fast_decode is not None "
+                 "and isinstance(iprot.trans, TTransport.CReadableTransport) "
+                 "and "
+              << id << ".thrift_spec is not None:" << endl;
+  indent_up();
+
+  if (is_immutable(tstruct)) {
+    indent(out) << "return iprot._fast_decode(None, iprot, (cls, cls.thrift_spec))" << endl;
+  } else {
+    indent(out) << "iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))" << endl;
+    indent(out) << "return" << endl;
+  }
+  indent_down();
+
+  indent(out) << "iprot.readStructBegin()" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while True:" << endl;
+  indent_up();
+
+  // Read beginning field marker
+  indent(out) << "(fname, ftype, fid) = iprot.readFieldBegin()" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if ftype == TType.STOP:" << endl;
+  indent_up();
+  indent(out) << "break" << endl;
+  indent_down();
+
+  // Switch statement on the field we are reading
+  bool first = true;
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << indent() << "if ";
+    } else {
+      out << indent() << "elif ";
+    }
+    out << "fid == " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << ":" << endl;
+    indent_up();
+    if (is_immutable(tstruct)) {
+      generate_deserialize_field(out, *f_iter);
+    } else {
+      generate_deserialize_field(out, *f_iter, "self.");
+    }
+    indent_down();
+    out << indent() << "else:" << endl << indent() << indent_str() << "iprot.skip(ftype)" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "else:" << endl << indent() << indent_str() << "iprot.skip(ftype)" << endl;
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd()" << endl;
+
+  indent_down();
+
+  indent(out) << "iprot.readStructEnd()" << endl;
+
+  if (is_immutable(tstruct)) {
+    indent(out) << "return cls(" << endl;
+    indent_up();
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      indent(out) << (*f_iter)->get_name() << "=" << (*f_iter)->get_name() << "," << endl;
+    }
+    indent_down();
+    indent(out) << ")" << endl;
+  }
+
+  indent_down();
+  out << endl;
+}
+
+void t_py_generator::generate_py_struct_writer(ofstream& out, t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "def write(self, oprot):" << endl;
+  indent_up();
+
+  indent(out) << "if oprot._fast_encode is not None and self.thrift_spec is not None:" << endl;
+  indent_up();
+
+  indent(out)
+      << "oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))"
+      << endl;
+  indent(out) << "return" << endl;
+  indent_down();
+
+  indent(out) << "oprot.writeStructBegin('" << name << "')" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    // Write field header
+    indent(out) << "if self." << (*f_iter)->get_name() << " is not None:" << endl;
+    indent_up();
+    indent(out) << "oprot.writeFieldBegin("
+                << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
+                << ", " << (*f_iter)->get_key() << ")" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "self.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd()" << endl;
+
+    indent_down();
+  }
+
+  // Write the struct map
+  out << indent() << "oprot.writeFieldStop()" << endl << indent() << "oprot.writeStructEnd()"
+      << endl;
+
+  out << endl;
+
+  indent_down();
+  generate_py_struct_required_validator(out, tstruct);
+}
+
+void t_py_generator::generate_py_struct_required_validator(ofstream& out, t_struct* tstruct) {
+  indent(out) << "def validate(self):" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+
+  if (fields.size() > 0) {
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = (*f_iter);
+      if (field->get_req() == t_field::T_REQUIRED) {
+        indent(out) << "if self." << field->get_name() << " is None:" << endl;
+        indent(out) << indent_str() << "raise TProtocolException(message='Required field "
+                    << field->get_name() << " is unset!')" << endl;
+      }
+    }
+  }
+
+  indent(out) << "return" << endl;
+  indent_down();
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_py_generator::generate_service(t_service* tservice) {
+  string f_service_name = package_dir_ + "/" + service_name_ + ".py";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << py_autogen_comment() << endl << py_imports() << endl;
+
+  if (tservice->get_extends() != NULL) {
+    f_service_ << "import "
+               << get_real_py_module(tservice->get_extends()->get_program(), gen_twisted_, package_prefix_) << "."
+               << tservice->get_extends()->get_name() << endl;
+  }
+
+  f_service_ << "import logging" << endl
+             << "from .ttypes import *" << endl
+             << "from thrift.Thrift import TProcessor" << endl
+             << "from thrift.transport import TTransport" << endl
+             << import_dynbase_;
+
+  if (gen_twisted_) {
+    f_service_ << "from zope.interface import Interface, implements" << endl
+               << "from twisted.internet import defer" << endl
+               << "from thrift.transport import TTwisted" << endl;
+  } else if (gen_tornado_) {
+    f_service_ << "from tornado import gen" << endl;
+    f_service_ << "from tornado import concurrent" << endl;
+  }
+
+  // Generate the three main parts of the service
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+  generate_service_remote(tservice);
+
+  // Close service file
+  f_service_.close();
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_py_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  f_service_ << endl << "# HELPER FUNCTIONS AND STRUCTURES" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_py_struct_definition(f_service_, ts, false);
+    generate_py_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_py_generator::generate_py_function_helpers(t_function* tfunction) {
+  if (!tfunction->is_oneway()) {
+    t_struct result(program_, tfunction->get_name() + "_result");
+    t_field success(tfunction->get_returntype(), "success", 0);
+    if (!tfunction->get_returntype()->is_void()) {
+      result.append(&success);
+    }
+
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& fields = xs->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      result.append(*f_iter);
+    }
+    generate_py_struct_definition(f_service_, &result, false);
+  }
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_py_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_if = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_if = "(" + extends + ".Iface)";
+  } else {
+    if (gen_twisted_) {
+      extends_if = "(Interface)";
+    } else if (gen_newstyle_ || gen_dynamic_ || gen_tornado_) {
+      extends_if = "(object)";
+    }
+  }
+
+  f_service_ << endl << endl << "class Iface" << extends_if << ":" << endl;
+  indent_up();
+  generate_python_docstring(f_service_, tservice);
+  vector<t_function*> functions = tservice->get_functions();
+  if (functions.empty()) {
+    f_service_ << indent() << "pass" << endl;
+  } else {
+    vector<t_function*>::iterator f_iter;
+    bool first = true;
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << endl;
+      }
+      f_service_ << indent() << "def " << function_signature(*f_iter, true) << ":" << endl;
+      indent_up();
+      generate_python_docstring(f_service_, (*f_iter));
+      f_service_ << indent() << "pass" << endl;
+      indent_down();
+    }
+  }
+
+  indent_down();
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_py_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    if (gen_twisted_) {
+      extends_client = "(" + extends + ".Client)";
+    } else {
+      extends_client = extends + ".Client, ";
+    }
+  } else {
+    if (gen_twisted_ && (gen_newstyle_ || gen_dynamic_)) {
+      extends_client = "(object)";
+    }
+  }
+
+  f_service_ << endl << endl;
+
+  if (gen_twisted_) {
+    f_service_ << "class Client" << extends_client << ":" << endl
+               << indent_str() << "implements(Iface)" << endl
+               << endl;
+  } else {
+    f_service_ << "class Client(" << extends_client << "Iface):" << endl;
+  }
+  indent_up();
+  generate_python_docstring(f_service_, tservice);
+
+  // Constructor function
+  if (gen_twisted_) {
+    f_service_ << indent() << "def __init__(self, transport, oprot_factory):" << endl;
+  } else if (gen_tornado_) {
+    f_service_ << indent()
+               << "def __init__(self, transport, iprot_factory, oprot_factory=None):" << endl;
+  } else {
+    f_service_ << indent() << "def __init__(self, iprot, oprot=None):" << endl;
+  }
+  indent_up();
+  if (extends.empty()) {
+    if (gen_twisted_) {
+      f_service_ << indent() << "self._transport = transport" << endl
+                 << indent() << "self._oprot_factory = oprot_factory" << endl
+                 << indent() << "self._seqid = 0" << endl
+                 << indent() << "self._reqs = {}" << endl;
+    } else if (gen_tornado_) {
+      f_service_ << indent() << "self._transport = transport" << endl
+                 << indent() << "self._iprot_factory = iprot_factory" << endl
+                 << indent() << "self._oprot_factory = (oprot_factory if oprot_factory is not None"
+                 << endl
+                 << indent() << "                       else iprot_factory)" << endl
+                 << indent() << "self._seqid = 0" << endl
+                 << indent() << "self._reqs = {}" << endl
+                 << indent() << "self._transport.io_loop.spawn_callback(self._start_receiving)"
+                 << endl;
+    } else {
+      f_service_ << indent() << "self._iprot = self._oprot = iprot" << endl
+                 << indent() << "if oprot is not None:" << endl
+                 << indent() << indent_str() << "self._oprot = oprot" << endl
+                 << indent() << "self._seqid = 0" << endl;
+    }
+  } else {
+    if (gen_twisted_) {
+      f_service_ << indent() << extends
+                 << ".Client.__init__(self, transport, oprot_factory)" << endl;
+    } else if (gen_tornado_) {
+      f_service_ << indent() << extends
+                 << ".Client.__init__(self, transport, iprot_factory, oprot_factory)" << endl;
+    } else {
+      f_service_ << indent() << extends << ".Client.__init__(self, iprot, oprot)" << endl;
+    }
+  }
+  indent_down();
+
+  if (gen_tornado_ && extends.empty()) {
+    f_service_ << endl <<
+      indent() << "@gen.engine" << endl <<
+      indent() << "def _start_receiving(self):" << endl;
+    indent_up();
+    indent(f_service_) << "while True:" << endl;
+    indent_up();
+    f_service_ << indent() << "try:" << endl
+               << indent() << indent_str() << "frame = yield self._transport.readFrame()" << endl
+               << indent() << "except TTransport.TTransportException as e:" << endl
+               << indent() << indent_str() << "for future in self._reqs.values():" << endl
+               << indent() << indent_str() << indent_str() << "future.set_exception(e)" << endl
+               << indent() << indent_str() << "self._reqs = {}" << endl
+               << indent() << indent_str() << "return" << endl
+               << indent() << "tr = TTransport.TMemoryBuffer(frame)" << endl
+               << indent() << "iprot = self._iprot_factory.getProtocol(tr)" << endl
+               << indent() << "(fname, mtype, rseqid) = iprot.readMessageBegin()" << endl
+               << indent() << "method = getattr(self, 'recv_' + fname)" << endl
+               << indent() << "future = self._reqs.pop(rseqid, None)" << endl
+               << indent() << "if not future:" << endl
+               << indent() << indent_str() << "# future has already been discarded" << endl
+               << indent() << indent_str() << "continue" << endl
+               << indent() << "try:" << endl
+               << indent() << indent_str() << "result = method(iprot, mtype, rseqid)" << endl
+               << indent() << "except Exception as e:" << endl
+               << indent() << indent_str() << "future.set_exception(e)" << endl
+               << indent() << "else:" << endl
+               << indent() << indent_str() << "future.set_result(result)" << endl;
+    indent_down();
+    indent_down();
+  }
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+
+    f_service_ << endl;
+    // Open function
+    indent(f_service_) << "def " << function_signature(*f_iter, false) << ":" << endl;
+    indent_up();
+    generate_python_docstring(f_service_, (*f_iter));
+    if (gen_twisted_) {
+      indent(f_service_) << "seqid = self._seqid = self._seqid + 1" << endl;
+      indent(f_service_) << "self._reqs[seqid] = defer.Deferred()" << endl << endl;
+      indent(f_service_) << "d = defer.maybeDeferred(self.send_" << funname;
+
+    } else if (gen_tornado_) {
+      indent(f_service_) << "self._seqid += 1" << endl;
+      if (!(*f_iter)->is_oneway()) {
+        indent(f_service_) << "future = self._reqs[self._seqid] = concurrent.Future()" << endl;
+      }
+      indent(f_service_) << "self.send_" << funname << "(";
+
+    } else {
+      indent(f_service_) << "self.send_" << funname << "(";
+    }
+
+    bool first = true;
+    if (gen_twisted_) {
+      // we need a leading comma if there are args, since it's called as maybeDeferred(funcname,
+      // arg)
+      first = false;
+    }
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << (*fld_iter)->get_name();
+    }
+
+    f_service_ << ")" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      if (gen_twisted_) {
+        // nothing. See the next block.
+      } else if (gen_tornado_) {
+        indent(f_service_) << "return future" << endl;
+      } else {
+        f_service_ << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          f_service_ << "return ";
+        }
+        f_service_ << "self.recv_" << funname << "()" << endl;
+      }
+    }
+    indent_down();
+
+    if (gen_twisted_) {
+      // This block injects the body of the send_<> method for twisted (and a cb/eb pair)
+      indent_up();
+      indent(f_service_) << "d.addCallbacks(" << endl;
+
+      indent_up();
+      f_service_ << indent() << "callback=self.cb_send_" << funname << "," << endl << indent()
+                 << "callbackArgs=(seqid,)," << endl << indent() << "errback=self.eb_send_"
+                 << funname << "," << endl << indent() << "errbackArgs=(seqid,))" << endl;
+      indent_down();
+
+      indent(f_service_) << "return d" << endl;
+      indent_down();
+      f_service_ << endl;
+
+      indent(f_service_) << "def cb_send_" << funname << "(self, _, seqid):" << endl;
+      indent_up();
+      if ((*f_iter)->is_oneway()) {
+        // if one-way, fire the deferred & remove it from _reqs
+        f_service_ << indent() << "d = self._reqs.pop(seqid)" << endl << indent()
+                   << "d.callback(None)" << endl << indent() << "return d" << endl;
+      } else {
+        f_service_ << indent() << "return self._reqs[seqid]" << endl;
+      }
+      indent_down();
+      f_service_ << endl;
+
+      // add an errback to fail the request if the call to send_<> raised an exception
+      indent(f_service_) << "def eb_send_" << funname << "(self, f, seqid):" << endl;
+      indent_up();
+      f_service_ << indent() << "d = self._reqs.pop(seqid)" << endl << indent() << "d.errback(f)"
+                 << endl << indent() << "return d" << endl;
+      indent_down();
+    }
+
+    f_service_ << endl;
+    indent(f_service_) << "def send_" << function_signature(*f_iter, false) << ":" << endl;
+    indent_up();
+
+    std::string argsname = (*f_iter)->get_name() + "_args";
+    std::string messageType = (*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL";
+
+    // Serialize the request header
+    if (gen_twisted_ || gen_tornado_) {
+      f_service_ << indent() << "oprot = self._oprot_factory.getProtocol(self._transport)" << endl
+                 << indent() << "oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', "
+                 << messageType << ", self._seqid)" << endl;
+    } else {
+      f_service_ << indent() << "self._oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', "
+                 << messageType << ", self._seqid)" << endl;
+    }
+
+    f_service_ << indent() << "args = " << argsname << "()" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
+                 << (*fld_iter)->get_name() << endl;
+    }
+
+    // Write to the stream
+    if (gen_twisted_ || gen_tornado_) {
+      f_service_ << indent() << "args.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()"
+                 << endl << indent() << "oprot.trans.flush()" << endl;
+    } else {
+      f_service_ << indent() << "args.write(self._oprot)" << endl << indent()
+                 << "self._oprot.writeMessageEnd()" << endl << indent()
+                 << "self._oprot.trans.flush()" << endl;
+    }
+
+    indent_down();
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = (*f_iter)->get_name() + "_result";
+      // Open function
+      f_service_ << endl;
+      if (gen_twisted_ || gen_tornado_) {
+        f_service_ << indent() << "def recv_" << (*f_iter)->get_name()
+                   << "(self, iprot, mtype, rseqid):" << endl;
+      } else {
+        t_struct noargs(program_);
+        t_function recv_function((*f_iter)->get_returntype(),
+                                 string("recv_") + (*f_iter)->get_name(),
+                                 &noargs);
+        f_service_ << indent() << "def " << function_signature(&recv_function) << ":" << endl;
+      }
+      indent_up();
+
+      // TODO(mcslee): Validate message reply here, seq ids etc.
+
+      if (gen_twisted_) {
+        f_service_ << indent() << "d = self._reqs.pop(rseqid)" << endl;
+      } else if (gen_tornado_) {
+      } else {
+        f_service_ << indent() << "iprot = self._iprot" << endl << indent()
+                   << "(fname, mtype, rseqid) = iprot.readMessageBegin()" << endl;
+      }
+
+      f_service_ << indent() << "if mtype == TMessageType.EXCEPTION:" << endl
+                 << indent() << indent_str() << "x = TApplicationException()" << endl;
+
+      if (gen_twisted_) {
+        f_service_ << indent() << indent_str() << "x.read(iprot)" << endl << indent()
+                   << indent_str() << "iprot.readMessageEnd()" << endl << indent() << indent_str() << "return d.errback(x)"
+                   << endl << indent() << "result = " << resultname << "()" << endl << indent()
+                   << "result.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl;
+      } else {
+        f_service_ << indent() << indent_str() << "x.read(iprot)" << endl << indent()
+                   << indent_str() << "iprot.readMessageEnd()" << endl << indent() << indent_str() << "raise x" << endl
+                   << indent() << "result = " << resultname << "()" << endl << indent()
+                   << "result.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if result.success is not None:" << endl;
+        if (gen_twisted_) {
+          f_service_ << indent() << indent_str() << "return d.callback(result.success)" << endl;
+        } else {
+          f_service_ << indent() << indent_str() << "return result.success" << endl;
+        }
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "if result." << (*x_iter)->get_name() << " is not None:" << endl;
+        if (gen_twisted_) {
+          f_service_ << indent() << indent_str() << "return d.errback(result." << (*x_iter)->get_name() << ")"
+                     << endl;
+        } else {
+          f_service_ << indent() << indent_str() << "raise result." << (*x_iter)->get_name() << "" << endl;
+        }
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        if (gen_twisted_) {
+          f_service_ << indent() << "return d.callback(None)" << endl;
+        } else {
+          f_service_ << indent() << "return" << endl;
+        }
+      } else {
+        if (gen_twisted_) {
+          f_service_
+              << indent()
+              << "return d.errback(TApplicationException(TApplicationException.MISSING_RESULT, \""
+              << (*f_iter)->get_name() << " failed: unknown result\"))" << endl;
+        } else {
+          f_service_ << indent()
+                     << "raise TApplicationException(TApplicationException.MISSING_RESULT, \""
+                     << (*f_iter)->get_name() << " failed: unknown result\")" << endl;
+        }
+      }
+
+      // Close function
+      indent_down();
+    }
+  }
+
+  indent_down();
+}
+
+/**
+ * Generates a command line tool for making remote requests
+ *
+ * @param tservice The service to generate a remote for.
+ */
+void t_py_generator::generate_service_remote(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  // Get all function from parents
+  t_service* parent = tservice->get_extends();
+  while (parent != NULL) {
+    vector<t_function*> p_functions = parent->get_functions();
+    functions.insert(functions.end(), p_functions.begin(), p_functions.end());
+    parent = parent->get_extends();
+  }
+  vector<t_function*>::iterator f_iter;
+
+  string f_remote_name = package_dir_ + "/" + service_name_ + "-remote";
+  ofstream f_remote;
+  f_remote.open(f_remote_name.c_str());
+
+  f_remote <<
+    "#!/usr/bin/env python" << endl <<
+    py_autogen_comment() << endl <<
+    "import sys" << endl <<
+    "import pprint" << endl <<
+    "if sys.version_info[0] > 2:" << endl <<
+    indent_str() << "from urllib.parse import urlparse" << endl <<
+    "else:" << endl <<
+    indent_str() << "from urlparse import urlparse" << endl <<
+    "from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient" << endl <<
+    "from thrift.protocol.TBinaryProtocol import TBinaryProtocol" << endl <<
+    endl;
+
+  f_remote <<
+    "from " << module_ << " import " << service_name_ << endl <<
+    "from " << module_ << ".ttypes import *" << endl <<
+    endl;
+
+  f_remote <<
+    "if len(sys.argv) <= 1 or sys.argv[1] == '--help':" << endl <<
+    indent_str() << "print('')" << endl <<
+    indent_str() << "print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] function [arg1 [arg2...]]')" << endl <<
+    indent_str() << "print('')" << endl <<
+    indent_str() << "print('Functions:')" << endl;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_remote << indent_str() << "print('  " << (*f_iter)->get_returntype()->get_name() << " "
+             << (*f_iter)->get_name() << "(";
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const std::vector<t_field*>& args = arg_struct->get_members();
+    vector<t_field*>::const_iterator a_iter;
+    std::vector<t_field*>::size_type num_args = args.size();
+    bool first = true;
+    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
+      if (first) {
+        first = false;
+      } else {
+        f_remote << ", ";
+      }
+      f_remote << args[i]->get_type()->get_name() << " " << args[i]->get_name();
+    }
+    f_remote << ")')" << endl;
+  }
+  f_remote << indent_str() << "print('')" << endl << indent_str() << "sys.exit(0)" << endl << endl;
+
+  f_remote << "pp = pprint.PrettyPrinter(indent=2)" << endl
+           << "host = 'localhost'" << endl
+           << "port = 9090" << endl
+           << "uri = ''" << endl
+           << "framed = False" << endl
+           << "ssl = False" << endl
+           << "http = False" << endl
+           << "argi = 1" << endl
+           << endl
+           << "if sys.argv[argi] == '-h':" << endl
+           << indent_str() << "parts = sys.argv[argi + 1].split(':')" << endl
+           << indent_str() << "host = parts[0]" << endl
+           << indent_str() << "if len(parts) > 1:" << endl
+           << indent_str() << indent_str() << "port = int(parts[1])" << endl
+           << indent_str() << "argi += 2" << endl
+           << endl
+           << "if sys.argv[argi] == '-u':" << endl
+           << indent_str() << "url = urlparse(sys.argv[argi + 1])" << endl
+           << indent_str() << "parts = url[1].split(':')" << endl
+           << indent_str() << "host = parts[0]" << endl
+           << indent_str() << "if len(parts) > 1:" << endl
+           << indent_str() << indent_str() << "port = int(parts[1])" << endl
+           << indent_str() << "else:" << endl
+           << indent_str() << indent_str() << "port = 80" << endl
+           << indent_str() << "uri = url[2]" << endl
+           << indent_str() << "if url[4]:" << endl
+           << indent_str() << indent_str() << "uri += '?%s' % url[4]" << endl
+           << indent_str() << "http = True" << endl
+           << indent_str() << "argi += 2" << endl
+           << endl
+           << "if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':" << endl
+           << indent_str() << "framed = True" << endl
+           << indent_str() << "argi += 1" << endl
+           << endl
+           << "if sys.argv[argi] == '-s' or sys.argv[argi] == '-ssl':" << endl
+           << indent_str() << "ssl = True" << endl
+           << indent_str() << "argi += 1" << endl
+           << endl
+           << "cmd = sys.argv[argi]" << endl
+           << "args = sys.argv[argi + 1:]" << endl
+           << endl
+           << "if http:" << endl
+           << indent_str() << "transport = THttpClient.THttpClient(host, port, uri)" << endl
+           << "else:" << endl
+           << indent_str() << "socket = TSSLSocket.TSSLSocket(host, port, validate=False) if ssl else "
+              "TSocket.TSocket(host, port)"
+           << endl
+           << indent_str() << "if framed:" << endl
+           << indent_str() << indent_str() << "transport = TTransport.TFramedTransport(socket)" << endl
+           << indent_str() << "else:" << endl
+           << indent_str() << indent_str() << "transport = TTransport.TBufferedTransport(socket)" << endl
+           << "protocol = TBinaryProtocol(transport)" << endl
+           << "client = " << service_name_ << ".Client(protocol)" << endl
+           << "transport.open()" << endl
+           << endl;
+
+  // Generate the dispatch methods
+  bool first = true;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_remote << "el";
+    }
+
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const std::vector<t_field*>& args = arg_struct->get_members();
+    vector<t_field*>::const_iterator a_iter;
+    std::vector<t_field*>::size_type num_args = args.size();
+
+    f_remote << "if cmd == '" << (*f_iter)->get_name() << "':" << endl;
+    indent_up();
+    f_remote << indent() << "if len(args) != " << num_args << ":" << endl
+             << indent() << indent_str() << "print('" << (*f_iter)->get_name() << " requires " << num_args
+             << " args')" << endl
+             << indent() << indent_str() << "sys.exit(1)" << endl
+             << indent() << "pp.pprint(client." << (*f_iter)->get_name() << "(";
+    indent_down();
+    bool first_arg = true;
+    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
+      if (first_arg)
+        first_arg = false;
+      else
+        f_remote << " ";
+      if (args[i]->get_type()->is_string()) {
+        f_remote << "args[" << i << "],";
+      } else {
+        f_remote << "eval(args[" << i << "]),";
+      }
+    }
+    f_remote << "))" << endl;
+
+    f_remote << endl;
+  }
+
+  if (functions.size() > 0) {
+    f_remote << "else:" << endl;
+    f_remote << indent_str() << "print('Unrecognized method %s' % cmd)" << endl;
+    f_remote << indent_str() << "sys.exit(1)" << endl;
+    f_remote << endl;
+  }
+
+  f_remote << "transport.close()" << endl;
+
+  // Close service file
+  f_remote.close();
+
+#ifndef _MSC_VER
+
+  // Make file executable, love that bitwise OR action
+  chmod(f_remote_name.c_str(),
+        S_IRUSR | S_IWUSR | S_IXUSR
+#ifndef _WIN32
+        | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
+#endif
+        );
+
+#endif // _MSC_VER
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_py_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = extends + ".Processor, ";
+  }
+
+  f_service_ << endl << endl;
+
+  // Generate the header portion
+  if (gen_twisted_) {
+    f_service_ << "class Processor(" << extends_processor << "TProcessor):" << endl
+               << indent_str() << "implements(Iface)" << endl << endl;
+  } else {
+    f_service_ << "class Processor(" << extends_processor << "Iface, TProcessor):" << endl;
+  }
+
+  indent_up();
+
+  indent(f_service_) << "def __init__(self, handler):" << endl;
+  indent_up();
+  if (extends.empty()) {
+    if (gen_twisted_) {
+      f_service_ << indent() << "self._handler = Iface(handler)" << endl;
+    } else {
+      f_service_ << indent() << "self._handler = handler" << endl;
+    }
+
+    f_service_ << indent() << "self._processMap = {}" << endl;
+  } else {
+    if (gen_twisted_) {
+      f_service_ << indent() << extends << ".Processor.__init__(self, Iface(handler))" << endl;
+    } else {
+      f_service_ << indent() << extends << ".Processor.__init__(self, handler)" << endl;
+    }
+  }
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "self._processMap[\"" << (*f_iter)->get_name()
+               << "\"] = Processor.process_" << (*f_iter)->get_name() << endl;
+  }
+  indent_down();
+  f_service_ << endl;
+
+  // Generate the server implementation
+  f_service_ << indent() << "def process(self, iprot, oprot):" << endl;
+  indent_up();
+
+  f_service_ << indent() << "(name, type, seqid) = iprot.readMessageBegin()" << endl;
+
+  // TODO(mcslee): validate message
+
+  // HOT: dictionary function lookup
+  f_service_ << indent() << "if name not in self._processMap:" << endl;
+  indent_up();
+  f_service_ << indent() << "iprot.skip(TType.STRUCT)" << endl
+             << indent() << "iprot.readMessageEnd()" << endl
+             << indent()
+             << "x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown "
+                "function %s' % (name))"
+             << endl
+             << indent() << "oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)" << endl
+             << indent() << "x.write(oprot)" << endl
+             << indent() << "oprot.writeMessageEnd()" << endl
+             << indent() << "oprot.trans.flush()" << endl;
+
+  if (gen_twisted_) {
+    f_service_ << indent() << "return defer.succeed(None)" << endl;
+  } else {
+    f_service_ << indent() << "return" << endl;
+  }
+  indent_down();
+
+  f_service_ << indent() << "else:" << endl;
+
+  if (gen_twisted_ || gen_tornado_) {
+    f_service_ << indent() << indent_str()
+               << "return self._processMap[name](self, seqid, iprot, oprot)" << endl;
+  } else {
+    f_service_ << indent() << indent_str() << "self._processMap[name](self, seqid, iprot, oprot)"
+               << endl;
+
+    // Read end of args field, the T_STOP, and the struct close
+    f_service_ << indent() << "return True" << endl;
+  }
+
+  indent_down();
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << endl;
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_py_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open function
+  if (gen_tornado_) {
+    f_service_ << indent() << "@gen.coroutine" << endl << indent() << "def process_"
+               << tfunction->get_name() << "(self, seqid, iprot, oprot):" << endl;
+  } else {
+    f_service_ << indent() << "def process_" << tfunction->get_name()
+               << "(self, seqid, iprot, oprot):" << endl;
+  }
+
+  indent_up();
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << "args = " << argsname << "()" << endl << indent() << "args.read(iprot)"
+             << endl << indent() << "iprot.readMessageEnd()" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "result = " << resultname << "()" << endl;
+  }
+
+  if (gen_twisted_) {
+    // TODO: Propagate arbitrary exception raised by handler to client as does plain "py"
+
+    // Generate the function call
+    t_struct* arg_struct = tfunction->get_arglist();
+    const std::vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    f_service_ << indent() << "d = defer.maybeDeferred(self._handler." << tfunction->get_name()
+               << ", ";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+    f_service_ << ")" << endl;
+
+    // Shortcut out here for oneway functions
+    if (tfunction->is_oneway()) {
+      f_service_ << indent() << "return d" << endl;
+      indent_down();
+      f_service_ << endl;
+      return;
+    }
+
+    f_service_ << indent() << "d.addCallback(self.write_results_success_" << tfunction->get_name()
+               << ", result, seqid, oprot)" << endl;
+
+    if (xceptions.size() > 0) {
+      f_service_ << indent() << "d.addErrback(self.write_results_exception_"
+                 << tfunction->get_name() << ", result, seqid, oprot)" << endl;
+    }
+
+    f_service_ << indent() << "return d" << endl;
+
+    indent_down();
+    f_service_ << endl;
+
+    indent(f_service_) << "def write_results_success_" << tfunction->get_name()
+                       << "(self, success, result, seqid, oprot):" << endl;
+    indent_up();
+    f_service_ << indent() << "result.success = success" << endl << indent()
+               << "oprot.writeMessageBegin(\"" << tfunction->get_name()
+               << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)"
+               << endl << indent() << "oprot.writeMessageEnd()" << endl << indent()
+               << "oprot.trans.flush()" << endl;
+    indent_down();
+
+    // Try block for a function with exceptions
+    if (!tfunction->is_oneway() && xceptions.size() > 0) {
+      f_service_ << endl;
+      indent(f_service_) << "def write_results_exception_" << tfunction->get_name()
+                         << "(self, error, result, seqid, oprot):" << endl;
+      indent_up();
+      f_service_ << indent() << "try:" << endl;
+
+      // Kinda absurd
+      f_service_ << indent() << indent_str() << "error.raiseException()" << endl;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ <<
+          indent() << "except " << type_name((*x_iter)->get_type()) << " as " << (*x_iter)->get_name() << ":" << endl;
+        if (!tfunction->is_oneway()) {
+          indent_up();
+          f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                     << (*x_iter)->get_name() << endl;
+          indent_down();
+        } else {
+          f_service_ << indent() << "pass" << endl;
+        }
+      }
+      f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
+                 << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)"
+                 << endl << indent() << "oprot.writeMessageEnd()" << endl << indent()
+                 << "oprot.trans.flush()" << endl;
+      indent_down();
+    }
+
+  } else if (gen_tornado_) {
+    // TODO: Propagate arbitrary exception raised by handler to client as does plain "py"
+
+    // Generate the function call
+    t_struct* arg_struct = tfunction->get_arglist();
+    const std::vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    if (xceptions.size() > 0) {
+      f_service_ << indent() << "try:" << endl;
+      indent_up();
+    }
+    f_service_ << indent();
+    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+      f_service_ << "result.success = ";
+    }
+    f_service_ << "yield gen.maybe_future(self._handler." << tfunction->get_name() << "(";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+    f_service_ << "))" << endl;
+
+    if (!tfunction->is_oneway() && xceptions.size() > 0) {
+      indent_down();
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as "
+                   << (*x_iter)->get_name() << ":" << endl;
+        if (!tfunction->is_oneway()) {
+          indent_up();
+          f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                     << (*x_iter)->get_name() << endl;
+          indent_down();
+        } else {
+          f_service_ << indent() << "pass" << endl;
+        }
+      }
+    }
+
+    if (!tfunction->is_oneway()) {
+      f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
+                 << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)"
+                 << endl << indent() << "oprot.writeMessageEnd()" << endl << indent()
+                 << "oprot.trans.flush()" << endl;
+    }
+
+    // Close function
+    indent_down();
+
+  } else { // py
+    // Try block for a function with exceptions
+    // It also catches arbitrary exceptions raised by handler method to propagate them to the client
+    f_service_ << indent() << "try:" << endl;
+    indent_up();
+
+    // Generate the function call
+    t_struct* arg_struct = tfunction->get_arglist();
+    const std::vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    f_service_ << indent();
+    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+      f_service_ << "result.success = ";
+    }
+    f_service_ << "self._handler." << tfunction->get_name() << "(";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+    f_service_ << ")" << endl;
+    if (!tfunction->is_oneway()) {
+      f_service_  << indent() << "msg_type = TMessageType.REPLY" << endl;
+    }
+
+    indent_down();
+    f_service_ << indent()
+               << "except (TTransport.TTransportException, KeyboardInterrupt, SystemExit):" << endl
+               << indent() << indent_str() << "raise" << endl;
+
+    if (!tfunction->is_oneway()) {
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as "
+                   << (*x_iter)->get_name() << ":" << endl;
+        if (!tfunction->is_oneway()) {
+          indent_up();
+          f_service_ << indent() << "msg_type = TMessageType.REPLY" << endl;
+          f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                     << (*x_iter)->get_name() << endl;
+          indent_down();
+        } else {
+          f_service_ << indent() << "pass" << endl;
+        }
+      }
+
+      f_service_ << indent() << "except Exception as ex:" << endl
+                 << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl
+                 << indent() << indent_str() << "logging.exception(ex)" << endl
+                 << indent()
+                 << indent_str() << "result = TApplicationException(TApplicationException.INTERNAL_ERROR, "
+                    "'Internal error')" << endl
+                 << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
+                 << "\", msg_type, seqid)" << endl
+                 << indent() << "result.write(oprot)" << endl
+                 << indent() << "oprot.writeMessageEnd()" << endl
+                 << indent() << "oprot.trans.flush()" << endl;
+    } else {
+      f_service_ << indent() << "except:" << endl
+                 << indent() << indent_str() << "pass" << endl;
+    }
+
+    // Close function
+    indent_down();
+  }
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_py_generator::generate_deserialize_field(ofstream& out,
+                                                t_field* tfield,
+                                                string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << name << " = iprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "readBinary()";
+        } else if(!gen_utf8strings_) {
+          out << "readString()";
+        } else {
+          out << "readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool()";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte()";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16()";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32()";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64()";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble()";
+        break;
+      default:
+        throw "compiler error: no Python name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32()";
+    }
+    out << endl;
+
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, calling read()
+ */
+void t_py_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  if (is_immutable(tstruct)) {
+    out << indent() << prefix << " = " << type_name(tstruct) << ".read(iprot)" << endl;
+  } else {
+    out << indent() << prefix << " = " << type_name(tstruct) << "()" << endl
+        << indent() << prefix << ".read(iprot)" << endl;
+  }
+}
+
+/**
+ * Serialize a container by writing out the header followed by
+ * data and then a footer.
+ */
+void t_py_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_i8, ktype);
+  t_field fvtype(g_type_i8, vtype);
+  t_field fetype(g_type_i8, etype);
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    out << indent() << prefix << " = {}" << endl << indent() << "(" << ktype << ", " << vtype
+        << ", " << size << ") = iprot.readMapBegin()" << endl;
+  } else if (ttype->is_set()) {
+    out << indent() << prefix << " = set()" << endl << indent() << "(" << etype << ", " << size
+        << ") = iprot.readSetBegin()" << endl;
+  } else if (ttype->is_list()) {
+    out << indent() << prefix << " = []" << endl << indent() << "(" << etype << ", " << size
+        << ") = iprot.readListBegin()" << endl;
+  }
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) <<
+    "for " << i << " in range(" << size << "):" << endl;
+
+  indent_up();
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  indent_down();
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "iprot.readMapEnd()" << endl;
+    if (is_immutable(ttype)) {
+      indent(out) << prefix << " = TFrozenDict(" << prefix << ")" << endl;
+    }
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot.readSetEnd()" << endl;
+    if (is_immutable(ttype)) {
+      indent(out) << prefix << " = frozenset(" << prefix << ")" << endl;
+    }
+  } else if (ttype->is_list()) {
+    if (is_immutable(ttype)) {
+      indent(out) << prefix << " = tuple(" << prefix << ")" << endl;
+    }
+    indent(out) << "iprot.readListEnd()" << endl;
+  }
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_py_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << "[" << key << "] = " << val << endl;
+}
+
+/**
+ * Write a set element
+ */
+void t_py_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ")" << endl;
+}
+
+/**
+ * Write a list element
+ */
+void t_py_generator::generate_deserialize_list_element(ofstream& out,
+                                                       t_list* tlist,
+                                                       string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".append(" << elem << ")" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_py_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + tfield->get_name());
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = prefix + tfield->get_name();
+
+    indent(out) << "oprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "writeBinary(" << name << ")";
+        } else if (!gen_utf8strings_) {
+          out << "writeString(" << name << ")";
+        } else {
+          out << "writeString(" << name << ".encode('utf-8') if sys.version_info[0] == 2 else " << name << ")";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ")";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ")";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ")";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ")";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ")";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ")";
+        break;
+      default:
+        throw "compiler error: no Python name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ")";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_py_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << prefix << ".write(oprot)" << endl;
+}
+
+void t_py_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  if (ttype->is_map()) {
+    indent(out) << "oprot.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
+                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
+                << "len(" << prefix << "))" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
+                << "len(" << prefix << "))" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
+                << ", "
+                << "len(" << prefix << "))" << endl;
+  }
+
+  if (ttype->is_map()) {
+    string kiter = tmp("kiter");
+    string viter = tmp("viter");
+    indent(out) << "for " << kiter << ", " << viter << " in " << prefix << ".items():" << endl;
+    indent_up();
+    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+    indent_down();
+  } else if (ttype->is_set()) {
+    string iter = tmp("iter");
+    indent(out) << "for " << iter << " in " << prefix << ":" << endl;
+    indent_up();
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    indent_down();
+  } else if (ttype->is_list()) {
+    string iter = tmp("iter");
+    indent(out) << "for " << iter << " in " << prefix << ":" << endl;
+    indent_up();
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    indent_down();
+  }
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.writeMapEnd()" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetEnd()" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListEnd()" << endl;
+  }
+}
+
+/**
+ * Serializes the members of a map.
+ *
+ */
+void t_py_generator::generate_serialize_map_element(ofstream& out,
+                                                    t_map* tmap,
+                                                    string kiter,
+                                                    string viter) {
+  t_field kfield(tmap->get_key_type(), kiter);
+  generate_serialize_field(out, &kfield, "");
+
+  t_field vfield(tmap->get_val_type(), viter);
+  generate_serialize_field(out, &vfield, "");
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_py_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_py_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Generates the docstring for a given struct.
+ */
+void t_py_generator::generate_python_docstring(ofstream& out, t_struct* tstruct) {
+  generate_python_docstring(out, tstruct, tstruct, "Attributes");
+}
+
+/**
+ * Generates the docstring for a given function.
+ */
+void t_py_generator::generate_python_docstring(ofstream& out, t_function* tfunction) {
+  generate_python_docstring(out, tfunction, tfunction->get_arglist(), "Parameters");
+}
+
+/**
+ * Generates the docstring for a struct or function.
+ */
+void t_py_generator::generate_python_docstring(ofstream& out,
+                                               t_doc* tdoc,
+                                               t_struct* tstruct,
+                                               const char* subheader) {
+  bool has_doc = false;
+  stringstream ss;
+  if (tdoc->has_doc()) {
+    has_doc = true;
+    ss << tdoc->get_doc();
+  }
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  if (fields.size() > 0) {
+    if (has_doc) {
+      ss << endl;
+    }
+    has_doc = true;
+    ss << subheader << ":\n";
+    vector<t_field*>::const_iterator p_iter;
+    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
+      t_field* p = *p_iter;
+      ss << " - " << p->get_name();
+      if (p->has_doc()) {
+        ss << ": " << p->get_doc();
+      } else {
+        ss << endl;
+      }
+    }
+  }
+
+  if (has_doc) {
+    generate_docstring_comment(out, "\"\"\"\n", "", ss.str(), "\"\"\"\n");
+  }
+}
+
+/**
+ * Generates the docstring for a generic object.
+ */
+void t_py_generator::generate_python_docstring(ofstream& out, t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    generate_docstring_comment(out, "\"\"\"\n", "", tdoc->get_doc(), "\"\"\"\n");
+  }
+}
+
+/**
+ * Declares an argument, which may include initialization as necessary.
+ *
+ * @param tfield The field
+ */
+string t_py_generator::declare_argument(t_field* tfield) {
+  std::ostringstream result;
+  result << tfield->get_name() << "=";
+  if (tfield->get_value() != NULL) {
+    result << "thrift_spec[" << tfield->get_key() << "][4]";
+  } else {
+    result << "None";
+  }
+  return result.str();
+}
+
+/**
+ * Renders a field default value, returns None otherwise.
+ *
+ * @param tfield The field
+ */
+string t_py_generator::render_field_default_value(t_field* tfield) {
+  t_type* type = get_true_type(tfield->get_type());
+  if (tfield->get_value() != NULL) {
+    return render_const_value(type, tfield->get_value());
+  } else {
+    return "None";
+  }
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_py_generator::function_signature(t_function* tfunction, bool interface) {
+  vector<string> pre;
+  vector<string> post;
+  string signature = tfunction->get_name() + "(";
+
+  if (!(gen_twisted_ && interface)) {
+    pre.push_back("self");
+  }
+
+  signature += argument_list(tfunction->get_arglist(), &pre, &post) + ")";
+  return signature;


<TRUNCATED>

[23/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_as3_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_as3_generator.cc b/compiler/cpp/src/thrift/generate/t_as3_generator.cc
new file mode 100644
index 0000000..5ae3f91
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_as3_generator.cc
@@ -0,0 +1,2594 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <sstream>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <stdexcept>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * AS3 code generator.
+ *
+ */
+class t_as3_generator : public t_oop_generator {
+public:
+  t_as3_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    bindable_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("bindable") == 0) {
+        bindable_ = true;
+      } else {
+        throw "unknown option as3:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-as3";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ofstream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false);
+  std::string render_const_value(ofstream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_as3_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_as3_struct_definition(std::ofstream& out,
+                                      t_struct* tstruct,
+                                      bool is_xception = false,
+                                      bool in_class = false,
+                                      bool is_result = false);
+  // removed -- equality,compare_to
+  void generate_as3_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_as3_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_as3_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_as3_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_as3_struct_tostring(std::ofstream& out, t_struct* tstruct, bool bindable);
+  void generate_as3_meta_data_map(std::ofstream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  std::string get_as3_type_string(t_type* type);
+  void generate_reflection_setters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_reflection_getters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
+  void generate_as3_bean_boilerplate(std::ofstream& out, t_struct* tstruct, bool bindable);
+
+  void generate_function_helpers(t_function* tfunction);
+  std::string get_cap_name(std::string name);
+  std::string generate_isset_check(t_field* field);
+  std::string generate_isset_check(std::string field);
+  void generate_isset_set(ofstream& out, t_field* field);
+  // removed std::string isset_field_id(t_field* field);
+
+  void generate_service_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_as3_doc(std::ofstream& out, t_doc* tdoc);
+
+  void generate_as3_doc(std::ofstream& out, t_function* tdoc);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string as3_package();
+  std::string as3_type_imports();
+  std::string as3_thrift_imports();
+  std::string as3_thrift_gen_imports(t_struct* tstruct, string& imports);
+  std::string as3_thrift_gen_imports(t_service* tservice);
+  std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false);
+  std::string base_type_name(t_base_type* tbase, bool in_container = false);
+  std::string declare_field(t_field* tfield, bool init = false);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string get_enum_class_name(t_type* type);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+  std::string constant_name(std::string name);
+
+private:
+  /**
+   * File streams
+   */
+
+  std::string package_name_;
+  std::ofstream f_service_;
+  std::string package_dir_;
+
+  bool bindable_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_as3_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  package_name_ = program_->get_namespace("as3");
+
+  string dir = package_name_;
+  string subdir = get_out_dir();
+  string::size_type loc;
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  package_dir_ = subdir;
+}
+
+/**
+ * Packages the generated file
+ *
+ * @return String of the package, i.e. "package org.apache.thriftdemo;"
+ */
+string t_as3_generator::as3_package() {
+  if (!package_name_.empty()) {
+    return string("package ") + package_name_ + " ";
+  }
+  return "package ";
+}
+
+/**
+ * Prints standard as3 imports
+ *
+ * @return List of imports for As3 types that are used in here
+ */
+string t_as3_generator::as3_type_imports() {
+  return string() + "import org.apache.thrift.Set;\n" + "import flash.utils.ByteArray;\n"
+         + "import flash.utils.Dictionary;\n\n";
+}
+
+/**
+ * Prints standard as3 imports
+ *
+ * @return List of imports necessary for thrift
+ */
+string t_as3_generator::as3_thrift_imports() {
+  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
+         + "import org.apache.thrift.protocol.*;\n\n";
+}
+
+/**
+ * Prints imports needed for a given type
+ *
+ * @return List of imports necessary for a given t_struct
+ */
+string t_as3_generator::as3_thrift_gen_imports(t_struct* tstruct, string& imports) {
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // For each type check if it is from a differnet namespace
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_program* program = (*m_iter)->get_type()->get_program();
+    if (program != NULL && program != program_) {
+      string package = program->get_namespace("as3");
+      if (!package.empty()) {
+        if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) {
+          imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n");
+        }
+      }
+    }
+  }
+  return imports;
+}
+
+/**
+ * Prints imports needed for a given type
+ *
+ * @return List of imports necessary for a given t_service
+ */
+string t_as3_generator::as3_thrift_gen_imports(t_service* tservice) {
+  string imports;
+  const vector<t_function*>& functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+
+  // For each type check if it is from a differnet namespace
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_program* program = (*f_iter)->get_returntype()->get_program();
+    if (program != NULL && program != program_) {
+      string package = program->get_namespace("as3");
+      if (!package.empty()) {
+        if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) {
+          imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name()
+                         + ";\n");
+        }
+      }
+    }
+
+    as3_thrift_gen_imports((*f_iter)->get_arglist(), imports);
+    as3_thrift_gen_imports((*f_iter)->get_xceptions(), imports);
+  }
+
+  return imports;
+}
+
+/**
+ * Nothing in As3
+ */
+void t_as3_generator::close_generator() {
+}
+
+/**
+ * Generates a typedef. This is not done in As3, since it does
+ * not support arbitrary name replacements, and it'd be a wacky waste
+ * of overhead to make wrapper classes.
+ *
+ * @param ttypedef The type definition
+ */
+void t_as3_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Enums are a class with a set of static constants.
+ *
+ * @param tenum The enumeration
+ */
+void t_as3_generator::generate_enum(t_enum* tenum) {
+  // Make output file
+  string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".as";
+  ofstream f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  // Comment and package it
+  f_enum << autogen_comment() << as3_package() << endl;
+
+  scope_up(f_enum);
+  // Add as3 imports
+  f_enum << string() + "import org.apache.thrift.Set;" << endl << "import flash.utils.Dictionary;"
+         << endl;
+
+  indent(f_enum) << "public class " << tenum->get_name() << " ";
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "public static const " << (*c_iter)->get_name() << ":int = " << value << ";"
+                   << endl;
+  }
+
+  // Create a static Set with all valid values for this enum
+  f_enum << endl;
+
+  indent(f_enum) << "public static const VALID_VALUES:Set = new Set(";
+  indent_up();
+  bool firstValue = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    // populate set
+    f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name();
+    firstValue = false;
+  }
+  indent_down();
+  f_enum << ");" << endl;
+
+  indent(f_enum) << "public static const VALUES_TO_NAMES:Dictionary = new Dictionary();" << endl;
+
+  scope_up(f_enum);
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    indent(f_enum) << "VALUES_TO_NAMES[" << (*c_iter)->get_name() << "] = \""
+                   << (*c_iter)->get_name() << "\";" << endl;
+  }
+  f_enum << endl;
+
+  scope_down(f_enum);
+
+  scope_down(f_enum); // end class
+
+  scope_down(f_enum); // end package
+
+  f_enum.close();
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_as3_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.as";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  // Print header
+  f_consts << autogen_comment() << as3_package();
+
+  scope_up(f_consts);
+  f_consts << endl;
+
+  f_consts << as3_type_imports();
+
+  indent(f_consts) << "public class " << program_name_ << "Constants {" << endl << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value(),
+                      false);
+  }
+  indent_down();
+  indent(f_consts) << "}" << endl;
+  scope_down(f_consts);
+  f_consts.close();
+}
+
+void t_as3_generator::print_const_value(std::ofstream& out,
+                                        string name,
+                                        t_type* type,
+                                        t_const_value* value,
+                                        bool in_static,
+                                        bool defval) {
+  type = get_true_type(type);
+
+  indent(out);
+  if (!defval) {
+    out << (in_static ? "var " : "public static const ");
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = " << value->get_integer() << ";" << endl << endl;
+  } else if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
+        << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function():void {" << endl;
+      indent_up();
+    }
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << ".";
+      out << v_iter->first->get_string() << " = " << val << ";" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function():void {" << endl;
+      indent_up();
+    }
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << "[" << key << "] = " << val << ";" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function():void {" << endl;
+      indent_up();
+    }
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << "." << (type->is_list() ? "push" : "add") << "(" << val << ");"
+                  << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_as3_generator::render_const_value(ofstream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value) {
+  (void)name;
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+      render << "(byte)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I16:
+      render << "(short)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "L";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << "(double)" << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with data members, read(), write(), and an inner Isset class.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_struct(t_struct* tstruct) {
+  generate_as3_struct(tstruct, false);
+}
+
+/**
+ * Exceptions are structs, but they inherit from Exception
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_xception(t_struct* txception) {
+  generate_as3_struct(txception, true);
+}
+
+/**
+ * As3 struct definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct(t_struct* tstruct, bool is_exception) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".as";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << as3_package();
+
+  scope_up(f_struct);
+  f_struct << endl;
+
+  string imports;
+
+  f_struct << as3_type_imports() << as3_thrift_imports() << as3_thrift_gen_imports(tstruct, imports)
+           << endl;
+
+  if (bindable_ && !is_exception) {
+    f_struct << "import flash.events.Event;" << endl << "import flash.events.EventDispatcher;"
+             << endl << "import mx.events.PropertyChangeEvent;" << endl;
+  }
+
+  generate_as3_struct_definition(f_struct, tstruct, is_exception);
+
+  scope_down(f_struct); // end of package
+  f_struct.close();
+}
+
+/**
+ * As3 struct definition. This has various parameters, as it could be
+ * generated standalone or inside another class as a helper. If it
+ * is a helper than it is a static class.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param in_class     If inside a class, needs to be static class
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_as3_generator::generate_as3_struct_definition(ofstream& out,
+                                                     t_struct* tstruct,
+                                                     bool is_exception,
+                                                     bool in_class,
+                                                     bool is_result) {
+  generate_as3_doc(out, tstruct);
+
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+  bool bindable = !is_exception && !in_class && bindable_;
+
+  indent(out) << (in_class ? "" : "public ") << (is_final ? "final " : "") << "class "
+              << tstruct->get_name() << " ";
+
+  if (is_exception) {
+    out << "extends Error ";
+  } else if (bindable) {
+    out << "extends EventDispatcher ";
+  }
+  out << "implements TBase ";
+
+  scope_up(out);
+
+  indent(out) << "private static const STRUCT_DESC:TStruct = new TStruct(\"" << tstruct->get_name()
+              << "\");" << endl;
+
+  // Members are public for -as3, private for -as3bean
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "private static const " << constant_name((*m_iter)->get_name())
+                << "_FIELD_DESC:TField = new TField(\"" << (*m_iter)->get_name() << "\", "
+                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");"
+                << endl;
+  }
+
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_as3_doc(out, *m_iter);
+    indent(out) << "private var _" << (*m_iter)->get_name() + ":" + type_name((*m_iter)->get_type())
+                << ";" << endl;
+
+    indent(out) << "public static const " << upcase_string((*m_iter)->get_name())
+                << ":int = " << (*m_iter)->get_key() << ";" << endl;
+  }
+
+  out << endl;
+
+  // Inner Isset class
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (!type_can_be_null((*m_iter)->get_type())) {
+        indent(out) << "private var __isset_" << (*m_iter)->get_name() << ":Boolean = false;"
+                    << endl;
+      }
+    }
+  }
+
+  out << endl;
+
+  generate_as3_meta_data_map(out, tstruct);
+
+  // Static initializer to populate global class to struct metadata map
+  indent(out) << "{" << endl;
+  indent_up();
+  indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);"
+              << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // Default constructor
+  indent(out) << "public function " << tstruct->get_name() << "() {" << endl;
+  indent_up();
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if ((*m_iter)->get_value() != NULL) {
+      indent(out) << "this._" << (*m_iter)->get_name() << " = "
+                  << (*m_iter)->get_value()->get_integer() << ";" << endl;
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  generate_as3_bean_boilerplate(out, tstruct, bindable);
+  generate_generic_field_getters_setters(out, tstruct);
+  generate_generic_isset_method(out, tstruct);
+
+  generate_as3_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_as3_struct_result_writer(out, tstruct);
+  } else {
+    generate_as3_struct_writer(out, tstruct);
+  }
+  generate_as3_struct_tostring(out, tstruct, bindable);
+  generate_as3_validator(out, tstruct);
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_reader(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public function read(iprot:TProtocol):void {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables and read struct header
+  out << indent() << "var field:TField;" << endl << indent() << "iprot.readStructBegin();" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "field = iprot.readFieldBegin();" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (field.type == TType.STOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (field.id)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "this.");
+    generate_isset_set(out, *f_iter);
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+        << endl << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "default:" << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+      << endl << indent() << "  break;" << endl;
+
+  scope_down(out);
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  out << indent() << "iprot.readStructEnd();" << endl << endl;
+
+  // in non-beans style, check for required fields of primitive type
+  // (which can be checked here but not in the general validate method)
+  out << endl << indent() << "// check for required fields of primitive type, which can't be "
+                             "checked in the validate method" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
+      out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent()
+          << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '"
+          << (*f_iter)->get_name()
+          << "' was not found in serialized data! Struct: \" + toString());" << endl << indent()
+          << "}" << endl;
+    }
+  }
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+// generates as3 method to perform various checks
+// (e.g. check that all required fields are set)
+void t_as3_generator::generate_as3_validator(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public function validate():void {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      if (type_can_be_null((*f_iter)->get_type())) {
+        indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
+        indent(out) << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '"
+                    << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());"
+                    << endl;
+        indent(out) << "}" << endl;
+      } else {
+        indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
+                    << "' because it's a primitive and you chose the non-beans generator." << endl;
+      }
+    }
+  }
+
+  // check that fields of type enum have valid values
+  out << indent() << "// check that fields of type enum have valid values" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    t_type* type = field->get_type();
+    // if field is an enum, check that its value is valid
+    if (type->is_enum()) {
+      indent(out) << "if (" << generate_isset_check(field) << " && !" << get_enum_class_name(type)
+                  << ".VALID_VALUES.contains(" << field->get_name() << ")){" << endl;
+      indent_up();
+      indent(out) << "throw new TProtocolError(TProtocolError.UNKNOWN, \"The field '"
+                  << field->get_name() << "' has been assigned the invalid value \" + "
+                  << field->get_name() << ");" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public function write(oprot:TProtocol):void {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl << endl;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+  // Write the struct map
+  out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
+      << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct,
+ * which is a function result. These fields are only written
+ * if they are set in the Isset array, and only one of them
+ * can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public function write(oprot:TProtocol):void {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
+
+    indent_up();
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+  // Write the struct map
+  out << endl << indent() << "oprot.writeFieldStop();" << endl << indent()
+      << "oprot.writeStructEnd();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+void t_as3_generator::generate_reflection_getters(ostringstream& out,
+                                                  t_type* type,
+                                                  string field_name,
+                                                  string cap_name) {
+  (void)type;
+  (void)cap_name;
+  indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "return this." << field_name << ";" << endl;
+  indent_down();
+}
+
+void t_as3_generator::generate_reflection_setters(ostringstream& out,
+                                                  t_type* type,
+                                                  string field_name,
+                                                  string cap_name) {
+  (void)type;
+  (void)cap_name;
+  indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "if (value == null) {" << endl;
+  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
+  indent(out) << "} else {" << endl;
+  indent(out) << "  this." << field_name << " = value;" << endl;
+  indent(out) << "}" << endl;
+  indent(out) << "break;" << endl << endl;
+
+  indent_down();
+}
+
+void t_as3_generator::generate_generic_field_getters_setters(std::ofstream& out,
+                                                             t_struct* tstruct) {
+
+  std::ostringstream getter_stream;
+  std::ostringstream setter_stream;
+
+  // build up the bodies of both the getter and setter at once
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    indent_up();
+    generate_reflection_setters(setter_stream, type, field_name, cap_name);
+    generate_reflection_getters(getter_stream, type, field_name, cap_name);
+    indent_down();
+  }
+
+  // create the setter
+  indent(out) << "public function setFieldValue(fieldID:int, value:*):void {" << endl;
+  indent_up();
+
+  indent(out) << "switch (fieldID) {" << endl;
+
+  out << setter_stream.str();
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // create the getter
+  indent(out) << "public function getFieldValue(fieldID:int):* {" << endl;
+  indent_up();
+
+  indent(out) << "switch (fieldID) {" << endl;
+
+  out << getter_stream.str();
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+// Creates a generic isSet method that takes the field number as argument
+void t_as3_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // create the isSet method
+  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
+                 "value) and false otherwise" << endl;
+  indent(out) << "public function isSet(fieldID:int):Boolean {" << endl;
+  indent_up();
+  indent(out) << "switch (fieldID) {" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a set of As3 Bean boilerplate functions (setters, getters, etc.)
+ * for the given struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_bean_boilerplate(ofstream& out,
+                                                    t_struct* tstruct,
+                                                    bool bindable) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    // Simple getter
+    generate_as3_doc(out, field);
+    indent(out) << "public function get " << field_name << "():" << type_name(type) << " {" << endl;
+    indent_up();
+    indent(out) << "return this._" << field_name << ";" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Simple setter
+    generate_as3_doc(out, field);
+    std::string propName = tmp("thriftPropertyChange");
+    if (bindable) {
+      indent(out) << "[Bindable(event=\"" << propName << "\")]" << endl;
+    }
+    indent(out) << "public function set " << field_name << "(" << field_name << ":"
+                << type_name(type) << "):void {" << endl;
+    indent_up();
+    indent(out) << "this._" << field_name << " = " << field_name << ";" << endl;
+    generate_isset_set(out, field);
+
+    if (bindable) {
+      // We have to use a custom event rather than the default, because if you use the default,
+      // the setter only gets called if the value has changed - this means calling
+      // foo.setIntValue(0)
+      // will not cause foo.isIntValueSet() to return true since the value of foo._intValue wasn't
+      // changed
+      // so the setter was never called.
+      indent(out) << "dispatchEvent(new Event(\"" << propName << "\"));" << endl;
+
+      // However, if you just use a custom event, then collections won't be able to detect when
+      // elements
+      // in the collections have changed since they listed for PropertyChangeEvents.  So, we
+      // dispatch both.
+      indent(out) << "dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE));"
+                  << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Unsetter
+    indent(out) << "public function unset" << cap_name << "():void {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "this." << field_name << " = null;" << endl;
+    } else {
+      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // isSet method
+    indent(out) << "// Returns true if field " << field_name
+                << " is set (has been assigned a value) and false otherwise" << endl;
+    indent(out) << "public function is" << get_cap_name("set") << cap_name << "():Boolean {"
+                << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "return this." << field_name << " != null;" << endl;
+    } else {
+      indent(out) << "return this.__isset_" << field_name << ";" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a toString() method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_tostring(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   bool bindable) {
+  // If it's bindable, it extends EventDispatcher so toString is an override.
+  out << indent() << "public " << (bindable ? "override " : "") << "function toString():String {"
+      << endl;
+  indent_up();
+
+  out << indent() << "var ret:String = new String(\"" << tstruct->get_name() << "(\");" << endl;
+  out << indent() << "var first:Boolean = true;" << endl << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+
+    t_field* field = (*f_iter);
+
+    if (!first) {
+      indent(out) << "if (!first) ret +=  \", \";" << endl;
+    }
+    indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl;
+    bool can_be_null = type_can_be_null(field->get_type());
+    if (can_be_null) {
+      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
+      indent(out) << "  ret += \"null\";" << endl;
+      indent(out) << "} else {" << endl;
+      indent_up();
+    }
+
+    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
+      indent(out) << "  ret += \"BINARY\";" << endl;
+    } else if (field->get_type()->is_enum()) {
+      indent(out) << "var " << field->get_name()
+                  << "_name:String = " << get_enum_class_name(field->get_type())
+                  << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl;
+      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
+      indent(out) << "  ret += " << field->get_name() << "_name;" << endl;
+      indent(out) << "  ret += \" (\";" << endl;
+      indent(out) << "}" << endl;
+      indent(out) << "ret += this." << field->get_name() << ";" << endl;
+      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
+      indent(out) << "  ret += \")\";" << endl;
+      indent(out) << "}" << endl;
+    } else {
+      indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl;
+    }
+
+    if (can_be_null) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    indent(out) << "first = false;" << endl;
+
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    first = false;
+  }
+  out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a static map with meta data to store information such as fieldID to
+ * fieldName mapping
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_meta_data_map(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Static Map with fieldID -> FieldMetaData mappings
+  indent(out) << "public static const metaDataMap:Dictionary = new Dictionary();" << endl;
+
+  if (fields.size() > 0) {
+    // Populate map
+    scope_up(out);
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = *f_iter;
+      std::string field_name = field->get_name();
+      indent(out) << "metaDataMap[" << upcase_string(field_name) << "] = new FieldMetaData(\""
+                  << field_name << "\", ";
+
+      // Set field requirement type (required, optional, etc.)
+      if (field->get_req() == t_field::T_REQUIRED) {
+        out << "TFieldRequirementType.REQUIRED, ";
+      } else if (field->get_req() == t_field::T_OPTIONAL) {
+        out << "TFieldRequirementType.OPTIONAL, ";
+      } else {
+        out << "TFieldRequirementType.DEFAULT, ";
+      }
+
+      // Create value meta data
+      generate_field_value_meta_data(out, field->get_type());
+      out << ");" << endl;
+    }
+    scope_down(out);
+  }
+}
+
+/**
+ * Returns a string with the as3 representation of the given thrift type
+ * (e.g. for the type struct it returns "TType.STRUCT")
+ */
+std::string t_as3_generator::get_as3_type_string(t_type* type) {
+  if (type->is_list()) {
+    return "TType.LIST";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_typedef()) {
+    return get_as3_type_string(((t_typedef*)type)->get_type());
+  } else if (type->is_base_type()) {
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_VOID:
+      return "TType.VOID";
+      break;
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+      break;
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+      break;
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+      break;
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+      break;
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+      break;
+    default:
+      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
+                               + "\" passed to t_as3_generator::get_as3_type_string!");
+      break; // This should never happen!
+    }
+  } else {
+    throw std::runtime_error(
+        "Unknown thrift type \"" + type->get_name()
+        + "\" passed to t_as3_generator::get_as3_type_string!"); // This should never happen!
+  }
+}
+
+void t_as3_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+  out << endl;
+  indent_up();
+  indent_up();
+  if (type->is_struct() || type->is_xception()) {
+    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type);
+  } else if (type->is_container()) {
+    if (type->is_list()) {
+      indent(out) << "new ListMetaData(TType.LIST, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else if (type->is_set()) {
+      indent(out) << "new SetMetaData(TType.SET, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else { // map
+      indent(out) << "new MapMetaData(TType.MAP, ";
+      t_type* key_type = ((t_map*)type)->get_key_type();
+      t_type* val_type = ((t_map*)type)->get_val_type();
+      generate_field_value_meta_data(out, key_type);
+      out << ", ";
+      generate_field_value_meta_data(out, val_type);
+    }
+  } else {
+    indent(out) << "new FieldValueMetaData(" << get_as3_type_string(type);
+  }
+  out << ")";
+  indent_down();
+  indent_down();
+}
+
+/**
+ * Generates a thrift service. In C++, this comprises an entirely separate
+ * header and source file. The header file defines the methods and includes
+ * the data types defined in the main header file, and the implementation
+ * file contains implementations of the basic printer and default interfaces.
+ *
+ * @param tservice The service definition
+ */
+void t_as3_generator::generate_service(t_service* tservice) {
+  // Make interface file
+  string f_service_name = package_dir_ + "/" + service_name_ + ".as";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << as3_package();
+
+  scope_up(f_service_);
+
+  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
+             << as3_thrift_gen_imports(tservice);
+
+  if (tservice->get_extends() != NULL) {
+    t_type* parent = tservice->get_extends();
+    string parent_namespace = parent->get_program()->get_namespace("as3");
+    if (!parent_namespace.empty() && parent_namespace != package_name_) {
+      f_service_ << "import " << type_name(parent) << ";" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_interface(tservice);
+
+  scope_down(f_service_);
+  f_service_.close();
+
+  // Now make the implementation/client file
+  f_service_name = package_dir_ + "/" + service_name_ + "Impl.as";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << as3_package();
+
+  scope_up(f_service_);
+
+  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
+             << as3_thrift_gen_imports(tservice);
+
+  if (tservice->get_extends() != NULL) {
+    t_type* parent = tservice->get_extends();
+    string parent_namespace = parent->get_program()->get_namespace("as3");
+    if (!parent_namespace.empty() && parent_namespace != package_name_) {
+      f_service_ << "import " << type_name(parent) << "Impl;" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_client(tservice);
+  scope_down(f_service_);
+
+  f_service_ << as3_type_imports();
+  f_service_ << as3_thrift_imports();
+  f_service_ << as3_thrift_gen_imports(tservice);
+  if (!package_name_.empty()) {
+    f_service_ << "import " << package_name_ << ".*;" << endl;
+  }
+
+  generate_service_helpers(tservice);
+
+  f_service_.close();
+
+  // Now make the processor/server file
+  f_service_name = package_dir_ + "/" + service_name_ + "Processor.as";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << as3_package();
+
+  scope_up(f_service_);
+
+  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
+             << as3_thrift_gen_imports(tservice) << endl;
+
+  generate_service_server(tservice);
+  scope_down(f_service_);
+
+  f_service_ << as3_type_imports();
+  f_service_ << as3_thrift_imports();
+  f_service_ << as3_thrift_gen_imports(tservice) << endl;
+  if (!package_name_.empty()) {
+    f_service_ << "import " << package_name_ << ".*;" << endl;
+  }
+
+  generate_service_helpers(tservice);
+
+  f_service_.close();
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_as3_generator::generate_service_interface(t_service* tservice) {
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends_iface = " extends " + tservice->get_extends()->get_name();
+  }
+
+  generate_as3_doc(f_service_, tservice);
+  f_service_ << indent() << "public interface " << service_name_ << extends_iface << " {" << endl
+             << endl;
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_as3_doc(f_service_, *f_iter);
+    if (!(*f_iter)->is_oneway()) {
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess():void;" << endl;
+      } else {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype())
+                           << "):void;" << endl;
+      }
+    }
+    indent(f_service_) << function_signature(*f_iter) << ";" << endl << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates structs for all the service args and return types
+ *
+ * @param tservice The service
+ */
+void t_as3_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_as3_struct_definition(f_service_, ts, false, true);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_as3_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = tservice->get_extends()->get_name();
+    extends_client = " extends " + extends + "Impl";
+  }
+
+  indent(f_service_) << "public class " << service_name_ << "Impl" << extends_client
+                     << " implements " << service_name_ << " {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public function " << service_name_ << "Impl"
+                     << "(iprot:TProtocol, oprot:TProtocol=null)" << endl;
+  scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ << indent() << "iprot_ = iprot;" << endl;
+    f_service_ << indent() << "if (oprot == null) {" << endl;
+    indent_up();
+    f_service_ << indent() << "oprot_ = iprot;" << endl;
+    indent_down();
+    f_service_ << indent() << "} else {" << endl;
+    indent_up();
+    f_service_ << indent() << "oprot_ = oprot;" << endl;
+    indent_down();
+    f_service_ << indent() << "}";
+  } else {
+    f_service_ << indent() << "super(iprot, oprot);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected var iprot_:TProtocol;" << endl << indent()
+               << "protected var oprot_:TProtocol;" << endl << endl << indent()
+               << "protected var seqid_:int;" << endl << endl;
+
+    indent(f_service_) << "public function getInputProtocol():TProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.iprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    indent(f_service_) << "public function getOutputProtocol():TProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.oprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    if (!(*f_iter)->is_oneway()) {
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess():void;" << endl;
+      } else {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype())
+                           << "):void;" << endl;
+      }
+    }
+    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
+    scope_up(f_service_);
+
+    // Get the struct of function call params
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    string argsname = (*f_iter)->get_name() + "_args";
+    vector<t_field*>::const_iterator fld_iter;
+    const vector<t_field*>& fields = arg_struct->get_members();
+
+    // Serialize the request
+    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
+               << ", seqid_));" << endl << indent() << "var args:" << argsname << " = new "
+               << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
+               << "oprot_.writeMessageEnd();" << endl;
+
+    if ((*f_iter)->is_oneway()) {
+      f_service_ << indent() << "oprot_.getTransport().flush();" << endl;
+    } else {
+      f_service_ << indent() << "oprot_.getTransport().flush(function(error:Error):void {" << endl;
+      indent_up();
+      f_service_ << indent() << "try {" << endl;
+      indent_up();
+      string resultname = (*f_iter)->get_name() + "_result";
+      f_service_ << indent() << "if (error != null) {" << endl << indent()
+                 << "  if (onError != null) onError(error);" << endl << indent() << "  return;"
+                 << endl << indent() << "}" << endl << indent()
+                 << "var msg:TMessage = iprot_.readMessageBegin();" << endl << indent()
+                 << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent()
+                 << "  var x:TApplicationError = TApplicationError.read(iprot_);" << endl
+                 << indent() << "  iprot_.readMessageEnd();" << endl << indent()
+                 << "  if (onError != null) onError(x);" << endl << indent() << "  return;" << endl
+                 << indent() << "}" << endl << indent() << "var result :" << resultname << " = new "
+                 << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl
+                 << indent() << "iprot_.readMessageEnd();" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl
+                   << indent() << "  if (onSuccess != null) onSuccess(result.success);" << endl
+                   << indent() << "  return;" << endl << indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl
+                   << indent() << "  if (onError != null) onError(result." << (*x_iter)->get_name()
+                   << ");" << endl << indent() << "  return;" << endl << indent() << "}" << endl;
+      }
+
+      // If you get here it's an exception, unless a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (onSuccess != null) onSuccess();" << endl << indent()
+                   << "return;" << endl;
+      } else {
+
+        f_service_ << indent() << "if (onError != null) onError(new "
+                                  "TApplicationError(TApplicationError.MISSING_RESULT, \""
+                   << (*f_iter)->get_name() << " failed: unknown result\"));" << endl;
+      }
+      indent_down();
+      f_service_ << indent() << "} catch (e:TError) {" << endl << indent()
+                 << "  if (onError != null) onError(e);" << endl << indent() << "}" << endl;
+
+      indent_down();
+      indent(f_service_) << "});" << endl;
+    }
+    // Close function
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl;
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_as3_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // Extends stuff
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = " extends " + extends + "Processor";
+  }
+
+  // Generate the header portion
+  indent(f_service_) << "public class " << service_name_ << "Processor" << extends_processor
+                     << " implements TProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public function " << service_name_ << "Processor(iface:" << service_name_
+                     << ")" << endl;
+  scope_up(f_service_);
+  if (!extends.empty()) {
+    f_service_ << indent() << "super(iface);" << endl;
+  }
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "PROCESS_MAP[\"" << (*f_iter)->get_name()
+               << "\"] = " << (*f_iter)->get_name() << "();" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  f_service_ << indent() << "private var iface_:" << service_name_ << ";" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected const PROCESS_MAP:Dictionary = new Dictionary();" << endl;
+  }
+
+  f_service_ << endl;
+
+  // Generate the server implementation
+  string override = "";
+  if (tservice->get_extends() != NULL) {
+    override = "override ";
+  }
+  indent(f_service_) << override
+                     << "public function process(iprot:TProtocol, oprot:TProtocol):Boolean" << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "var msg:TMessage = iprot.readMessageBegin();" << endl;
+
+  // TODO(mcslee): validate message, was the seqid etc. legit?
+  // AS- If all method is oneway:
+  // do you have an oprot?
+  // do you you need nullcheck?
+  f_service_
+      << indent() << "var fn:Function = PROCESS_MAP[msg.name];" << endl << indent()
+      << "if (fn == null) {" << endl << indent() << "  TProtocolUtil.skip(iprot, TType.STRUCT);"
+      << endl << indent() << "  iprot.readMessageEnd();" << endl << indent()
+      << "  var x:TApplicationError = new TApplicationError(TApplicationError.UNKNOWN_METHOD, "
+         "\"Invalid method name: '\"+msg.name+\"'\");" << endl << indent()
+      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
+      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
+      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
+      << "  return true;" << endl << indent() << "}" << endl << indent()
+      << "fn.call(this,msg.seqid, iprot, oprot);" << endl;
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_as3_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  t_struct result(program_, tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_as3_struct_definition(f_service_, &result, false, true, true);
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_as3_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open class
+  indent(f_service_) << "private function " << tfunction->get_name() << "():Function {" << endl;
+  indent_up();
+
+  // Open function
+  indent(f_service_) << "return function(seqid:int, iprot:TProtocol, oprot:TProtocol):void" << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << "var args:" << argsname << " = new " << argsname << "();" << endl
+             << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();"
+             << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "var result:" << resultname << " = new " << resultname << "();"
+               << endl;
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try {" << endl;
+    indent_up();
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (tfunction->is_oneway()) {
+    f_service_ << "iface_." << tfunction->get_name() << "(";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+    f_service_ << ");" << endl;
+  } else {
+    f_service_ << "// sorry this operation is not supported yet" << endl;
+    f_service_ << indent() << "throw new Error(\"This is not yet supported\");" << endl;
+  }
+
+  // Set isset on success field
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()
+      && !type_can_be_null(tfunction->get_returntype())) {
+    f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet")
+               << "(true);" << endl;
+  }
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}";
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << " catch (" << (*x_iter)->get_name() << ":"
+                 << type_name((*x_iter)->get_type(), false, false) << ") {" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                   << (*x_iter)->get_name() << ";" << endl;
+        indent_down();
+        f_service_ << indent() << "}";
+      } else {
+        f_service_ << "}";
+      }
+    }
+    f_service_ << " catch (th:Error) {" << endl;
+    indent_up();
+    f_service_ << indent() << "trace(\"Internal error processing " << tfunction->get_name()
+               << "\", th);" << endl << indent()
+               << "var x:TApplicationError = new "
+                  "TApplicationError(TApplicationError.INTERNAL_ERROR, \"Internal error processing "
+               << tfunction->get_name() << "\");" << endl << indent()
+               << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.EXCEPTION, seqid));" << endl << indent() << "x.write(oprot);"
+               << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
+               << "oprot.getTransport().flush();" << endl << indent() << "return;" << endl;
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "return;" << endl;
+    scope_down(f_service_);
+
+    // Close class
+    indent_down();
+    f_service_ << indent() << "}" << endl << endl;
+    return;
+  }
+
+  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
+             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
+             << "oprot.getTransport().flush();" << endl;
+
+  // Close function
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Close class
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param prefix The variable name or container for this field
+ */
+void t_as3_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    indent(out) << name << " = iprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "readBinary();";
+        } else {
+          out << "readString();";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool();";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte();";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16();";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32();";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64();";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble();";
+        break;
+      default:
+        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32();";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, invokes read()
+ */
+void t_as3_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent()
+      << prefix << ".read(iprot);" << endl;
+}
+
+/**
+ * Deserializes a container by reading its size and then iterating
+ */
+void t_as3_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  string obj;
+
+  if (ttype->is_map()) {
+    obj = tmp("_map");
+  } else if (ttype->is_set()) {
+    obj = tmp("_set");
+  } else if (ttype->is_list()) {
+    obj = tmp("_list");
+  }
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "var " << obj << ":TMap = iprot.readMapBegin();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "var " << obj << ":TSet = iprot.readSetBegin();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "var " << obj << ":TList = iprot.readListBegin();" << endl;
+  }
+
+  indent(out) << prefix << " = new " << type_name(ttype, false, true)
+              // size the collection correctly
+              << "("
+              << ");" << endl;
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for (var " << i << ":int = 0; " << i << " < " << obj << ".size"
+              << "; "
+              << "++" << i << ")" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "iprot.readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot.readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "iprot.readListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_as3_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey) << endl;
+  indent(out) << declare_field(&fval) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
+}
+
+/**
+ * Deserializes a set element
+ */
+void t_as3_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
+}
+
+/**
+ * Deserializes a list element
+ */
+void t_as3_generator::generate_deserialize_list_element(ofstream& out,
+                                                        t_list* tlist,
+                                                        string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".push(" << elem << ");" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_as3_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + tfield->get_name());
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = prefix + tfield->get_name();
+    indent(out) << "oprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "writeBinary(" << name << ");";
+        } else {
+          out << "writeString(" << name << ");";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ");";
+        break;
+      default:
+        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ");";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_as3_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  out << indent() << prefix << ".write(oprot);" << endl;
+}
+
+/**
+ * Serializes a container by writing its size then the elements.
+ *
+ * @param ttype  The type of container
+ * @param prefix String prefix for fields
+ */
+void t_as3_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    string iter = tmp("_key");
+    string counter = tmp("_sizeCounter");
+    indent(out) << "var " << counter << ":int = 0;" << endl;
+    indent(out) << "for (var " << iter << ":* in " << prefix << ") {" << endl;
+    indent(out) << "  " << counter << +"++;" << endl;
+    indent(out) << "}" << endl;
+
+    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));"
+                << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                << ", " << prefix << ".size));" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListBegin(new TList("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
+                << endl;
+  }
+
+  string iter = tmp("elem");
+  if (ttype->is_map()) {
+    indent(out) << "for (var " << iter << ":* in " << prefix << ")";
+  } else if (ttype->is_set()) {
+    indent(out) << "for each (var " << iter << ":* in " << prefix << ".toArray())";
+  } else if (ttype->is_list()) {
+    indent(out) << "for each (var " << iter << ":* in " << prefix << ")";
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ */
+void t_as3_generator::generate_serialize_map_element(ofstream& out,
+                                                     t_map* tmap,
+                                                     string iter,
+                                                     string map) {
+  t_field kfield(tmap->get_key_type(), iter);
+  generate_serialize_field(out, &kfield, "");
+  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
+  generate_serialize_field(out, &vfield, "");
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_as3_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_as3_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Returns a As3 type name
+ *
+ * @param ttype The type
+ * @param container Is the type going inside a container?
+ * @return As3 type name, i.e. HashMap<Key,Value>
+ */
+string t_as3_generator::type_name(t_type* ttype, bool in_container, bool in_init) {
+  (void)in_init;
+  // In As3 typedefs are just resolved to their real type
+  ttype = get_true_type(ttype);
+  string prefix;
+
+  if (ttype->is_base_type()) {
+    return base_type_name((t_base_type*)ttype, in_container);
+  } else if (ttype->is_enum()) {
+    return "int";
+  } else if (ttype->is_map()) {
+    return "Dictionary";
+  } else if (ttype->is_set()) {
+    return "Set";
+  } else if (ttype->is_list()) {
+    return "Array";
+  }
+
+  // Check for namespacing
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    string package = program->get_namespace("as3");
+    if (!package.empty()) {
+      return package + "." + ttype->get_name();
+    }
+  }
+
+  return ttype->get_name();
+}
+
+/**
+ * Returns the AS3 type that corresponds to the thrift type.
+ *
+ * @param tbase The base type
+ * @param container Is it going in a As3 container?
+ */
+string t_as3_generator::base_type_name(t_base_type* type, bool in_container) {
+  (void)in_container;
+  t_base_type::t_base tbase = type->get_base();
+
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (type->is_binary()) {
+      return "ByteArray";
+    } else {
+      return "String";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "Boolean";
+  case t_base_type::TYPE_I8:
+  case t_base_type::TYPE_I16:
+  case t_base_type::TYPE_I32:
+    return "int";
+  case t_base_type::TYPE_I64:
+    throw "i64 is not yet supported in as3";
+  case t_base_type::TYPE_DOUBLE:
+    return "Number";
+  default:
+    throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
+  }
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ */
+string t_as3_generator::declare_field(t_field* tfield, bool init) {
+  // TODO(mcslee): do we ever need to initialize the field?
+  string result = "var " + tfield->get_name() + ":" + type_name(tfield->get_type());
+  if (init) {
+    t_type* ttype = get_true_type(tfield->get_type());
+    if (ttype->is_base_type() && tfield->get_value() != NULL) {
+      ofstream dummy;
+      result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
+    } else if (ttype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "NO T_VOID CONSTRUCT";
+      case t_base_type::TYPE_STRING:
+        result += " = null";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+        result += " = 0";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = (double)0";
+        break;
+      }
+
+    } else if (ttype->is_enum()) {
+      result += " = 0";
+    } else if (ttype->is_container()) {
+      result += " = new " + type_name(ttype, false, true) + "()";
+    } else {
+      result += " = new " + type_name(ttype, false, true) + "()";
+      ;
+    }
+  }
+  return result + ";";
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_as3_generator::function_signature(t_function* tfunction, string prefix) {
+  std::string arguments = argument_list(tfunction->get_arglist());
+  if (!tfunction->is_oneway()) {
+    if (arguments != "") {
+      arguments += ", ";
+    }
+    arguments += "onError:Function, onSuccess:Function";
+  }
+
+  std::string result = "function " + prefix + tfunction->get_name() + "(" + arguments + "):void";
+  return result;
+}
+
+/**
+ * Renders a comma separated field list, with type names
+ */
+string t_as3_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += (*f_iter)->get_name() + ":" + type_name((*f_iter)->get_type());
+  }
+  return result;
+}
+
+/**
+ * Converts the parse type to a C++ enum string for the given type.
+ */
+string t_as3_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_list()) {
+    return "TType.LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Applies the correct style to a string based on the value of nocamel_style_
+ */
+std::string t_as3_generator::get_cap_name(std::string name) {
+  name[0] = toupper(name[0]);
+  return name;
+}
+
+string t_as3_generator::constant_name(string name) {
+  string constant_name;
+
+  bool is_first = true;
+  bool was_previous_char_upper = false;
+  for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
+    string::value_type character = (*iter);
+
+    bool is_upper = isupper(character);
+
+    if (is_upper && !is_first && !was_previous_char_upper) {
+      constant_name += '_';
+    }
+    constant_name += tou

<TRUNCATED>

[10/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_html_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_html_generator.cc b/compiler/cpp/src/thrift/generate/t_html_generator.cc
new file mode 100644
index 0000000..ec78e10
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_html_generator.cc
@@ -0,0 +1,1088 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <map>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/generate/t_generator.h"
+#include "thrift/generate/t_html_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::pair;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+enum input_type { INPUT_UNKNOWN, INPUT_UTF8, INPUT_PLAIN };
+
+/**
+ * HTML code generator
+ *
+ * mostly copy/pasting/tweaking from mcslee's work.
+ */
+class t_html_generator : public t_generator {
+public:
+  t_html_generator(t_program* program,
+                   const std::map<std::string, std::string>& parsed_options,
+                   const std::string& option_string)
+    : t_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    standalone_ = false;
+    unsafe_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("standalone") == 0) {
+        standalone_ = true;
+      } else if( iter->first.compare("noescape") == 0) {
+        unsafe_ = true;
+      } else {
+        throw "unknown option html:" + iter->first;
+      }
+    }
+
+
+    out_dir_base_ = "gen-html";
+    input_type_ = INPUT_UNKNOWN;
+
+    escape_.clear();
+    escape_['&'] = "&amp;";
+    escape_['<'] = "&lt;";
+    escape_['>'] = "&gt;";
+    escape_['"'] = "&quot;";
+    escape_['\''] = "&apos;";
+
+    init_allowed__markup();
+  }
+
+  void generate_program();
+  void generate_program_toc();
+  void generate_program_toc_row(t_program* tprog);
+  void generate_program_toc_rows(t_program* tprog, std::vector<t_program*>& finished);
+  void generate_index();
+  std::string escape_html(std::string const& str);
+  std::string escape_html_tags(std::string const& str);
+  void generate_css();
+  void generate_css_content(std::ofstream& f_target);
+  void generate_style_tag();
+  std::string make_file_link(std::string name);
+  bool is_utf8_sequence(std::string const& str, size_t firstpos);
+  void detect_input_encoding(std::string const& str, size_t firstpos);
+  void init_allowed__markup();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_service(t_service* tservice);
+  void generate_xception(t_struct* txception);
+
+  void print_doc(t_doc* tdoc);
+  int print_type(t_type* ttype);
+  void print_const_value(t_type* type, t_const_value* tvalue);
+  void print_fn_args_doc(t_function* tfunction);
+
+private:
+  std::ofstream f_out_;
+  std::string current_file_;
+  input_type input_type_;
+  std::map<std::string, int> allowed_markup;
+  bool standalone_;
+  bool unsafe_;
+};
+
+/**
+ * Emits the Table of Contents links at the top of the module's page
+ */
+void t_html_generator::generate_program_toc() {
+  f_out_ << "<table class=\"table-bordered table-striped "
+            "table-condensed\"><thead><th>Module</th><th>Services</th>"
+         << "<th>Data types</th><th>Constants</th></thead>" << endl;
+  generate_program_toc_row(program_);
+  f_out_ << "</table>" << endl;
+}
+
+/**
+ * Recurses through from the provided program and generates a ToC row
+ * for each discovered program exactly once by maintaining the list of
+ * completed rows in 'finished'
+ */
+void t_html_generator::generate_program_toc_rows(t_program* tprog,
+                                                 std::vector<t_program*>& finished) {
+  for (vector<t_program*>::iterator iter = finished.begin(); iter != finished.end(); iter++) {
+    if (tprog->get_path() == (*iter)->get_path()) {
+      return;
+    }
+  }
+  finished.push_back(tprog);
+  generate_program_toc_row(tprog);
+  vector<t_program*> includes = tprog->get_includes();
+  for (vector<t_program*>::iterator iter = includes.begin(); iter != includes.end(); iter++) {
+    generate_program_toc_rows(*iter, finished);
+  }
+}
+
+/**
+ * Emits the Table of Contents links at the top of the module's page
+ */
+void t_html_generator::generate_program_toc_row(t_program* tprog) {
+  string fname = tprog->get_name() + ".html";
+  f_out_ << "<tr>" << endl << "<td>" << tprog->get_name() << "</td><td>";
+  if (!tprog->get_services().empty()) {
+    vector<t_service*> services = tprog->get_services();
+    vector<t_service*>::iterator sv_iter;
+    for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+      string name = get_service_name(*sv_iter);
+      f_out_ << "<a href=\"" << make_file_link(fname) << "#Svc_" << name << "\">" << name
+             << "</a><br/>" << endl;
+      f_out_ << "<ul>" << endl;
+      map<string, string> fn_html;
+      vector<t_function*> functions = (*sv_iter)->get_functions();
+      vector<t_function*>::iterator fn_iter;
+      for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
+        string fn_name = (*fn_iter)->get_name();
+        string html = "<li><a href=\"" + make_file_link(fname) + "#Fn_" + name + "_" + fn_name
+                      + "\">" + fn_name + "</a></li>";
+        fn_html.insert(pair<string, string>(fn_name, html));
+      }
+      for (map<string, string>::iterator html_iter = fn_html.begin(); html_iter != fn_html.end();
+           html_iter++) {
+        f_out_ << html_iter->second << endl;
+      }
+      f_out_ << "</ul>" << endl;
+    }
+  }
+  f_out_ << "</td>" << endl << "<td>";
+  map<string, string> data_types;
+  if (!tprog->get_enums().empty()) {
+    vector<t_enum*> enums = tprog->get_enums();
+    vector<t_enum*>::iterator en_iter;
+    for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
+      string name = (*en_iter)->get_name();
+      // f_out_ << "<a href=\"" << make_file_link(fname) << "#Enum_" << name << "\">" << name
+      // <<  "</a><br/>" << endl;
+      string html = "<a href=\"" + make_file_link(fname) + "#Enum_" + name + "\">" + name + "</a>";
+      data_types.insert(pair<string, string>(name, html));
+    }
+  }
+  if (!tprog->get_typedefs().empty()) {
+    vector<t_typedef*> typedefs = tprog->get_typedefs();
+    vector<t_typedef*>::iterator td_iter;
+    for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
+      string name = (*td_iter)->get_symbolic();
+      // f_out_ << "<a href=\"" << make_file_link(fname) << "#Typedef_" << name << "\">" << name
+      // << "</a><br/>" << endl;
+      string html = "<a href=\"" + make_file_link(fname) + "#Typedef_" + name + "\">" + name
+                    + "</a>";
+      data_types.insert(pair<string, string>(name, html));
+    }
+  }
+  if (!tprog->get_objects().empty()) {
+    vector<t_struct*> objects = tprog->get_objects();
+    vector<t_struct*>::iterator o_iter;
+    for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
+      string name = (*o_iter)->get_name();
+      // f_out_ << "<a href=\"" << make_file_link(fname) << "#Struct_" << name << "\">" << name
+      //<< "</a><br/>" << endl;
+      string html = "<a href=\"" + make_file_link(fname) + "#Struct_" + name + "\">" + name
+                    + "</a>";
+      data_types.insert(pair<string, string>(name, html));
+    }
+  }
+  for (map<string, string>::iterator dt_iter = data_types.begin(); dt_iter != data_types.end();
+       dt_iter++) {
+    f_out_ << dt_iter->second << "<br/>" << endl;
+  }
+  f_out_ << "</td>" << endl << "<td>";
+  if (!tprog->get_consts().empty()) {
+    map<string, string> const_html;
+    vector<t_const*> consts = tprog->get_consts();
+    vector<t_const*>::iterator con_iter;
+    for (con_iter = consts.begin(); con_iter != consts.end(); ++con_iter) {
+      string name = (*con_iter)->get_name();
+      string html = "<code><a href=\"" + make_file_link(fname) + "#Const_" + name + "\">" + name
+                    + "</a></code>";
+      const_html.insert(pair<string, string>(name, html));
+    }
+    for (map<string, string>::iterator con_iter = const_html.begin(); con_iter != const_html.end();
+         con_iter++) {
+      f_out_ << con_iter->second << "<br/>" << endl;
+    }
+  }
+  f_out_ << "</code></td>" << endl << "</tr>";
+}
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * stream.
+ */
+void t_html_generator::generate_program() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  current_file_ = program_->get_name() + ".html";
+  string fname = get_out_dir() + current_file_;
+  f_out_.open(fname.c_str());
+  f_out_ << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" << endl;
+  f_out_ << "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" << endl;
+  f_out_ << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl;
+  f_out_ << "<head>" << endl;
+  f_out_ << "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />" << endl;
+  generate_style_tag();
+  f_out_ << "<title>Thrift module: " << program_->get_name() << "</title></head><body>" << endl
+         << "<div class=\"container-fluid\">" << endl
+         << "<h1>Thrift module: " << program_->get_name() << "</h1>" << endl;
+
+  print_doc(program_);
+
+  generate_program_toc();
+
+  if (!program_->get_consts().empty()) {
+    f_out_ << "<hr/><h2 id=\"Constants\">Constants</h2>" << endl;
+    vector<t_const*> consts = program_->get_consts();
+    f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
+    f_out_ << "<thead><th>Constant</th><th>Type</th><th>Value</th></thead>" << endl;
+    generate_consts(consts);
+    f_out_ << "</table>";
+  }
+
+  if (!program_->get_enums().empty()) {
+    f_out_ << "<hr/><h2 id=\"Enumerations\">Enumerations</h2>" << endl;
+    // Generate enums
+    vector<t_enum*> enums = program_->get_enums();
+    vector<t_enum*>::iterator en_iter;
+    for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
+      generate_enum(*en_iter);
+    }
+  }
+
+  if (!program_->get_typedefs().empty()) {
+    f_out_ << "<hr/><h2 id=\"Typedefs\">Type declarations</h2>" << endl;
+    // Generate typedefs
+    vector<t_typedef*> typedefs = program_->get_typedefs();
+    vector<t_typedef*>::iterator td_iter;
+    for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
+      generate_typedef(*td_iter);
+    }
+  }
+
+  if (!program_->get_objects().empty()) {
+    f_out_ << "<hr/><h2 id=\"Structs\">Data structures</h2>" << endl;
+    // Generate structs and exceptions in declared order
+    vector<t_struct*> objects = program_->get_objects();
+    vector<t_struct*>::iterator o_iter;
+    for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
+      if ((*o_iter)->is_xception()) {
+        generate_xception(*o_iter);
+      } else {
+        generate_struct(*o_iter);
+      }
+    }
+  }
+
+  if (!program_->get_services().empty()) {
+    f_out_ << "<hr/><h2 id=\"Services\">Services</h2>" << endl;
+    // Generate services
+    vector<t_service*> services = program_->get_services();
+    vector<t_service*>::iterator sv_iter;
+    for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+      service_name_ = get_service_name(*sv_iter);
+      generate_service(*sv_iter);
+    }
+  }
+
+  f_out_ << "</div></body></html>" << endl;
+  f_out_.close();
+
+  generate_index();
+  generate_css();
+}
+
+/**
+ * Emits the index.html file for the recursive set of Thrift programs
+ */
+void t_html_generator::generate_index() {
+  current_file_ = "index.html";
+  string index_fname = get_out_dir() + current_file_;
+  f_out_.open(index_fname.c_str());
+  f_out_ << "<html><head>" << endl;
+  generate_style_tag();
+  f_out_ << "<title>All Thrift declarations</title></head><body>" << endl
+         << "<div class=\"container-fluid\">" << endl << "<h1>All Thrift declarations</h1>" << endl;
+  f_out_ << "<table class=\"table-bordered table-striped "
+            "table-condensed\"><thead><th>Module</th><th>Services</th><th>Data types</th>"
+         << "<th>Constants</th></thead>" << endl;
+  vector<t_program*> programs;
+  generate_program_toc_rows(program_, programs);
+  f_out_ << "</table>" << endl;
+  f_out_ << "</div></body></html>" << endl;
+  f_out_.close();
+}
+
+void t_html_generator::generate_css() {
+  if (!standalone_) {
+    current_file_ = "style.css";
+    string css_fname = get_out_dir() + current_file_;
+    f_out_.open(css_fname.c_str());
+    generate_css_content(f_out_);
+    f_out_.close();
+  }
+}
+
+void t_html_generator::generate_css_content(std::ofstream& f_target) {
+  f_target << BOOTSTRAP_CSS() << endl;
+  f_target << "/* Auto-generated CSS for generated Thrift docs */" << endl;
+  f_target << "h3, h4 { margin-bottom: 6px; }" << endl;
+  f_target << "div.definition { border: 1px solid #CCC; margin-bottom: 10px; padding: 10px; }"
+           << endl;
+  f_target << "div.extends { margin: -0.5em 0 1em 5em }" << endl;
+  f_target << "td { vertical-align: top; }" << endl;
+  f_target << "table { empty-cells: show; }" << endl;
+  f_target << "code { line-height: 20px; }" << endl;
+  f_target << ".table-bordered th, .table-bordered td { border-bottom: 1px solid #DDDDDD; }"
+           << endl;
+}
+
+/**
+ * Generates the CSS tag.
+ * Depending on "standalone", either a CSS file link (default), or the entire CSS is embedded
+ * inline.
+ */
+void t_html_generator::generate_style_tag() {
+  if (!standalone_) {
+    f_out_ << "<link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\"/>" << endl;
+  } else {
+    f_out_ << "<style type=\"text/css\"/><!--" << endl;
+    generate_css_content(f_out_);
+    f_out_ << "--></style>" << endl;
+  }
+}
+
+/**
+ * Returns the target file for a <a href> link
+ * The returned string is empty, whenever filename refers to the current file.
+ */
+std::string t_html_generator::make_file_link(std::string filename) {
+  return (current_file_.compare(filename) != 0) ? filename : "";
+}
+
+/**
+ * If the provided documentable object has documentation attached, this
+ * will emit it to the output stream in HTML format.
+ */
+void t_html_generator::print_doc(t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    if (unsafe_) {
+      f_out_ << tdoc->get_doc() << "<br/>";
+    } else {
+      f_out_ << escape_html(tdoc->get_doc()) << "<br/>";
+    }
+  }
+}
+
+bool t_html_generator::is_utf8_sequence(std::string const& str, size_t firstpos) {
+  // leading char determines the length of the sequence
+  unsigned char c = str.at(firstpos);
+  int count = 0;
+  if ((c & 0xE0) == 0xC0) {
+    count = 1;
+  } else if ((c & 0xF0) == 0xE0) {
+    count = 2;
+  } else if ((c & 0xF8) == 0xF0) {
+    count = 3;
+  } else if ((c & 0xFC) == 0xF8) {
+    count = 4;
+  } else if ((c & 0xFE) == 0xFC) {
+    count = 5;
+  } else {
+    // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 leading byte", c, int(c));
+    return false; // no UTF-8
+  }
+
+  // following chars
+  size_t pos = firstpos + 1;
+  while ((pos < str.length()) && (0 < count)) {
+    c = str.at(pos);
+    if ((c & 0xC0) != 0x80) {
+      // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 following byte", c, int(c));
+      return false; // no UTF-8
+    }
+    --count;
+    ++pos;
+  }
+
+  // true if the sequence is complete
+  return (0 == count);
+}
+
+void t_html_generator::detect_input_encoding(std::string const& str, size_t firstpos) {
+  if (is_utf8_sequence(str, firstpos)) {
+    pdebug("Input seems to be already UTF-8 encoded");
+    input_type_ = INPUT_UTF8;
+    return;
+  }
+
+  // fallback
+  pwarning(1, "Input is not UTF-8, treating as plain ANSI");
+  input_type_ = INPUT_PLAIN;
+}
+
+void t_html_generator::init_allowed__markup() {
+  allowed_markup.clear();
+  // standalone tags
+  allowed_markup["br"] = 1;
+  allowed_markup["br/"] = 1;
+  allowed_markup["img"] = 1;
+  // paired tags
+  allowed_markup["b"] = 1;
+  allowed_markup["/b"] = 1;
+  allowed_markup["u"] = 1;
+  allowed_markup["/u"] = 1;
+  allowed_markup["i"] = 1;
+  allowed_markup["/i"] = 1;
+  allowed_markup["s"] = 1;
+  allowed_markup["/s"] = 1;
+  allowed_markup["big"] = 1;
+  allowed_markup["/big"] = 1;
+  allowed_markup["small"] = 1;
+  allowed_markup["/small"] = 1;
+  allowed_markup["sup"] = 1;
+  allowed_markup["/sup"] = 1;
+  allowed_markup["sub"] = 1;
+  allowed_markup["/sub"] = 1;
+  allowed_markup["pre"] = 1;
+  allowed_markup["/pre"] = 1;
+  allowed_markup["tt"] = 1;
+  allowed_markup["/tt"] = 1;
+  allowed_markup["ul"] = 1;
+  allowed_markup["/ul"] = 1;
+  allowed_markup["ol"] = 1;
+  allowed_markup["/ol"] = 1;
+  allowed_markup["li"] = 1;
+  allowed_markup["/li"] = 1;
+  allowed_markup["a"] = 1;
+  allowed_markup["/a"] = 1;
+  allowed_markup["p"] = 1;
+  allowed_markup["/p"] = 1;
+  allowed_markup["code"] = 1;
+  allowed_markup["/code"] = 1;
+  allowed_markup["dl"] = 1;
+  allowed_markup["/dl"] = 1;
+  allowed_markup["dt"] = 1;
+  allowed_markup["/dt"] = 1;
+  allowed_markup["dd"] = 1;
+  allowed_markup["/dd"] = 1;
+  allowed_markup["h1"] = 1;
+  allowed_markup["/h1"] = 1;
+  allowed_markup["h2"] = 1;
+  allowed_markup["/h2"] = 1;
+  allowed_markup["h3"] = 1;
+  allowed_markup["/h3"] = 1;
+  allowed_markup["h4"] = 1;
+  allowed_markup["/h4"] = 1;
+  allowed_markup["h5"] = 1;
+  allowed_markup["/h5"] = 1;
+  allowed_markup["h6"] = 1;
+  allowed_markup["/h6"] = 1;
+}
+
+std::string t_html_generator::escape_html_tags(std::string const& str) {
+  std::ostringstream result;
+
+  unsigned char c = '?';
+  size_t lastpos;
+  size_t firstpos = 0;
+  while (firstpos < str.length()) {
+
+    // look for non-ASCII char
+    lastpos = firstpos;
+    while (lastpos < str.length()) {
+      c = str.at(lastpos);
+      if (('<' == c) || ('>' == c)) {
+        break;
+      }
+      ++lastpos;
+    }
+
+    // copy what we got so far
+    if (lastpos > firstpos) {
+      result << str.substr(firstpos, lastpos - firstpos);
+      firstpos = lastpos;
+    }
+
+    // reached the end?
+    if (firstpos >= str.length()) {
+      break;
+    }
+
+    // tag end without corresponding begin
+    ++firstpos;
+    if ('>' == c) {
+      result << "&gt;";
+      continue;
+    }
+
+    // extract the tag
+    std::ostringstream tagstream;
+    while (firstpos < str.length()) {
+      c = str.at(firstpos);
+      ++firstpos;
+      if ('<' == c) {
+        tagstream << "&lt;"; // nested begin?
+      } else if ('>' == c) {
+        break;
+      } else {
+        tagstream << c; // not very efficient, but tags should be quite short
+      }
+    }
+
+    // we allow for several markup in docstrings, all else will become escaped
+    string tag_content = tagstream.str();
+    string tag_key = tag_content;
+    size_t first_white = tag_key.find_first_of(" \t\f\v\n\r");
+    if (first_white != string::npos) {
+      tag_key.erase(first_white);
+    }
+    for (std::string::size_type i = 0; i < tag_key.length(); ++i) {
+      tag_key[i] = tolower(tag_key[i]);
+    }
+    if (allowed_markup.find(tag_key) != allowed_markup.end()) {
+      result << "<" << tag_content << ">";
+    } else {
+      result << "&lt;" << tagstream.str() << "&gt;";
+      pverbose("illegal markup <%s> in doc-comment\n", tag_key.c_str());
+    }
+  }
+
+  return result.str();
+}
+
+std::string t_html_generator::escape_html(std::string const& str) {
+  // the generated HTML header says it is UTF-8 encoded
+  // if UTF-8 input has been detected before, we don't need to change anything
+  if (input_type_ == INPUT_UTF8) {
+    return escape_html_tags(str);
+  }
+
+  // convert unsafe chars to their &#<num>; equivalent
+  std::ostringstream result;
+  unsigned char c = '?';
+  unsigned int ic = 0;
+  size_t lastpos;
+  size_t firstpos = 0;
+  while (firstpos < str.length()) {
+
+    // look for non-ASCII char
+    lastpos = firstpos;
+    while (lastpos < str.length()) {
+      c = str.at(lastpos);
+      ic = c;
+      if ((32 > ic) || (127 < ic)) {
+        break;
+      }
+      ++lastpos;
+    }
+
+    // copy what we got so far
+    if (lastpos > firstpos) {
+      result << str.substr(firstpos, lastpos - firstpos);
+      firstpos = lastpos;
+    }
+
+    // reached the end?
+    if (firstpos >= str.length()) {
+      break;
+    }
+
+    // some control code?
+    if (ic <= 31) {
+      switch (c) {
+      case '\r':
+      case '\n':
+      case '\t':
+        result << c;
+        break;
+      default: // silently consume all other ctrl chars
+        break;
+      }
+      ++firstpos;
+      continue;
+    }
+
+    // reached the end?
+    if (firstpos >= str.length()) {
+      break;
+    }
+
+    // try to detect input encoding
+    if (input_type_ == INPUT_UNKNOWN) {
+      detect_input_encoding(str, firstpos);
+      if (input_type_ == INPUT_UTF8) {
+        lastpos = str.length();
+        result << str.substr(firstpos, lastpos - firstpos);
+        break;
+      }
+    }
+
+    // convert the character to something useful based on the detected encoding
+    switch (input_type_) {
+    case INPUT_PLAIN:
+      result << "&#" << ic << ";";
+      ++firstpos;
+      break;
+    default:
+      throw "Unexpected or unrecognized input encoding";
+    }
+  }
+
+  return escape_html_tags(result.str());
+}
+
+/**
+ * Prints out the provided type in HTML
+ */
+int t_html_generator::print_type(t_type* ttype) {
+  std::string::size_type len = 0;
+  f_out_ << "<code>";
+  if (ttype->is_container()) {
+    if (ttype->is_list()) {
+      f_out_ << "list&lt;";
+      len = 6 + print_type(((t_list*)ttype)->get_elem_type());
+      f_out_ << "&gt;";
+    } else if (ttype->is_set()) {
+      f_out_ << "set&lt;";
+      len = 5 + print_type(((t_set*)ttype)->get_elem_type());
+      f_out_ << "&gt;";
+    } else if (ttype->is_map()) {
+      f_out_ << "map&lt;";
+      len = 5 + print_type(((t_map*)ttype)->get_key_type());
+      f_out_ << ", ";
+      len += print_type(((t_map*)ttype)->get_val_type());
+      f_out_ << "&gt;";
+    }
+  } else if (ttype->is_base_type()) {
+    f_out_ << (((t_base_type*)ttype)->is_binary() ? "binary" : ttype->get_name());
+    len = ttype->get_name().size();
+  } else {
+    string prog_name = ttype->get_program()->get_name();
+    string type_name = ttype->get_name();
+    f_out_ << "<a href=\"" << make_file_link(prog_name + ".html") << "#";
+    if (ttype->is_typedef()) {
+      f_out_ << "Typedef_";
+    } else if (ttype->is_struct() || ttype->is_xception()) {
+      f_out_ << "Struct_";
+    } else if (ttype->is_enum()) {
+      f_out_ << "Enum_";
+    } else if (ttype->is_service()) {
+      f_out_ << "Svc_";
+    }
+    f_out_ << type_name << "\">";
+    len = type_name.size();
+    if (ttype->get_program() != program_) {
+      f_out_ << prog_name << ".";
+      len += prog_name.size() + 1;
+    }
+    f_out_ << type_name << "</a>";
+  }
+  f_out_ << "</code>";
+  return (int)len;
+}
+
+/**
+ * Prints out an HTML representation of the provided constant value
+ */
+void t_html_generator::print_const_value(t_type* type, t_const_value* tvalue) {
+
+  // if tvalue is an identifier, the constant content is already shown elsewhere
+  if (tvalue->get_type() == t_const_value::CV_IDENTIFIER) {
+    string fname = program_->get_name() + ".html";
+    string name = escape_html(tvalue->get_identifier());
+    f_out_ << "<code><a href=\"" + make_file_link(fname) + "#Const_" + name + "\">" + name
+              + "</a></code>";
+    return;
+  }
+
+  t_type* truetype = type;
+  while (truetype->is_typedef()) {
+    truetype = ((t_typedef*)truetype)->get_type();
+  }
+
+  bool first = true;
+  if (truetype->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      f_out_ << '"' << escape_html(get_escaped_string(tvalue)) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      f_out_ << ((tvalue->get_integer() != 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+      f_out_ << tvalue->get_integer();
+      break;
+    case t_base_type::TYPE_I16:
+      f_out_ << tvalue->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      f_out_ << tvalue->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      f_out_ << tvalue->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (tvalue->get_type() == t_const_value::CV_INTEGER) {
+        f_out_ << tvalue->get_integer();
+      } else {
+        f_out_ << tvalue->get_double();
+      }
+      break;
+    default:
+      f_out_ << "UNKNOWN BASE TYPE";
+      break;
+    }
+  } else if (truetype->is_enum()) {
+    f_out_ << escape_html(truetype->get_name()) << "."
+           << escape_html(tvalue->get_identifier_name());
+  } else if (truetype->is_struct() || truetype->is_xception()) {
+    f_out_ << "{ ";
+    const vector<t_field*>& fields = ((t_struct*)truetype)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = tvalue->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + truetype->get_name() + " has no field "
+            + v_iter->first->get_string();
+      }
+      if (!first) {
+        f_out_ << ", ";
+      }
+      first = false;
+      f_out_ << escape_html(v_iter->first->get_string()) << " = ";
+      print_const_value(field_type, v_iter->second);
+    }
+    f_out_ << " }";
+  } else if (truetype->is_map()) {
+    f_out_ << "{ ";
+    map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
+    map<t_const_value*, t_const_value*>::iterator map_iter;
+    for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
+      if (!first) {
+        f_out_ << ", ";
+      }
+      first = false;
+      print_const_value(((t_map*)truetype)->get_key_type(), map_iter->first);
+      f_out_ << " = ";
+      print_const_value(((t_map*)truetype)->get_val_type(), map_iter->second);
+    }
+    f_out_ << " }";
+  } else if (truetype->is_list()) {
+    f_out_ << "{ ";
+    vector<t_const_value*> list_elems = tvalue->get_list();
+    ;
+    vector<t_const_value*>::iterator list_iter;
+    for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
+      if (!first) {
+        f_out_ << ", ";
+      }
+      first = false;
+      print_const_value(((t_list*)truetype)->get_elem_type(), *list_iter);
+    }
+    f_out_ << " }";
+  } else if (truetype->is_set()) {
+    f_out_ << "{ ";
+    vector<t_const_value*> list_elems = tvalue->get_list();
+    ;
+    vector<t_const_value*>::iterator list_iter;
+    for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
+      if (!first) {
+        f_out_ << ", ";
+      }
+      first = false;
+      print_const_value(((t_set*)truetype)->get_elem_type(), *list_iter);
+    }
+    f_out_ << " }";
+  } else {
+    f_out_ << "UNKNOWN TYPE";
+  }
+}
+
+/**
+ * Prints out documentation for arguments/exceptions of a function, if any documentation has been
+ * supplied.
+ */
+void t_html_generator::print_fn_args_doc(t_function* tfunction) {
+  bool has_docs = false;
+  vector<t_field*> args = tfunction->get_arglist()->get_members();
+  vector<t_field*>::iterator arg_iter = args.begin();
+  if (arg_iter != args.end()) {
+    for (; arg_iter != args.end(); arg_iter++) {
+      if ((*arg_iter)->has_doc() && !(*arg_iter)->get_doc().empty())
+        has_docs = true;
+    }
+    if (has_docs) {
+      arg_iter = args.begin();
+      f_out_ << "<br/><h4 id=\"Parameters_" << service_name_ << "_" << tfunction->get_name()
+             << "\">Parameters</h4>" << endl;
+      f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
+      f_out_ << "<thead><th>Name</th><th>Description</th></thead>";
+      for (; arg_iter != args.end(); arg_iter++) {
+        f_out_ << "<tr><td>" << (*arg_iter)->get_name();
+        f_out_ << "</td><td>";
+        f_out_ << escape_html((*arg_iter)->get_doc());
+        f_out_ << "</td></tr>" << endl;
+      }
+      f_out_ << "</table>";
+    }
+  }
+
+  has_docs = false;
+  vector<t_field*> excepts = tfunction->get_xceptions()->get_members();
+  vector<t_field*>::iterator ex_iter = excepts.begin();
+  if (ex_iter != excepts.end()) {
+    for (; ex_iter != excepts.end(); ex_iter++) {
+      if ((*ex_iter)->has_doc() && !(*ex_iter)->get_doc().empty())
+        has_docs = true;
+    }
+    if (has_docs) {
+      ex_iter = excepts.begin();
+      f_out_ << "<br/><h4 id=\"Exceptions_" << service_name_ << "_" << tfunction->get_name()
+             << "\">Exceptions</h4>" << endl;
+      f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
+      f_out_ << "<thead><th>Type</th><th>Description</th></thead>";
+      for (; ex_iter != excepts.end(); ex_iter++) {
+        f_out_ << "<tr><td>" << (*ex_iter)->get_type()->get_name();
+        f_out_ << "</td><td>";
+        f_out_ << escape_html((*ex_iter)->get_doc());
+        f_out_ << "</td></tr>" << endl;
+      }
+      f_out_ << "</table>";
+    }
+  }
+}
+
+/**
+ * Generates a typedef.
+ *
+ * @param ttypedef The type definition
+ */
+void t_html_generator::generate_typedef(t_typedef* ttypedef) {
+  string name = ttypedef->get_name();
+  f_out_ << "<div class=\"definition\">";
+  f_out_ << "<h3 id=\"Typedef_" << name << "\">Typedef: " << name << "</h3>" << endl;
+  f_out_ << "<p><strong>Base type:</strong>&nbsp;";
+  print_type(ttypedef->get_type());
+  f_out_ << "</p>" << endl;
+  print_doc(ttypedef);
+  f_out_ << "</div>" << endl;
+}
+
+/**
+ * Generates code for an enumerated type.
+ *
+ * @param tenum The enumeration
+ */
+void t_html_generator::generate_enum(t_enum* tenum) {
+  string name = tenum->get_name();
+  f_out_ << "<div class=\"definition\">";
+  f_out_ << "<h3 id=\"Enum_" << name << "\">Enumeration: " << name << "</h3>" << endl;
+  print_doc(tenum);
+  vector<t_enum_value*> values = tenum->get_constants();
+  vector<t_enum_value*>::iterator val_iter;
+  f_out_ << "<br/><table class=\"table-bordered table-striped table-condensed\">" << endl;
+  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
+    f_out_ << "<tr><td><code>";
+    f_out_ << (*val_iter)->get_name();
+    f_out_ << "</code></td><td><code>";
+    f_out_ << (*val_iter)->get_value();
+    f_out_ << "</code></td><td>" << endl;
+    print_doc((*val_iter));
+    f_out_ << "</td></tr>" << endl;
+  }
+  f_out_ << "</table></div>" << endl;
+}
+
+/**
+ * Generates a constant value
+ */
+void t_html_generator::generate_const(t_const* tconst) {
+  string name = tconst->get_name();
+  f_out_ << "<tr id=\"Const_" << name << "\"><td><code>" << name << "</code></td><td>";
+  print_type(tconst->get_type());
+  f_out_ << "</td><td><code>";
+  print_const_value(tconst->get_type(), tconst->get_value());
+  f_out_ << "</code></td></tr>";
+  if (tconst->has_doc()) {
+    f_out_ << "<tr><td colspan=\"3\"><blockquote>";
+    print_doc(tconst);
+    f_out_ << "</blockquote></td></tr>";
+  }
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_html_generator::generate_struct(t_struct* tstruct) {
+  string name = tstruct->get_name();
+  f_out_ << "<div class=\"definition\">";
+  f_out_ << "<h3 id=\"Struct_" << name << "\">";
+  if (tstruct->is_xception()) {
+    f_out_ << "Exception: ";
+  } else if (tstruct->is_union()) {
+    f_out_ << "Union: ";
+  } else {
+    f_out_ << "Struct: ";
+  }
+  f_out_ << name << "</h3>" << endl;
+  vector<t_field*> members = tstruct->get_members();
+  vector<t_field*>::iterator mem_iter = members.begin();
+  f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
+  f_out_ << "<thead><th>Key</th><th>Field</th><th>Type</th><th>Description</th><th>Requiredness</"
+            "th><th>Default value</th></thead>" << endl;
+  for (; mem_iter != members.end(); mem_iter++) {
+    f_out_ << "<tr><td>" << (*mem_iter)->get_key() << "</td><td>";
+    f_out_ << (*mem_iter)->get_name();
+    f_out_ << "</td><td>";
+    print_type((*mem_iter)->get_type());
+    f_out_ << "</td><td>";
+    f_out_ << escape_html((*mem_iter)->get_doc());
+    f_out_ << "</td><td>";
+    if ((*mem_iter)->get_req() == t_field::T_OPTIONAL) {
+      f_out_ << "optional";
+    } else if ((*mem_iter)->get_req() == t_field::T_REQUIRED) {
+      f_out_ << "required";
+    } else {
+      f_out_ << "default";
+    }
+    f_out_ << "</td><td>";
+    t_const_value* default_val = (*mem_iter)->get_value();
+    if (default_val != NULL) {
+      f_out_ << "<code>";
+      print_const_value((*mem_iter)->get_type(), default_val);
+      f_out_ << "</code>";
+    }
+    f_out_ << "</td></tr>" << endl;
+  }
+  f_out_ << "</table><br/>";
+  print_doc(tstruct);
+  f_out_ << "</div>";
+}
+
+/**
+ * Exceptions are special structs
+ *
+ * @param tstruct The struct definition
+ */
+void t_html_generator::generate_xception(t_struct* txception) {
+  generate_struct(txception);
+}
+
+/**
+ * Generates the HTML block for a Thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_html_generator::generate_service(t_service* tservice) {
+  f_out_ << "<h3 id=\"Svc_" << service_name_ << "\">Service: " << service_name_ << "</h3>" << endl;
+
+  if (tservice->get_extends()) {
+    f_out_ << "<div class=\"extends\"><em>extends</em> ";
+    print_type(tservice->get_extends());
+    f_out_ << "</div>\n";
+  }
+  print_doc(tservice);
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator fn_iter = functions.begin();
+  for (; fn_iter != functions.end(); fn_iter++) {
+    string fn_name = (*fn_iter)->get_name();
+    f_out_ << "<div class=\"definition\">";
+    f_out_ << "<h4 id=\"Fn_" << service_name_ << "_" << fn_name << "\">Function: " << service_name_
+           << "." << fn_name << "</h4>" << endl;
+    f_out_ << "<pre>";
+    std::string::size_type offset = print_type((*fn_iter)->get_returntype());
+    bool first = true;
+    f_out_ << " " << fn_name << "(";
+    offset += fn_name.size() + 2;
+    vector<t_field*> args = (*fn_iter)->get_arglist()->get_members();
+    vector<t_field*>::iterator arg_iter = args.begin();
+    for (; arg_iter != args.end(); arg_iter++) {
+      if (!first) {
+        f_out_ << "," << endl;
+        for (std::string::size_type i = 0; i < offset; ++i) {
+          f_out_ << " ";
+        }
+      }
+      first = false;
+      print_type((*arg_iter)->get_type());
+      f_out_ << " " << (*arg_iter)->get_name();
+      if ((*arg_iter)->get_value() != NULL) {
+        f_out_ << " = ";
+        print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value());
+      }
+    }
+    f_out_ << ")" << endl;
+    first = true;
+    vector<t_field*> excepts = (*fn_iter)->get_xceptions()->get_members();
+    vector<t_field*>::iterator ex_iter = excepts.begin();
+    if (ex_iter != excepts.end()) {
+      f_out_ << "    throws ";
+      for (; ex_iter != excepts.end(); ex_iter++) {
+        if (!first) {
+          f_out_ << ", ";
+        }
+        first = false;
+        print_type((*ex_iter)->get_type());
+      }
+      f_out_ << endl;
+    }
+    f_out_ << "</pre>";
+    print_doc(*fn_iter);
+    print_fn_args_doc(*fn_iter);
+    f_out_ << "</div>";
+  }
+}
+
+THRIFT_REGISTER_GENERATOR(
+    html,
+    "HTML",
+    "    standalone:      Self-contained mode, includes all CSS in the HTML files.\n"
+    "                     Generates no style.css file, but HTML files will be larger.\n"
+    "    noescape:        Do not escape html in doc text.\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_html_generator.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_html_generator.h b/compiler/cpp/src/thrift/generate/t_html_generator.h
new file mode 100644
index 0000000..600b17f
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_html_generator.h
@@ -0,0 +1,240 @@
+#define BOOTSTRAP_CSS()                                                                            \
+  "/*!\n"                                                                                          \
+  " * Bootstrap v2.0.3\n"                                                                          \
+  " *\n"                                                                                           \
+  " * Copyright 2012 Twitter, Inc\n"                                                               \
+  " * Licensed under the Apache License v2.0\n"                                                    \
+  " * http://www.apache.org/licenses/LICENSE-2.0\n"                                                \
+  " *\n"                                                                                           \
+  " * Designed and built with all the love in the world @twitter by @mdo and @fat.\n"              \
+  " */\n"                                                                                          \
+  ".clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:\"\";}\n"             \
+  ".clearfix:after{clear:both;}\n"                                                                 \
+  ".hide-text{font:0/0 "                                                                           \
+  "a;color:transparent;text-shadow:none;background-color:transparent;border:0;}\n"                 \
+  ".input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-"    \
+  "moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;}\n"                  \
+  "article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}\n"     \
+  "audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}\n"                            \
+  "audio:not([controls]){display:none;}\n"                                                         \
+  "html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}\n"                \
+  "a:focus{outline:thin dotted #333;outline:5px auto "                                             \
+  "-webkit-focus-ring-color;outline-offset:-2px;}\n"                                               \
+  "a:hover,a:active{outline:0;}\n"                                                                 \
+  "sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}\n"              \
+  "sup{top:-0.5em;}\n"                                                                             \
+  "sub{bottom:-0.25em;}\n"                                                                         \
+  "img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}\n"           \
+  "button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}\n"                 \
+  "button,input{*overflow:visible;line-height:normal;}\n"                                          \
+  "button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}\n"                        \
+  "button,input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{cursor:pointer;-"    \
+  "webkit-appearance:button;}\n"                                                                   \
+  "input[type=\"search\"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:"  \
+  "content-box;-webkit-appearance:textfield;}\n"                                                   \
+  "input[type=\"search\"]::-webkit-search-decoration,input[type=\"search\"]::-webkit-search-"      \
+  "cancel-button{-webkit-appearance:none;}\n"                                                      \
+  "textarea{overflow:auto;vertical-align:top;}\n"                                                  \
+  "body{margin:0;font-family:\"Helvetica "                                                         \
+  "Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-"    \
+  "color:#ffffff;}\n"                                                                              \
+  "a{color:#0088cc;text-decoration:none;}\n"                                                       \
+  "a:hover{color:#005580;text-decoration:underline;}\n"                                            \
+  ".row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:\"\";}\n"          \
+  ".row:after{clear:both;}\n"                                                                      \
+  "[class*=\"span\"]{float:left;margin-left:20px;}\n"                                              \
+  ".container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}\n"        \
+  ".span12{width:940px;}\n"                                                                        \
+  ".span11{width:860px;}\n"                                                                        \
+  ".span10{width:780px;}\n"                                                                        \
+  ".span9{width:700px;}\n"                                                                         \
+  ".span8{width:620px;}\n"                                                                         \
+  ".span7{width:540px;}\n"                                                                         \
+  ".span6{width:460px;}\n"                                                                         \
+  ".span5{width:380px;}\n"                                                                         \
+  ".span4{width:300px;}\n"                                                                         \
+  ".span3{width:220px;}\n"                                                                         \
+  ".span2{width:140px;}\n"                                                                         \
+  ".span1{width:60px;}\n"                                                                          \
+  ".offset12{margin-left:980px;}\n"                                                                \
+  ".offset11{margin-left:900px;}\n"                                                                \
+  ".offset10{margin-left:820px;}\n"                                                                \
+  ".offset9{margin-left:740px;}\n"                                                                 \
+  ".offset8{margin-left:660px;}\n"                                                                 \
+  ".offset7{margin-left:580px;}\n"                                                                 \
+  ".offset6{margin-left:500px;}\n"                                                                 \
+  ".offset5{margin-left:420px;}\n"                                                                 \
+  ".offset4{margin-left:340px;}\n"                                                                 \
+  ".offset3{margin-left:260px;}\n"                                                                 \
+  ".offset2{margin-left:180px;}\n"                                                                 \
+  ".offset1{margin-left:100px;}\n"                                                                 \
+  ".row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:\"\";}" \
+  "\n"                                                                                             \
+  ".row-fluid:after{clear:both;}\n"                                                                \
+  ".row-fluid "                                                                                    \
+  "[class*=\"span\"]{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-" \
+  "box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:"  \
+  "2.127659574%;*margin-left:2.0744680846382977%;}\n"                                              \
+  ".row-fluid [class*=\"span\"]:first-child{margin-left:0;}\n"                                     \
+  ".row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%;}\n"                      \
+  ".row-fluid .span11{width:91.489361693%;*width:91.4361702036383%;}\n"                            \
+  ".row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%;}\n"                      \
+  ".row-fluid .span9{width:74.468085099%;*width:74.4148936096383%;}\n"                             \
+  ".row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%;}\n"                       \
+  ".row-fluid .span7{width:57.446808505%;*width:57.3936170156383%;}\n"                             \
+  ".row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%;}\n"                       \
+  ".row-fluid .span5{width:40.425531911%;*width:40.3723404216383%;}\n"                             \
+  ".row-fluid .span4{width:31.914893614%;*width:31.8617021246383%;}\n"                             \
+  ".row-fluid .span3{width:23.404255317%;*width:23.3510638276383%;}\n"                             \
+  ".row-fluid .span2{width:14.89361702%;*width:14.8404255306383%;}\n"                              \
+  ".row-fluid .span1{width:6.382978723%;*width:6.329787233638298%;}\n"                             \
+  ".container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{"     \
+  "display:table;content:\"\";}\n"                                                                 \
+  ".container:after{clear:both;}\n"                                                                \
+  ".container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,."       \
+  "container-fluid:after{display:table;content:\"\";}\n"                                           \
+  ".container-fluid:after{clear:both;}\n"                                                          \
+  "p{margin:0 0 9px;font-family:\"Helvetica "                                                      \
+  "Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p "                          \
+  "small{font-size:11px;color:#999999;}\n"                                                         \
+  ".lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;}\n"                   \
+  "h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:"  \
+  "optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 "                           \
+  "small{font-weight:normal;color:#999999;}\n"                                                     \
+  "h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}\n"                                \
+  "h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}\n"                                \
+  "h3{font-size:18px;line-height:27px;}h3 small{font-size:14px;}\n"                                \
+  "h4,h5,h6{line-height:18px;}\n"                                                                  \
+  "h4{font-size:14px;}h4 small{font-size:12px;}\n"                                                 \
+  "h5{font-size:12px;}\n"                                                                          \
+  "h6{font-size:11px;color:#999999;text-transform:uppercase;}\n"                                   \
+  ".page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;}\n"             \
+  ".page-header h1{line-height:1;}\n"                                                              \
+  "ul,ol{padding:0;margin:0 0 9px 25px;}\n"                                                        \
+  "ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}\n"                                                    \
+  "ul{list-style:disc;}\n"                                                                         \
+  "ol{list-style:decimal;}\n"                                                                      \
+  "li{line-height:18px;}\n"                                                                        \
+  "ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}\n"                                      \
+  "dl{margin-bottom:18px;}\n"                                                                      \
+  "dt,dd{line-height:18px;}\n"                                                                     \
+  "dt{font-weight:bold;line-height:17px;}\n"                                                       \
+  "dd{margin-left:9px;}\n"                                                                         \
+  ".dl-horizontal "                                                                                \
+  "dt{float:left;width:120px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;"  \
+  "white-space:nowrap;}\n"                                                                         \
+  ".dl-horizontal dd{margin-left:130px;}\n"                                                        \
+  "hr{margin:18px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}\n"     \
+  "strong{font-weight:bold;}\n"                                                                    \
+  "em{font-style:italic;}\n"                                                                       \
+  ".muted{color:#999999;}\n"                                                                       \
+  "abbr[title]{cursor:help;border-bottom:1px dotted #ddd;}\n"                                      \
+  "abbr.initialism{font-size:90%;text-transform:uppercase;}\n"                                     \
+  "blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote "       \
+  "p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}\n"                        \
+  "blockquote small{display:block;line-height:18px;color:#999999;}blockquote "                     \
+  "small:before{content:'\\2014 \\00A0';}\n"                                                       \
+  "blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid "    \
+  "#eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right "                          \
+  "small{text-align:right;}\n"                                                                     \
+  "q:before,q:after,blockquote:before,blockquote:after{content:\"\";}\n"                           \
+  "address{display:block;margin-bottom:18px;font-style:normal;line-height:18px;}\n"                \
+  "small{font-size:100%;}\n"                                                                       \
+  "cite{font-style:normal;}\n"                                                                     \
+  "code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,\"Courier "                        \
+  "New\",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;" \
+  "border-radius:3px;}\n"                                                                          \
+  "code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}\n"          \
+  "pre{display:block;padding:8.5px;margin:0 0 "                                                    \
+  "9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:" \
+  "pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid "      \
+  "rgba(0, 0, 0, "                                                                                 \
+  "0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{"     \
+  "margin-bottom:18px;}\n"                                                                         \
+  "pre code{padding:0;color:inherit;background-color:transparent;border:0;}\n"                     \
+  ".pre-scrollable{max-height:340px;overflow-y:scroll;}\n"                                         \
+  ".label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#ffffff;vertical-"     \
+  "align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, "                          \
+  "0.25);background-color:#999999;}\n"                                                             \
+  ".label{padding:1px 4px "                                                                        \
+  "2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}\n"                     \
+  ".badge{padding:1px 9px "                                                                        \
+  "2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}\n"                     \
+  "a.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}\n"              \
+  ".label-important,.badge-important{background-color:#b94a48;}\n"                                 \
+  ".label-important[href],.badge-important[href]{background-color:#953b39;}\n"                     \
+  ".label-warning,.badge-warning{background-color:#f89406;}\n"                                     \
+  ".label-warning[href],.badge-warning[href]{background-color:#c67605;}\n"                         \
+  ".label-success,.badge-success{background-color:#468847;}\n"                                     \
+  ".label-success[href],.badge-success[href]{background-color:#356635;}\n"                         \
+  ".label-info,.badge-info{background-color:#3a87ad;}\n"                                           \
+  ".label-info[href],.badge-info[href]{background-color:#2d6987;}\n"                               \
+  ".label-inverse,.badge-inverse{background-color:#333333;}\n"                                     \
+  ".label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a;}\n"                         \
+  "table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}"  \
+  "\n"                                                                                             \
+  ".table{width:100%;margin-bottom:18px;}.table th,.table "                                        \
+  "td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid "       \
+  "#dddddd;}\n"                                                                                    \
+  ".table th{font-weight:bold;}\n"                                                                 \
+  ".table thead th{vertical-align:bottom;}\n"                                                      \
+  ".table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table "          \
+  "colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table "               \
+  "thead:first-child tr:first-child th,.table thead:first-child tr:first-child "                   \
+  "td{border-top:0;}\n"                                                                            \
+  ".table tbody+tbody{border-top:2px solid #dddddd;}\n"                                            \
+  ".table-condensed th,.table-condensed td{padding:4px 5px;}\n"                                    \
+  ".table-bordered{border:1px solid "                                                              \
+  "#dddddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-"      \
+  "radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered "       \
+  "td{border-left:1px solid #dddddd;}\n"                                                           \
+  ".table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child "  \
+  "th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead "             \
+  "tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered "            \
+  "colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child "             \
+  "th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child "      \
+  "tr:first-child td{border-top:0;}\n"                                                             \
+  ".table-bordered thead:first-child tr:first-child th:first-child,.table-bordered "               \
+  "tbody:first-child tr:first-child "                                                              \
+  "td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-"      \
+  "radius-topleft:4px;}\n"                                                                         \
+  ".table-bordered thead:first-child tr:first-child th:last-child,.table-bordered "                \
+  "tbody:first-child tr:first-child "                                                              \
+  "td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-"     \
+  "radius-topright:4px;}\n"                                                                        \
+  ".table-bordered thead:last-child tr:last-child th:first-child,.table-bordered "                 \
+  "tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 "                     \
+  "4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 "                                          \
+  "4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-"    \
+  "bottomleft:4px;}\n"                                                                             \
+  ".table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child " \
+  "tr:last-child "                                                                                 \
+  "td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-"      \
+  "border-radius-bottomright:4px;}\n"                                                              \
+  ".table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) "              \
+  "th{background-color:#f9f9f9;}\n"                                                                \
+  ".table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5;}\n"                 \
+  "table .span1{float:none;width:44px;margin-left:0;}\n"                                           \
+  "table .span2{float:none;width:124px;margin-left:0;}\n"                                          \
+  "table .span3{float:none;width:204px;margin-left:0;}\n"                                          \
+  "table .span4{float:none;width:284px;margin-left:0;}\n"                                          \
+  "table .span5{float:none;width:364px;margin-left:0;}\n"                                          \
+  "table .span6{float:none;width:444px;margin-left:0;}\n"                                          \
+  "table .span7{float:none;width:524px;margin-left:0;}\n"                                          \
+  "table .span8{float:none;width:604px;margin-left:0;}\n"                                          \
+  "table .span9{float:none;width:684px;margin-left:0;}\n"                                          \
+  "table .span10{float:none;width:764px;margin-left:0;}\n"                                         \
+  "table .span11{float:none;width:844px;margin-left:0;}\n"                                         \
+  "table .span12{float:none;width:924px;margin-left:0;}\n"                                         \
+  "table .span13{float:none;width:1004px;margin-left:0;}\n"                                        \
+  "table .span14{float:none;width:1084px;margin-left:0;}\n"                                        \
+  "table .span15{float:none;width:1164px;margin-left:0;}\n"                                        \
+  "table .span16{float:none;width:1244px;margin-left:0;}\n"                                        \
+  "table .span17{float:none;width:1324px;margin-left:0;}\n"                                        \
+  "table .span18{float:none;width:1404px;margin-left:0;}\n"                                        \
+  "table .span19{float:none;width:1484px;margin-left:0;}\n"                                        \
+  "table .span20{float:none;width:1564px;margin-left:0;}\n"                                        \
+  "table .span21{float:none;width:1644px;margin-left:0;}\n"                                        \
+  "table .span22{float:none;width:1724px;margin-left:0;}\n"                                        \
+  "table .span23{float:none;width:1804px;margin-left:0;}\n"                                        \
+  "table .span24{float:none;width:1884px;margin-left:0;}"


[46/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_csharp_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_csharp_generator.cc b/compiler/cpp/src/generate/t_csharp_generator.cc
deleted file mode 100644
index d356f26..0000000
--- a/compiler/cpp/src/generate/t_csharp_generator.cc
+++ /dev/null
@@ -1,3202 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <cassert>
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <cctype>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-struct member_mapping_scope {
-  void* scope_member;
-  std::map<std::string, std::string> mapping_table;
-};
-
-class t_csharp_generator : public t_oop_generator {
-public:
-  t_csharp_generator(t_program* program,
-                     const std::map<std::string, std::string>& parsed_options,
-                     const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-
-    std::map<std::string, std::string>::const_iterator iter;
-
-    async_ = false;
-    nullable_ = false;
-    hashcode_ = false;
-    union_ = false;
-    serialize_ = false;
-    wcf_ = false;
-    wcf_namespace_.clear();
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("async") == 0) {
-        async_ = true;
-      } else if( iter->first.compare("nullable") == 0) {
-        nullable_ = true;
-      } else if( iter->first.compare("hashcode") == 0) {
-        hashcode_ = true;
-      } else if( iter->first.compare("union") == 0) {
-        union_ = true;
-      } else if( iter->first.compare("serial") == 0) {
-        serialize_ = true;
-        wcf_namespace_ = iter->second; // since there can be only one namespace
-      } else if( iter->first.compare("wcf") == 0) {
-        wcf_ = true;
-        wcf_namespace_ = iter->second;
-      } else {
-        throw "unknown option csharp:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-csharp";
-  }
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_union(t_struct* tunion);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-  void generate_property(ofstream& out, t_field* tfield, bool isPublic, bool generateIsset);
-  void generate_csharp_property(ofstream& out,
-                                t_field* tfield,
-                                bool isPublic,
-                                bool includeIsset = true,
-                                std::string fieldPrefix = "");
-  bool print_const_value(std::ofstream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool in_static,
-                         bool defval = false,
-                         bool needtype = false);
-  std::string render_const_value(std::ofstream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-  void print_const_constructor(std::ofstream& out, std::vector<t_const*> consts);
-  void print_const_def_value(std::ofstream& out,
-                             std::string name,
-                             t_type* type,
-                             t_const_value* value);
-
-  void generate_csharp_struct(t_struct* tstruct, bool is_exception);
-  void generate_csharp_union(t_struct* tunion);
-  void generate_csharp_struct_definition(std::ofstream& out,
-                                         t_struct* tstruct,
-                                         bool is_xception = false,
-                                         bool in_class = false,
-                                         bool is_result = false);
-  void generate_csharp_union_definition(std::ofstream& out, t_struct* tunion);
-  void generate_csharp_union_class(std::ofstream& out, t_struct* tunion, t_field* tfield);
-  void generate_csharp_wcffault(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_equals(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_hashcode(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_union_reader(std::ofstream& out, t_struct* tunion);
-
-  void generate_function_helpers(t_function* tfunction);
-  void generate_service_interface(t_service* tservice);
-  void generate_separate_service_interfaces(t_service* tservice);
-  void generate_sync_service_interface(t_service* tservice);
-  void generate_async_service_interface(t_service* tservice);
-  void generate_combined_service_interface(t_service* tservice);
-  void generate_silverlight_async_methods(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_service_server_sync(t_service* tservice);
-  void generate_service_server_async(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* function);
-  void generate_process_function_async(t_service* tservice, t_function* function);
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  bool is_propertyless = false);
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-  void generate_deserialize_list_element(std::ofstream& out, t_list* list, std::string prefix = "");
-  void generate_serialize_field(std::ofstream& out,
-                                t_field* tfield,
-                                std::string prefix = "",
-                                bool is_element = false,
-                                bool is_propertyless = false);
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map);
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_csharp_doc(std::ofstream& out, t_field* field);
-  void generate_csharp_doc(std::ofstream& out, t_doc* tdoc);
-  void generate_csharp_doc(std::ofstream& out, t_function* tdoc);
-  void generate_csharp_docstring_comment(std::ofstream& out, string contents);
-
-  void start_csharp_namespace(std::ofstream& out);
-  void end_csharp_namespace(std::ofstream& out);
-
-  std::string csharp_type_usings();
-  std::string csharp_thrift_usings();
-
-  std::string type_name(t_type* ttype,
-                        bool in_countainer = false,
-                        bool in_init = false,
-                        bool in_param = false,
-                        bool is_required = false);
-  std::string base_type_name(t_base_type* tbase,
-                             bool in_container = false,
-                             bool in_param = false,
-                             bool is_required = false);
-  std::string declare_field(t_field* tfield, bool init = false, std::string prefix = "");
-  std::string function_signature_async_begin(t_function* tfunction, std::string prefix = "");
-  std::string function_signature_async_end(t_function* tfunction, std::string prefix = "");
-  std::string function_signature_async(t_function* tfunction, std::string prefix = "");
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string prop_name(t_field* tfield, bool suppress_mapping = false);
-  std::string get_enum_class_name(t_type* type);
-
-  bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; }
-
-  bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; }
-
-  bool type_can_be_null(t_type* ttype) {
-    while (ttype->is_typedef()) {
-      ttype = ((t_typedef*)ttype)->get_type();
-    }
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
-           || ttype->is_string();
-  }
-
-private:
-  std::string namespace_name_;
-  std::ofstream f_service_;
-  std::string namespace_dir_;
-  bool async_;
-  bool nullable_;
-  bool union_;
-  bool hashcode_;
-  bool serialize_;
-  bool wcf_;
-  std::string wcf_namespace_;
-
-  std::map<std::string, int> csharp_keywords;
-  std::vector<member_mapping_scope>  member_mapping_scopes;
-
-  void init_keywords();
-  std::string normalize_name(std::string name);
-  std::string make_valid_csharp_identifier(std::string const& fromName);
-  void prepare_member_name_mapping(t_struct* tstruct);
-  void prepare_member_name_mapping(void* scope,
-                                   const vector<t_field*>& members,
-                                   const string& structname);
-  void cleanup_member_name_mapping(void* scope);
-  string get_mapped_member_name(string oldname);
-};
-
-void t_csharp_generator::init_generator() {
-  MKDIR(get_out_dir().c_str());
-  namespace_name_ = program_->get_namespace("csharp");
-
-  string dir = namespace_name_;
-  string subdir = get_out_dir().c_str();
-  string::size_type loc;
-
-  while ((loc = dir.find(".")) != string::npos) {
-    subdir = subdir + "/" + dir.substr(0, loc);
-    MKDIR(subdir.c_str());
-    dir = dir.substr(loc + 1);
-  }
-  if (dir.size() > 0) {
-    subdir = subdir + "/" + dir;
-    MKDIR(subdir.c_str());
-  }
-
-  namespace_dir_ = subdir;
-  init_keywords();
-  
-  while( ! member_mapping_scopes.empty()) {
-    cleanup_member_name_mapping( member_mapping_scopes.back().scope_member);
-  }
-
-  pverbose("C# options:\n");
-  pverbose("- async ...... %s\n", (async_ ? "ON" : "off"));
-  pverbose("- nullable ... %s\n", (nullable_ ? "ON" : "off"));
-  pverbose("- union ...... %s\n", (union_ ? "ON" : "off"));
-  pverbose("- hashcode ... %s\n", (hashcode_ ? "ON" : "off"));
-  pverbose("- serialize .. %s\n", (serialize_ ? "ON" : "off"));
-  pverbose("- wcf ........ %s\n", (wcf_ ? "ON" : "off"));
-}
-
-std::string t_csharp_generator::normalize_name(std::string name) {
-  string tmp(name);
-  std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
-
-  // un-conflict keywords by prefixing with "@"
-  if (csharp_keywords.find(tmp) != csharp_keywords.end()) {
-    return "@" + name;
-  }
-
-  // no changes necessary
-  return name;
-}
-
-void t_csharp_generator::init_keywords() {
-  csharp_keywords.clear();
-
-  // C# keywords
-  csharp_keywords["abstract"] = 1;
-  csharp_keywords["as"] = 1;
-  csharp_keywords["base"] = 1;
-  csharp_keywords["bool"] = 1;
-  csharp_keywords["break"] = 1;
-  csharp_keywords["byte"] = 1;
-  csharp_keywords["case"] = 1;
-  csharp_keywords["catch"] = 1;
-  csharp_keywords["char"] = 1;
-  csharp_keywords["checked"] = 1;
-  csharp_keywords["class"] = 1;
-  csharp_keywords["const"] = 1;
-  csharp_keywords["continue"] = 1;
-  csharp_keywords["decimal"] = 1;
-  csharp_keywords["default"] = 1;
-  csharp_keywords["delegate"] = 1;
-  csharp_keywords["do"] = 1;
-  csharp_keywords["double"] = 1;
-  csharp_keywords["else"] = 1;
-  csharp_keywords["enum"] = 1;
-  csharp_keywords["event"] = 1;
-  csharp_keywords["explicit"] = 1;
-  csharp_keywords["extern"] = 1;
-  csharp_keywords["false"] = 1;
-  csharp_keywords["finally"] = 1;
-  csharp_keywords["fixed"] = 1;
-  csharp_keywords["float"] = 1;
-  csharp_keywords["for"] = 1;
-  csharp_keywords["foreach"] = 1;
-  csharp_keywords["goto"] = 1;
-  csharp_keywords["if"] = 1;
-  csharp_keywords["implicit"] = 1;
-  csharp_keywords["in"] = 1;
-  csharp_keywords["int"] = 1;
-  csharp_keywords["interface"] = 1;
-  csharp_keywords["internal"] = 1;
-  csharp_keywords["is"] = 1;
-  csharp_keywords["lock"] = 1;
-  csharp_keywords["long"] = 1;
-  csharp_keywords["namespace"] = 1;
-  csharp_keywords["new"] = 1;
-  csharp_keywords["null"] = 1;
-  csharp_keywords["object"] = 1;
-  csharp_keywords["operator"] = 1;
-  csharp_keywords["out"] = 1;
-  csharp_keywords["override"] = 1;
-  csharp_keywords["params"] = 1;
-  csharp_keywords["private"] = 1;
-  csharp_keywords["protected"] = 1;
-  csharp_keywords["public"] = 1;
-  csharp_keywords["readonly"] = 1;
-  csharp_keywords["ref"] = 1;
-  csharp_keywords["return"] = 1;
-  csharp_keywords["sbyte"] = 1;
-  csharp_keywords["sealed"] = 1;
-  csharp_keywords["short"] = 1;
-  csharp_keywords["sizeof"] = 1;
-  csharp_keywords["stackalloc"] = 1;
-  csharp_keywords["static"] = 1;
-  csharp_keywords["string"] = 1;
-  csharp_keywords["struct"] = 1;
-  csharp_keywords["switch"] = 1;
-  csharp_keywords["this"] = 1;
-  csharp_keywords["throw"] = 1;
-  csharp_keywords["true"] = 1;
-  csharp_keywords["try"] = 1;
-  csharp_keywords["typeof"] = 1;
-  csharp_keywords["uint"] = 1;
-  csharp_keywords["ulong"] = 1;
-  csharp_keywords["unchecked"] = 1;
-  csharp_keywords["unsafe"] = 1;
-  csharp_keywords["ushort"] = 1;
-  csharp_keywords["using"] = 1;
-  csharp_keywords["virtual"] = 1;
-  csharp_keywords["void"] = 1;
-  csharp_keywords["volatile"] = 1;
-  csharp_keywords["while"] = 1;
-
-  // C# contextual keywords
-  csharp_keywords["add"] = 1;
-  csharp_keywords["alias"] = 1;
-  csharp_keywords["ascending"] = 1;
-  csharp_keywords["async"] = 1;
-  csharp_keywords["await"] = 1;
-  csharp_keywords["descending"] = 1;
-  csharp_keywords["dynamic"] = 1;
-  csharp_keywords["from"] = 1;
-  csharp_keywords["get"] = 1;
-  csharp_keywords["global"] = 1;
-  csharp_keywords["group"] = 1;
-  csharp_keywords["into"] = 1;
-  csharp_keywords["join"] = 1;
-  csharp_keywords["let"] = 1;
-  csharp_keywords["orderby"] = 1;
-  csharp_keywords["partial"] = 1;
-  csharp_keywords["remove"] = 1;
-  csharp_keywords["select"] = 1;
-  csharp_keywords["set"] = 1;
-  csharp_keywords["value"] = 1;
-  csharp_keywords["var"] = 1;
-  csharp_keywords["where"] = 1;
-  csharp_keywords["yield"] = 1;
-}
-
-void t_csharp_generator::start_csharp_namespace(ofstream& out) {
-  if (!namespace_name_.empty()) {
-    out << "namespace " << namespace_name_ << "\n";
-    scope_up(out);
-  }
-}
-
-void t_csharp_generator::end_csharp_namespace(ofstream& out) {
-  if (!namespace_name_.empty()) {
-    scope_down(out);
-  }
-}
-
-string t_csharp_generator::csharp_type_usings() {
-  return string() + "using System;\n" + "using System.Collections;\n"
-         + "using System.Collections.Generic;\n" + "using System.Text;\n" + "using System.IO;\n"
-         + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n"
-         + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "")
-         + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "")
-         + ((serialize_ || wcf_) ? "#endif\n" : "") + (wcf_ ? "//using System.ServiceModel;\n" : "")
-         + "using System.Runtime.Serialization;\n";
-}
-
-string t_csharp_generator::csharp_thrift_usings() {
-  return string() + "using Thrift.Protocol;\n" + "using Thrift.Transport;\n";
-}
-
-void t_csharp_generator::close_generator() {
-}
-void t_csharp_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-void t_csharp_generator::generate_enum(t_enum* tenum) {
-  string f_enum_name = namespace_dir_ + "/" + (tenum->get_name()) + ".cs";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
-
-  f_enum << autogen_comment() << endl;
-
-  start_csharp_namespace(f_enum);
-
-  generate_csharp_doc(f_enum, tenum);
-
-  indent(f_enum) << "public enum " << tenum->get_name() << "\n";
-  scope_up(f_enum);
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    generate_csharp_doc(f_enum, *c_iter);
-
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << (*c_iter)->get_name() << " = " << value << "," << endl;
-  }
-
-  scope_down(f_enum);
-
-  end_csharp_namespace(f_enum);
-
-  f_enum.close();
-}
-
-void t_csharp_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-  string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  f_consts << autogen_comment() << csharp_type_usings() << endl;
-
-  start_csharp_namespace(f_consts);
-
-  indent(f_consts) << "public static class " << make_valid_csharp_identifier(program_name_)
-                   << "Constants" << endl;
-  scope_up(f_consts);
-
-  vector<t_const*>::iterator c_iter;
-  bool need_static_constructor = false;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    generate_csharp_doc(f_consts, (*c_iter));
-    if (print_const_value(f_consts,
-                          (*c_iter)->get_name(),
-                          (*c_iter)->get_type(),
-                          (*c_iter)->get_value(),
-                          false)) {
-      need_static_constructor = true;
-    }
-  }
-
-  if (need_static_constructor) {
-    print_const_constructor(f_consts, consts);
-  }
-
-  scope_down(f_consts);
-  end_csharp_namespace(f_consts);
-  f_consts.close();
-}
-
-void t_csharp_generator::print_const_def_value(std::ofstream& out,
-                                               string name,
-                                               t_type* type,
-                                               t_const_value* value) {
-  if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    prepare_member_name_mapping((t_struct*)type);
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_field* field = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field = (*f_iter);
-        }
-      }
-      if (field == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      t_type* field_type = field->get_type();
-      string val = render_const_value(out, name, field_type, v_iter->second);
-      indent(out) << name << "." << prop_name(field) << " = " << val << ";" << endl;
-    }
-    cleanup_member_name_mapping((t_struct*)type);
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, name, ktype, v_iter->first);
-      string val = render_const_value(out, name, vtype, v_iter->second);
-      indent(out) << name << "[" << key << "]"
-                  << " = " << val << ";" << endl;
-    }
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      indent(out) << name << ".Add(" << val << ");" << endl;
-    }
-  }
-}
-
-void t_csharp_generator::print_const_constructor(std::ofstream& out, std::vector<t_const*> consts) {
-  indent(out) << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()"
-              << endl;
-  scope_up(out);
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    string name = (*c_iter)->get_name();
-    t_type* type = (*c_iter)->get_type();
-    t_const_value* value = (*c_iter)->get_value();
-
-    print_const_def_value(out, name, type, value);
-  }
-  scope_down(out);
-}
-
-// it seems like all that methods that call this are using in_static to be the opposite of what it
-// would imply
-bool t_csharp_generator::print_const_value(std::ofstream& out,
-                                           string name,
-                                           t_type* type,
-                                           t_const_value* value,
-                                           bool in_static,
-                                           bool defval,
-                                           bool needtype) {
-  indent(out);
-  bool need_static_construction = !in_static;
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
-
-  if (!defval || needtype) {
-    out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ")
-        << type_name(type) << " ";
-  }
-  if (type->is_base_type()) {
-    string v2 = render_const_value(out, name, type, value);
-    out << name << " = " << v2 << ";" << endl;
-    need_static_construction = false;
-  } else if (type->is_enum()) {
-    out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name()
-        << ";" << endl;
-    need_static_construction = false;
-  } else if (type->is_struct() || type->is_xception()) {
-    out << name << " = new " << type_name(type) << "();" << endl;
-  } else if (type->is_map()) {
-    out << name << " = new " << type_name(type, true, true) << "();" << endl;
-  } else if (type->is_list() || type->is_set()) {
-    out << name << " = new " << type_name(type) << "();" << endl;
-  }
-
-  if (defval && !type->is_base_type() && !type->is_enum()) {
-    print_const_def_value(out, name, type, value);
-  }
-
-  return need_static_construction;
-}
-
-std::string t_csharp_generator::render_const_value(ofstream& out,
-                                                   string name,
-                                                   t_type* type,
-                                                   t_const_value* value) {
-  (void)name;
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << type->get_name() << "." << value->get_identifier_name();
-  } else {
-    string t = tmp("tmp");
-    print_const_value(out, t, type, value, true, true, true);
-    render << t;
-  }
-
-  return render.str();
-}
-
-void t_csharp_generator::generate_struct(t_struct* tstruct) {
-  if (union_ && tstruct->is_union()) {
-    generate_csharp_union(tstruct);
-  } else {
-    generate_csharp_struct(tstruct, false);
-  }
-}
-
-void t_csharp_generator::generate_xception(t_struct* txception) {
-  generate_csharp_struct(txception, true);
-}
-
-void t_csharp_generator::generate_csharp_struct(t_struct* tstruct, bool is_exception) {
-  string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs";
-  ofstream f_struct;
-
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
-
-  generate_csharp_struct_definition(f_struct, tstruct, is_exception);
-
-  f_struct.close();
-}
-
-void t_csharp_generator::generate_csharp_struct_definition(ofstream& out,
-                                                           t_struct* tstruct,
-                                                           bool is_exception,
-                                                           bool in_class,
-                                                           bool is_result) {
-
-  if (!in_class) {
-    start_csharp_namespace(out);
-  }
-
-  out << endl;
-
-  generate_csharp_doc(out, tstruct);
-  prepare_member_name_mapping(tstruct);
-
-  indent(out) << "#if !SILVERLIGHT" << endl;
-  indent(out) << "[Serializable]" << endl;
-  indent(out) << "#endif" << endl;
-  if ((serialize_ || wcf_) && !is_exception) {
-    indent(out) << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]"
-                << endl; // do not make exception classes directly WCF serializable, we provide a
-                         // separate "fault" for that
-  }
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-
-  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class "
-              << normalize_name(tstruct->get_name()) << " : ";
-
-  if (is_exception) {
-    out << "TException, ";
-  }
-  out << "TBase";
-
-  out << endl;
-
-  scope_up(out);
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  // make private members with public Properties
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    // if the field is requied, then we use auto-properties
-    if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) {
-      indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
-    }
-  }
-  out << endl;
-
-  bool has_non_required_fields = false;
-  bool has_non_required_default_value_fields = false;
-  bool has_required_fields = false;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_csharp_doc(out, *m_iter);
-    generate_property(out, *m_iter, true, true);
-    bool is_required = field_is_required((*m_iter));
-    bool has_default = field_has_default((*m_iter));
-    if (is_required) {
-      has_required_fields = true;
-    } else {
-      if (has_default) {
-        has_non_required_default_value_fields = true;
-      }
-      has_non_required_fields = true;
-    }
-  }
-
-  bool generate_isset = (nullable_ && has_non_required_default_value_fields)
-                        || (!nullable_ && has_non_required_fields);
-  if (generate_isset) {
-    out << endl;
-    if (serialize_ || wcf_) {
-      out << indent() << "[XmlIgnore] // XmlSerializer" << endl << indent()
-          << "[DataMember(Order = 1)]  // XmlObjectSerializer, DataContractJsonSerializer, etc."
-          << endl;
-    }
-    out << indent() << "public Isset __isset;" << endl << indent() << "#if !SILVERLIGHT" << endl
-        << indent() << "[Serializable]" << endl << indent() << "#endif" << endl;
-    if (serialize_ || wcf_) {
-      indent(out) << "[DataContract]" << endl;
-    }
-    indent(out) << "public struct Isset {" << endl;
-    indent_up();
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      bool is_required = field_is_required((*m_iter));
-      bool has_default = field_has_default((*m_iter));
-      // if it is required, don't need Isset for that variable
-      // if it is not required, if it has a default value, we need to generate Isset
-      // if we are not nullable, then we generate Isset
-      if (!is_required && (!nullable_ || has_default)) {
-        if (serialize_ || wcf_) {
-          indent(out) << "[DataMember]" << endl;
-        }
-        indent(out) << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl;
-      }
-    }
-
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    if (generate_isset && (serialize_ || wcf_)) {
-      indent(out) << "#region XmlSerializer support" << endl << endl;
-
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        bool is_required = field_is_required((*m_iter));
-        bool has_default = field_has_default((*m_iter));
-        // if it is required, don't need Isset for that variable
-        // if it is not required, if it has a default value, we need to generate Isset
-        // if we are not nullable, then we generate Isset
-        if (!is_required && (!nullable_ || has_default)) {
-          indent(out) << "public bool ShouldSerialize" << prop_name((*m_iter)) << "()" << endl;
-          indent(out) << "{" << endl;
-          indent_up();
-          indent(out) << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl;
-          indent_down();
-          indent(out) << "}" << endl << endl;
-        }
-      }
-
-      indent(out) << "#endregion XmlSerializer support" << endl << endl;
-    }
-  }
-
-  // We always want a default, no argument constructor for Reading
-  indent(out) << "public " << normalize_name(tstruct->get_name()) << "() {" << endl;
-  indent_up();
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
-    if ((*m_iter)->get_value() != NULL) {
-      if (field_is_required((*m_iter))) {
-        print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true);
-      } else {
-        print_const_value(out,
-                          "this._" + (*m_iter)->get_name(),
-                          t,
-                          (*m_iter)->get_value(),
-                          true,
-                          true);
-        // Optionals with defaults are marked set
-        indent(out) << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;"
-                    << endl;
-      }
-    }
-  }
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  if (has_required_fields) {
-    indent(out) << "public " << tstruct->get_name() << "(";
-    bool first = true;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (field_is_required((*m_iter))) {
-        if (first) {
-          first = false;
-        } else {
-          out << ", ";
-        }
-        out << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
-      }
-    }
-    out << ") : this() {" << endl;
-    indent_up();
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (field_is_required((*m_iter))) {
-        indent(out) << "this." << prop_name((*m_iter)) << " = " << (*m_iter)->get_name() << ";"
-                    << endl;
-      }
-    }
-
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-
-  generate_csharp_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_csharp_struct_result_writer(out, tstruct);
-  } else {
-    generate_csharp_struct_writer(out, tstruct);
-  }
-  if (hashcode_) {
-    generate_csharp_struct_equals(out, tstruct);
-    generate_csharp_struct_hashcode(out, tstruct);
-  }
-  generate_csharp_struct_tostring(out, tstruct);
-  scope_down(out);
-  out << endl;
-
-  // generate a corresponding WCF fault to wrap the exception
-  if ((serialize_ || wcf_) && is_exception) {
-    generate_csharp_wcffault(out, tstruct);
-  }
-
-  cleanup_member_name_mapping(tstruct);
-  if (!in_class) {
-    end_csharp_namespace(out);
-  }
-}
-
-void t_csharp_generator::generate_csharp_wcffault(ofstream& out, t_struct* tstruct) {
-  out << endl;
-  indent(out) << "#if !SILVERLIGHT" << endl;
-  indent(out) << "[Serializable]" << endl;
-  indent(out) << "#endif" << endl;
-  indent(out) << "[DataContract]" << endl;
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-
-  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name()
-              << "Fault" << endl;
-
-  scope_up(out);
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  // make private members with public Properties
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
-  }
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_property(out, *m_iter, true, false);
-  }
-
-  scope_down(out);
-  out << endl;
-}
-
-void t_csharp_generator::generate_csharp_struct_reader(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public void Read (TProtocol iprot)" << endl;
-  scope_up(out);
-
-  out << indent() << "iprot.IncrementRecursionDepth();" << endl;
-  out << indent() << "try" << endl;
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Required variables aren't in __isset, so we need tmp vars to check them
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (field_is_required((*f_iter))) {
-      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
-    }
-  }
-
-  indent(out) << "TField field;" << endl << indent() << "iprot.ReadStructBegin();" << endl;
-
-  indent(out) << "while (true)" << endl;
-  scope_up(out);
-
-  indent(out) << "field = iprot.ReadFieldBegin();" << endl;
-
-  indent(out) << "if (field.Type == TType.Stop) { " << endl;
-  indent_up();
-  indent(out) << "break;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent(out) << "switch (field.ID)" << endl;
-
-  scope_up(out);
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool is_required = field_is_required((*f_iter));
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
-    indent_up();
-    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-
-    generate_deserialize_field(out, *f_iter);
-    if (is_required) {
-      indent(out) << "isset_" << (*f_iter)->get_name() << " = true;" << endl;
-    }
-
-    indent_down();
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
-        << endl << indent() << "}" << endl << indent() << "break;" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default: " << endl;
-  indent_up();
-  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl;
-  indent(out) << "break;" << endl;
-  indent_down();
-
-  scope_down(out);
-
-  indent(out) << "iprot.ReadFieldEnd();" << endl;
-
-  scope_down(out);
-
-  indent(out) << "iprot.ReadStructEnd();" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (field_is_required((*f_iter))) {
-      indent(out) << "if (!isset_" << (*f_iter)->get_name() << ")" << endl;
-      indent_up();
-      indent(out) << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl;
-      indent_down();
-    }
-  }
-
-  scope_down(out);
-  out << indent() << "finally" << endl;
-  scope_up(out);
-  out << indent() << "iprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-
-  indent_down();
-
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_csharp_struct_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public void Write(TProtocol oprot) {" << endl;
-  indent_up();
-  
-  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
-  out << indent() << "try" << endl;
-  scope_up(out);
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl;
-  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
-
-  if (fields.size() > 0) {
-    indent(out) << "TField field = new TField();" << endl;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      bool is_required = field_is_required((*f_iter));
-      bool has_default = field_has_default((*f_iter));
-      if (nullable_ && !has_default && !is_required) {
-        indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl;
-        indent_up();
-      } else if (!is_required) {
-        bool null_allowed = type_can_be_null((*f_iter)->get_type());
-        if (null_allowed) {
-          indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset."
-                      << normalize_name((*f_iter)->get_name()) << ") {" << endl;
-          indent_up();
-        } else {
-          indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
-          indent_up();
-        }
-      }
-      indent(out) << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl;
-      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
-      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl;
-      indent(out) << "oprot.WriteFieldBegin(field);" << endl;
-
-      generate_serialize_field(out, *f_iter);
-
-      indent(out) << "oprot.WriteFieldEnd();" << endl;
-      if (!is_required) {
-        indent_down();
-        indent(out) << "}" << endl;
-      }
-    }
-  }
-
-  indent(out) << "oprot.WriteFieldStop();" << endl;
-  indent(out) << "oprot.WriteStructEnd();" << endl;
-
-  scope_down(out);
-  out << indent() << "finally" << endl;
-  scope_up(out);
-  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-
-  indent_down();
-  
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_csharp_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public void Write(TProtocol oprot) {" << endl;
-  indent_up();
-
-  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
-  out << indent() << "try" << endl;
-  scope_up(out);
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl;
-  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
-
-  if (fields.size() > 0) {
-    indent(out) << "TField field = new TField();" << endl;
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-        out << endl << indent() << "if ";
-      } else {
-        out << " else if ";
-      }
-
-      if (nullable_) {
-        out << "(this." << prop_name((*f_iter)) << " != null) {" << endl;
-      } else {
-        out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
-      }
-      indent_up();
-
-      bool null_allowed = !nullable_ && type_can_be_null((*f_iter)->get_type());
-      if (null_allowed) {
-        indent(out) << "if (" << prop_name(*f_iter) << " != null) {" << endl;
-        indent_up();
-      }
-
-      indent(out) << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl;
-      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
-      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl;
-      indent(out) << "oprot.WriteFieldBegin(field);" << endl;
-
-      generate_serialize_field(out, *f_iter);
-
-      indent(out) << "oprot.WriteFieldEnd();" << endl;
-
-      if (null_allowed) {
-        indent_down();
-        indent(out) << "}" << endl;
-      }
-
-      indent_down();
-      indent(out) << "}";
-    }
-  }
-
-  out << endl << indent() << "oprot.WriteFieldStop();" << endl << indent()
-      << "oprot.WriteStructEnd();" << endl;
-
-  scope_down(out);
-  out << indent() << "finally" << endl;
-  scope_up(out);
-  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-
-  indent_down();
-
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_csharp_struct_tostring(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public override string ToString() {" << endl;
-  indent_up();
-
-  indent(out) << "StringBuilder __sb = new StringBuilder(\"" << tstruct->get_name() << "(\");"
-              << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  bool useFirstFlag = false;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (!field_is_required((*f_iter))) {
-      indent(out) << "bool __first = true;" << endl;
-      useFirstFlag = true;
-    }
-    break;
-  }
-
-  bool had_required = false; // set to true after first required field has been processed
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool is_required = field_is_required((*f_iter));
-    bool has_default = field_has_default((*f_iter));
-    if (nullable_ && !has_default && !is_required) {
-      indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl;
-      indent_up();
-    } else if (!is_required) {
-      bool null_allowed = type_can_be_null((*f_iter)->get_type());
-      if (null_allowed) {
-        indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset."
-                    << normalize_name((*f_iter)->get_name()) << ") {" << endl;
-        indent_up();
-      } else {
-        indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
-        indent_up();
-      }
-    }
-
-    if (useFirstFlag && (!had_required)) {
-      indent(out) << "if(!__first) { __sb.Append(\", \"); }" << endl;
-      if (!is_required) {
-        indent(out) << "__first = false;" << endl;
-      }
-      indent(out) << "__sb.Append(\"" << prop_name((*f_iter)) << ": \");" << endl;
-    } else {
-      indent(out) << "__sb.Append(\", " << prop_name((*f_iter)) << ": \");" << endl;
-    }
-
-    t_type* ttype = (*f_iter)->get_type();
-    if (ttype->is_xception() || ttype->is_struct()) {
-      indent(out) << "__sb.Append(" << prop_name((*f_iter))
-                  << "== null ? \"<null>\" : " << prop_name((*f_iter)) << ".ToString());" << endl;
-    } else {
-      indent(out) << "__sb.Append(" << prop_name((*f_iter)) << ");" << endl;
-    }
-
-    if (!is_required) {
-      indent_down();
-      indent(out) << "}" << endl;
-    } else {
-      had_required = true; // now __first must be false, so we don't need to check it anymore
-    }
-  }
-
-  indent(out) << "__sb.Append(\")\");" << endl;
-  indent(out) << "return __sb.ToString();" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_csharp_union(t_struct* tunion) {
-  string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs";
-  ofstream f_union;
-
-  f_union.open(f_union_name.c_str());
-
-  f_union << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
-
-  generate_csharp_union_definition(f_union, tunion);
-
-  f_union.close();
-}
-
-void t_csharp_generator::generate_csharp_union_definition(std::ofstream& out, t_struct* tunion) {
-  // Let's define the class first
-  start_csharp_namespace(out);
-
-  indent(out) << "public abstract partial class " << tunion->get_name() << " : TAbstractBase {"
-              << endl;
-
-  indent_up();
-
-  indent(out) << "public abstract void Write(TProtocol protocol);" << endl;
-  indent(out) << "public readonly bool Isset;" << endl;
-  indent(out) << "public abstract object Data { get; }" << endl;
-
-  indent(out) << "protected " << tunion->get_name() << "(bool isset) {" << endl;
-  indent_up();
-  indent(out) << "Isset = isset;" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  indent(out) << "public class ___undefined : " << tunion->get_name() << " {" << endl;
-  indent_up();
-
-  indent(out) << "public override object Data { get { return null; } }" << endl;
-
-  indent(out) << "public ___undefined() : base(false) {}" << endl << endl;
-
-  indent(out) << "public override void Write(TProtocol protocol) {" << endl;
-  indent_up();
-  indent(out) << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist "
-                 "an union type which is not set.\");" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  const vector<t_field*>& fields = tunion->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    generate_csharp_union_class(out, tunion, (*f_iter));
-  }
-
-  generate_csharp_union_reader(out, tunion);
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  end_csharp_namespace(out);
-}
-
-void t_csharp_generator::generate_csharp_union_class(std::ofstream& out,
-                                                     t_struct* tunion,
-                                                     t_field* tfield) {
-  indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {"
-              << endl;
-  indent_up();
-  indent(out) << "private " << type_name(tfield->get_type()) << " _data;" << endl;
-  indent(out) << "public override object Data { get { return _data; } }" << endl;
-  indent(out) << "public " << tfield->get_name() << "(" << type_name(tfield->get_type())
-              << " data) : base(true) {" << endl;
-  indent_up();
-  indent(out) << "this._data = data;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-  indent(out) << "public override void Write(TProtocol oprot) {" << endl;
-  indent_up();
-
-  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
-  out << indent() << "try" << endl;
-  scope_up(out);
-
-  indent(out) << "TStruct struc = new TStruct(\"" << tunion->get_name() << "\");" << endl;
-  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
-
-  indent(out) << "TField field = new TField();" << endl;
-  indent(out) << "field.Name = \"" << tfield->get_name() << "\";" << endl;
-  indent(out) << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl;
-  indent(out) << "field.ID = " << tfield->get_key() << ";" << endl;
-  indent(out) << "oprot.WriteFieldBegin(field);" << endl;
-
-  generate_serialize_field(out, tfield, "_data", true, true);
-
-  indent(out) << "oprot.WriteFieldEnd();" << endl;
-  indent(out) << "oprot.WriteFieldStop();" << endl;
-  indent(out) << "oprot.WriteStructEnd();" << endl;
-  indent_down();
-
-  scope_down(out);
-  out << indent() << "finally" << endl;
-  scope_up(out);
-  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_csharp_struct_equals(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public override bool Equals(object that) {" << endl;
-  indent_up();
-
-  indent(out) << "var other = that as " << type_name(tstruct) << ";" << endl;
-  indent(out) << "if (other == null) return false;" << endl;
-  indent(out) << "if (ReferenceEquals(this, other)) return true;" << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  bool first = true;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      indent(out) << "return ";
-      indent_up();
-    } else {
-      out << endl;
-      indent(out) << "&& ";
-    }
-    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) {
-      out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset."
-          << normalize_name((*f_iter)->get_name()) << ") && ((!__isset."
-          << normalize_name((*f_iter)->get_name()) << ") || (";
-    }
-    t_type* ttype = (*f_iter)->get_type();
-    if (ttype->is_container() || (ttype->is_base_type() && (((t_base_type*)ttype)->is_binary()))) {
-      out << "TCollections.Equals(";
-    } else {
-      out << "System.Object.Equals(";
-    }
-    out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")";
-    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) {
-      out << ")))";
-    }
-  }
-  if (first) {
-    indent(out) << "return true;" << endl;
-  } else {
-    out << ";" << endl;
-    indent_down();
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_csharp_struct_hashcode(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public override int GetHashCode() {" << endl;
-  indent_up();
-
-  indent(out) << "int hashcode = 0;" << endl;
-  indent(out) << "unchecked {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_type* ttype = (*f_iter)->get_type();
-    indent(out) << "hashcode = (hashcode * 397) ^ ";
-    if (field_is_required((*f_iter))) {
-      out << "(";
-    } else if (nullable_) {
-      out << "(" << prop_name((*f_iter)) << " == null ? 0 : ";
-    } else {
-      out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : ";
-    }
-    if (ttype->is_container()) {
-      out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))";
-    } else {
-      out << "(" << prop_name((*f_iter)) << ".GetHashCode())";
-    }
-    out << ");" << endl;
-  }
-
-  indent_down();
-  indent(out) << "}" << endl;
-  indent(out) << "return hashcode;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_service(t_service* tservice) {
-  string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
-
-  start_csharp_namespace(f_service_);
-
-  indent(f_service_) << "public partial class " << normalize_name(service_name_) << " {" << endl;
-  indent_up();
-
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-
-  indent_down();
-
-  indent(f_service_) << "}" << endl;
-  end_csharp_namespace(f_service_);
-  f_service_.close();
-}
-
-void t_csharp_generator::generate_service_interface(t_service* tservice) {
-  generate_separate_service_interfaces(tservice);
-}
-
-void t_csharp_generator::generate_separate_service_interfaces(t_service* tservice) {
-  generate_sync_service_interface(tservice);
-
-  if (async_) {
-    generate_async_service_interface(tservice);
-  }
-
-  generate_combined_service_interface(tservice);
-}
-
-void t_csharp_generator::generate_sync_service_interface(t_service* tservice) {
-  string extends = "";
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_iface = " : " + extends + ".ISync";
-  }
-
-  generate_csharp_doc(f_service_, tservice);
-
-  if (wcf_) {
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
-  }
-  indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl;
-
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_csharp_doc(f_service_, *f_iter);
-
-    // if we're using WCF, add the corresponding attributes
-    if (wcf_) {
-      indent(f_service_) << "[OperationContract]" << endl;
-
-      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        indent(f_service_) << "[FaultContract(typeof("
-          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
-      }
-    }
-
-    indent(f_service_) << function_signature(*f_iter) << ";" << endl;
-  }
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_async_service_interface(t_service* tservice) {
-  string extends = "";
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_iface = " : " + extends + ".IAsync";
-  }
-
-  generate_csharp_doc(f_service_, tservice);
-
-  if (wcf_) {
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
-  }
-  indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl;
-
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_csharp_doc(f_service_, *f_iter);
-
-    // if we're using WCF, add the corresponding attributes
-    if (wcf_) {
-      indent(f_service_) << "[OperationContract]" << endl;
-
-      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        indent(f_service_) << "[FaultContract(typeof("
-          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
-      }
-    }
-
-    indent(f_service_) << function_signature_async(*f_iter) << ";" << endl;
-  }
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_combined_service_interface(t_service* tservice) {
-  string extends_iface = " : ISync";
-
-  if (async_) {
-    extends_iface += ", IAsync";
-  }
-
-  generate_csharp_doc(f_service_, tservice);
-
-  if (wcf_) {
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
-  }
-
-  indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl;
-
-  indent_up();
-
-  // We need to generate extra old style async methods for silverlight. Since
-  // this isn't something you'd want to implement server-side, just put them into
-  // the main Iface interface.
-  generate_silverlight_async_methods(tservice);
-
-  indent_down();
-
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_silverlight_async_methods(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_csharp_doc(f_service_, *f_iter);
-
-    // For backwards compatibility, include the Begin_, End_ methods if we're generating
-    // with the async flag. I'm not sure this is necessary, so someone with more knowledge
-    // can maybe remove these checks if they know it's safe.
-    if (!async_) {
-      indent(f_service_) << "#if SILVERLIGHT" << endl;
-    }
-
-    indent(f_service_) << function_signature_async_begin(*f_iter, "Begin_") << ";" << endl;
-    indent(f_service_) << function_signature_async_end(*f_iter, "End_") << ";" << endl;
-
-    if (!async_) {
-      indent(f_service_) << "#endif" << endl;
-    }
-  }
-}
-
-void t_csharp_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_csharp_struct_definition(f_service_, ts, false, true);
-    generate_function_helpers(*f_iter);
-  }
-}
-
-void t_csharp_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_client = extends + ".Client, ";
-  } else {
-    extends_client = "IDisposable, ";
-  }
-
-  generate_csharp_doc(f_service_, tservice);
-
-  indent(f_service_) << "public class Client : " << extends_client << "Iface {" << endl;
-  indent_up();
-  indent(f_service_) << "public Client(TProtocol prot) : this(prot, prot)" << endl;
-  scope_up(f_service_);
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)";
-  if (!extends.empty()) {
-    f_service_ << " : base(iprot, oprot)";
-  }
-  f_service_ << endl;
-
-  scope_up(f_service_);
-  if (extends.empty()) {
-    f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl;
-  }
-  scope_down(f_service_);
-
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent()
-               << "protected TProtocol oprot_;" << endl << indent() << "protected int seqid_;"
-               << endl << endl;
-
-    f_service_ << indent() << "public TProtocol InputProtocol" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "get { return iprot_; }" << endl;
-    scope_down(f_service_);
-
-    f_service_ << indent() << "public TProtocol OutputProtocol" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "get { return oprot_; }" << endl;
-    scope_down(f_service_);
-    f_service_ << endl << endl;
-
-    indent(f_service_) << "#region \" IDisposable Support \"" << endl;
-    indent(f_service_) << "private bool _IsDisposed;" << endl << endl;
-    indent(f_service_) << "// IDisposable" << endl;
-    indent(f_service_) << "public void Dispose()" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "Dispose(true);" << endl;
-    scope_down(f_service_);
-    indent(f_service_) << endl << endl;
-    indent(f_service_) << "protected virtual void Dispose(bool disposing)" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "if (!_IsDisposed)" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "if (disposing)" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "if (iprot_ != null)" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "((IDisposable)iprot_).Dispose();" << endl;
-    scope_down(f_service_);
-    indent(f_service_) << "if (oprot_ != null)" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "((IDisposable)oprot_).Dispose();" << endl;
-    scope_down(f_service_);
-    scope_down(f_service_);
-    scope_down(f_service_);
-    indent(f_service_) << "_IsDisposed = true;" << endl;
-    scope_down(f_service_);
-    indent(f_service_) << "#endregion" << endl;
-    f_service_ << endl << endl;
-  }
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-
-    indent(f_service_) << endl;
-
-    if (!async_) {
-      indent(f_service_) << "#if SILVERLIGHT" << endl;
-    }
-    // Begin_
-    indent(f_service_) << "public " << function_signature_async_begin(*f_iter, "Begin_") << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return "
-                       << "send_" << funname << "(callback, state";
-
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    prepare_member_name_mapping(arg_struct);
-
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << ", ";
-      f_service_ << normalize_name((*fld_iter)->get_name());
-    }
-    f_service_ << ");" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    // End
-    indent(f_service_) << "public " << function_signature_async_end(*f_iter, "End_") << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "oprot_.Transport.EndFlush(asyncResult);" << endl;
-    if (!(*f_iter)->is_oneway()) {
-      f_service_ << indent();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
-      }
-      f_service_ << "recv_" << funname << "();" << endl;
-    }
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    // async
-    bool first;
-    if (async_) {
-      indent(f_service_) << "public async " << function_signature_async(*f_iter, "") << endl;
-      scope_up(f_service_);
-
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << type_name((*f_iter)->get_returntype()) << " retval;" << endl;
-        indent(f_service_) << "retval = ";
-      } else {
-        indent(f_service_);
-      }
-      f_service_ << "await Task.Run(() =>" << endl;
-      scope_up(f_service_);
-      indent(f_service_);
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
-      }
-      f_service_ << funname << "(";
-      first = true;
-      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-        if (first) {
-          first = false;
-        } else {
-          f_service_ << ", ";
-        }
-        f_service_ << (*fld_iter)->get_name();
-      }
-      f_service_ << ");" << endl;
-      indent_down();
-      indent(f_service_) << "});" << endl;
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "return retval;" << endl;
-      }
-      scope_down(f_service_);
-      f_service_ << endl;
-    }
-
-    if (!async_) {
-      indent(f_service_) << "#endif" << endl << endl;
-    }
-
-    // "Normal" Synchronous invoke
-    generate_csharp_doc(f_service_, *f_iter);
-    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
-    scope_up(f_service_);
-
-    if (!async_) {
-      indent(f_service_) << "#if !SILVERLIGHT" << endl;
-      indent(f_service_) << "send_" << funname << "(";
-
-      first = true;
-      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-        if (first) {
-          first = false;
-        } else {
-          f_service_ << ", ";
-        }
-        f_service_ << normalize_name((*fld_iter)->get_name());
-      }
-      f_service_ << ");" << endl;
-
-      if (!(*f_iter)->is_oneway()) {
-        f_service_ << indent();
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          f_service_ << "return ";
-        }
-        f_service_ << "recv_" << funname << "();" << endl;
-      }
-      f_service_ << endl;
-
-      indent(f_service_) << "#else" << endl;
-    }
-
-    // Silverlight synchronous invoke
-    indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null";
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << ", " << normalize_name((*fld_iter)->get_name());
-    }
-    f_service_ << ");" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_service_ << indent();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
-      }
-      f_service_ << "End_" << funname << "(asyncResult);" << endl;
-    }
-    f_service_ << endl;
-
-    if (!async_) {
-      indent(f_service_) << "#endif" << endl;
-    }
-    scope_down(f_service_);
-
-    // Send
-    t_function send_function(g_type_void,
-                             string("send_") + (*f_iter)->get_name(),
-                             (*f_iter)->get_arglist());
-
-    string argsname = (*f_iter)->get_name() + "_args";
-
-    if (!async_) {
-      indent(f_service_) << "#if SILVERLIGHT" << endl;
-    }
-    indent(f_service_) << "public " << function_signature_async_begin(&send_function) << endl;
-    if (!async_) {
-      indent(f_service_) << "#else" << endl;
-      indent(f_service_) << "public " << function_signature(&send_function) << endl;
-      indent(f_service_) << "#endif" << endl;
-    }
-    scope_up(f_service_);
-
-    f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", "
-               << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call")
-               << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname
-               << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args." << prop_name(*fld_iter) << " = "
-                 << normalize_name((*fld_iter)->get_name()) << ";" << endl;
-    }
-
-    f_service_ << indent() << "args.Write(oprot_);" << endl << indent()
-               << "oprot_.WriteMessageEnd();" << endl;
-    ;
-
-    if (!async_) {
-      indent(f_service_) << "#if SILVERLIGHT" << endl;
-    }
-    indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl;
-    if (!async_) {
-      indent(f_service_) << "#else" << endl;
-      indent(f_service_) << "oprot_.Transport.Flush();" << endl;
-      indent(f_service_) << "#endif" << endl;
-    }
-
-    cleanup_member_name_mapping(arg_struct);
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      string resultname = (*f_iter)->get_name() + "_result";
-
-      t_struct noargs(program_);
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs,
-                               (*f_iter)->get_xceptions());
-      indent(f_service_) << "public " << function_signature(&recv_function) << endl;
-      scope_up(f_service_);
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      prepare_member_name_mapping(xs, xs->get_members(), resultname);
-
-      f_service_ << indent() << "TMessage msg = iprot_.ReadMessageBegin();" << endl << indent()
-                 << "if (msg.Type == TMessageType.Exception) {" << endl;
-      indent_up();
-      f_service_ << indent() << "TApplicationException x = TApplicationException.Read(iprot_);"
-                 << endl << indent() << "iprot_.ReadMessageEnd();" << endl << indent() << "throw x;"
-                 << endl;
-      indent_down();
-      f_service_ << indent() << "}" << endl << indent() << resultname << " result = new "
-                 << resultname << "();" << endl << indent() << "result.Read(iprot_);" << endl
-                 << indent() << "iprot_.ReadMessageEnd();" << endl;
-
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        if (nullable_) {
-          if (type_can_be_null((*f_iter)->get_returntype())) {
-            f_service_ << indent() << "if (result.Success != null) {" << endl << indent()
-                       << "  return result.Success;" << endl << indent() << "}" << endl;
-          } else {
-            f_service_ << indent() << "if (result.Success.HasValue) {" << endl << indent()
-                       << "  return result.Success.Value;" << endl << indent() << "}" << endl;
-          }
-        } else {
-          f_service_ << indent() << "if (result.__isset.success) {" << endl << indent()
-                     << "  return result.Success;" << endl << indent() << "}" << endl;
-        }
-      }
-
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        if (nullable_) {
-          f_service_ << indent() << "if (result." << prop_name(*x_iter) << " != null) {" << endl
-                     << indent() << "  throw result." << prop_name(*x_iter) << ";" << endl
-                     << indent() << "}" << endl;
-        } else {
-          f_service_ << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name())
-                     << ") {" << endl << indent() << "  throw result." << prop_name(*x_iter) << ";"
-                     << endl << indent() << "}" << endl;
-        }
-      }
-
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "return;" << endl;
-      } else {
-        f_service_ << indent()
-                   << "throw new "
-                      "TApplicationException(TApplicationException.ExceptionType.MissingResult, \""
-                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
-      }
-
-      cleanup_member_name_mapping((*f_iter)->get_xceptions());
-      scope_down(f_service_);
-      f_service_ << endl;
-    }
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl;
-}
-
-void t_csharp_generator::generate_service_server(t_service* tservice) {
-  if (async_) {
-    generate_service_server_async(tservice);
-    generate_service_server_sync(tservice);
-  }
-  else {
-    generate_service_server_sync(tservice);
-  }
-}
-
-void t_csharp_generator::generate_service_server_sync(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_processor = extends + ".Processor, ";
-  }
-
-  indent(f_service_) << "public class Processor : " << extends_processor << "TProcessor {" << endl;
-  indent_up();
-
-  indent(f_service_) << "public Processor(ISync iface)";
-
-  if (!extends.empty()) {
-    f_service_ << " : base(iface)";
-  }
-  f_service_ << endl;
-  scope_up(f_service_);
-  f_service_ << indent() << "iface_ = iface;" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name()
-      << "\"] = " << (*f_iter)->get_name() << "_Process;" << endl;
-  }
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_
-      << indent()
-      << "protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);"
-      << endl;
-  }
-
-  f_service_ << indent() << "private ISync iface_;" << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new "
-      "Dictionary<string, ProcessFunction>();" << endl;
-  }
-
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    indent(f_service_) << "public bool Process(TProtocol iprot, TProtocol oprot)" << endl;
-  }
-  else {
-    indent(f_service_) << "public new bool Process(TProtocol iprot, TProtocol oprot)" << endl;
-  }
-  scope_up(f_service_);
-
-  f_service_ << indent() << "try" << endl;
-  scope_up(f_service_);
-
-  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl;
-
-  f_service_
-    << indent() << "ProcessFunction fn;" << endl << indent()
-    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {"
-    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent()
-    << "  iprot.ReadMessageEnd();" << endl << indent()
-    << "  TApplicationException x = new TApplicationException "
-    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + "
-    "msg.Name + \"'\");" << endl << indent()
-    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));"
-    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();"
-    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;"
-    << endl << indent() << "}" << endl << indent() << "fn(msg.SeqID, iprot, oprot);" << endl;
-
-  scope_down(f_service_);
-
-  f_service_ << indent() << "catch (IOException)" << endl;
-  scope_up(f_service_);
-  f_service_ << indent() << "return false;" << endl;
-  scope_down(f_service_);
-
-  f_service_ << indent() << "return true;" << endl;
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_service_server_async(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_processor = extends + ".Processor, ";
-  }
-
-  indent(f_service_) << "public class AsyncProcessor : " << extends_processor << "TAsyncProcessor {" << endl;
-  indent_up();
-
-  indent(f_service_) << "public AsyncProcessor(IAsync iface)";
-  if (!extends.empty()) {
-    f_service_ << " : base(iface)";
-  }
-  f_service_ << endl;
-  scope_up(f_service_);
-  f_service_ << indent() << "iface_ = iface;" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name()
-      << "\"] = " << (*f_iter)->get_name() << "_ProcessAsync;" << endl;
-  }
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_
-      << indent()
-      << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);"
-      << endl;
-  }
-
-  f_service_ << indent() << "private IAsync iface_;" << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new "
-      "Dictionary<string, ProcessFunction>();" << endl;
-  }
-
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    indent(f_service_) << "public async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl;
-  }
-  else {
-    indent(f_service_) << "public new async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl;
-  }
-  scope_up(f_service_);
-
-  f_service_ << indent() << "try" << endl;
-  scope_up(f_service_);
-
-  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl;
-
-  f_service_
-    << indent() << "ProcessFunction fn;" << endl << indent()
-    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {"
-    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent()
-    << "  iprot.ReadMessageEnd();" << endl << indent()
-    << "  TApplicationException x = new TApplicationException "
-    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + "
-    "msg.Name + \"'\");" << endl << indent()
-    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));"
-    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();"
-    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;"
-    << endl << indent() << "}" << endl << indent() << "await fn(msg.SeqID, iprot, oprot);" << endl;
-
-  scope_down(f_service_);
-
-  f_service_ << indent() << "catch (IOException)" << endl;
-  scope_up(f_service_);
-  f_service_ << indent() << "return false;" << endl;
-  scope_down(f_service_);
-
-  f_service_ << indent() << "return true;" << endl;
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function_async(tservice, *f_iter);
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl << endl;
-}
-
-void t_csharp_generator::generate_function_helpers(t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  t_struct result(program_, tfunction->get_name() + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_csharp_struct_definition(f_service_, &result, false, true, true);
-}
-
-void t_csharp_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  indent(f_service_) << "public void " << tfunction->get_name()
-                     << "_Process(int seqid, TProtocol iprot, TProtocol oprot)" << endl;
-  scope_up(f_service_);
-
-  string argsname = tfunction->get_name() + "_args";
-  string resultname = tfunction->get_name() + "_result";
-
-  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl
-             << indent() << "args.Read(iprot);" << endl
-             << indent() << "iprot.ReadMessageEnd();" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
-  }
-
-  f_service_ << indent() << "try" << endl
-             << indent() << "{" << endl;
-  indent_up();
-
-  if (xceptions.size() > 0) {
-    f_service_ << indent() << "try" << endl
-               << indent() << "{" << endl;
-    indent_up();
-  }
-
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_ << indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "result.Success = ";
-  }
-  f_service_ << "iface_." << normalize_name(tfunction->get_name()) << "(";
-  bool first = true;
-  prepare_member_name_mapping(arg_struct);
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_service_ << ", ";
-    }
-    f_service_ << "args." << prop_name(*f_iter);
-    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) {
-      f_service_ << ".Value";
-    }
-  }
-  cleanup_member_name_mapping(arg_struct);
-  f_service_ << ");" << endl;
-
-  prepare_member_name_mapping(xs, xs->get_members(), resultname);
-  if (xceptions.size() > 0) {
-    indent_down();
-    f_service_ << indent() << "}" << endl;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " "
-                 << (*x_iter)->get_name() << ")" << endl
-                 << indent() << "{" << endl;
-      if (!tfunction->is_oneway()) {
-        indent_up();
-        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name()
-                   << ";" << endl;
-        indent_down();
-      }
-      f_service_ << indent() << "}" << endl;
-    }
-  }
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
-               << "\", TMessageType.Reply, seqid)); " << endl;
-    f_service_ << indent() << "result.Write(oprot);" << endl;
-  }
-  indent_down();
-
-  cleanup_member_name_mapping(xs);
-
-  f_service_ << indent() << "}" << endl
-             << indent() << "catch (TTransportException)" << endl
-             << indent() << "{" << endl
-             << indent() << "  throw;" << endl
-             << indent() << "}" << endl
-             << indent() << "catch (Exception ex)" << endl
-             << indent() << "{" << endl
-             << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl
-             << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl;
-
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "}" << endl;
-  } else {
-    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent()
-               << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");"
-               << endl
-               << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
-               << "\", TMessageType.Exception, seqid));" << endl
-               << indent() << "  x.Write(oprot);" << endl
-               << indent() << "}" << endl;
-    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl
-               << indent() << "oprot.Transport.Flush();" << endl;
-  }
-
-  scope_down(f_service_);
-
-  f_service_ << endl;
-}
-
-void t_csharp_generator::generate_process_function_async(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  indent(f_service_) << "public async Task " << tfunction->get_name()
-    << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot)" << endl;
-  scope_up(f_service_);
-
-  string argsname = tfunction->get_name() + "_args";
-  string resultname = tfunction->get_name() + "_result";
-
-  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl
-    << indent() << "args.Read(iprot);" << endl
-    << indent() << "iprot.ReadMessageEnd();" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
-  }
-
-  f_service_ << indent() << "try" << endl
-    << indent() << "{" << endl;
-  indent_up();
-
-  if (xceptions.size() > 0) {
-    f_service_ << indent() << "try" << endl
-      << indent() << "{" << endl;
-    indent_up();
-  }
-
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_ << indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "result.Success = ";
-  }
-  f_service_ << "await iface_." << normalize_name(tfunction->get_name()) << "Async(";
-  bool first = true;
-  prepare_member_name_mapping(arg_struct);
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    }
-    else {
-      f_service_ << ", ";
-    }
-    f_service_ << "args." << prop_name(*f_iter);
-    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) {
-      f_service_ << ".Value";
-    }
-  }
-  cleanup_member_name_mapping(arg_struct);
-  f_service_ << ");" << endl;
-
-  prepare_member_name_mapping(xs, xs->get_members(), resultname);
-  if (xceptions.size() > 0) {
-    indent_down();
-    f_service_ << indent() << "}" << endl;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " "
-        << (*x_iter)->get_name() << ")" << endl
-        << indent() << "{" << endl;
-      if (!tfunction->is_oneway()) {
-        indent_up();
-        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name()
-          << ";" << endl;
-        indent_down();
-      }
-      f_service_ << indent() << "}" << endl;
-    }
-  }
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
-      << "\", TMessageType.Reply, seqid)); " << endl;
-    f_service_ << indent() << "result.Write(oprot);" << endl;
-  }
-  indent_down();
-
-  cleanup_member_name_mapping(xs);
-
-  f_service_ << indent() << "}" << endl
-    << indent() << "catch (TTransportException)" << endl
-    << indent() << "{" << endl
-    << indent() << "  throw;" << endl
-    << indent() << "}" << endl
-    << indent() << "catch (Exception ex)" << endl
-    << indent() << "{" << endl
-    << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl
-    << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl;
-
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "}" << endl;
-  }
-  else {
-    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent()
-      << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");"
-      << endl
-      << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
-      << "\", TMessageType.Exception, seqid));" << endl
-      << indent() << "  x.Write(oprot);" << endl
-      << indent() << "}" << endl;
-    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl
-      << indent() << "oprot.Transport.Flush();" << endl;
-  }
-
-  scope_down(f_service_);
-
-  f_service_ << endl;
-}
-
-void t_csharp_generator::generate_csharp_union_reader(std::ofstream& out, t_struct* tunion) {
-  // Thanks to THRIFT-1768, we don't need to check for required fields in the union
-  const vector<t_field*>& fields = tunion->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "public static " << tunion->get_name() << " Read(TProtocol iprot)" << endl;
-  scope_up(out);
-
-  out << indent() << "iprot.IncrementRecursionDepth();" << endl;
-  out << indent() << "try" << endl;
-  scope_up(out);
-
-  indent(out) << tunion->get_name() << " retval;" << endl;
-  indent(out) << "iprot.ReadStructBegin();" << endl;
-  indent(out) << "TField field = iprot.ReadFieldBegin();" << endl;
-  // we cannot have the first field be a stop -- we must have a single field defined
-  indent(out) << "if (field.Type == TType.Stop)" << endl;
-  scope_up(out);
-  indent(out) << "iprot.ReadFieldEnd();" << endl;
-  indent(out) << "retval = new ___undefined();" << endl;
-  scope_down(out);
-  indent(out) << "else" << endl;
-  scope_up(out);
-  indent(out) << "switch (field.ID)" << endl;
-  scope_up(out);
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
-    indent_up();
-    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-
-    indent(out) << type_name((*f_iter)->get_type()) << " temp;" << endl;
-    generate_deserialize_field(out, (*f_iter), "temp", true);
-    indent(out) << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl;
-
-    indent_down();
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
-        << endl << indent() << "  retval = new ___undefined();" << endl << indent() << "}" << endl
-        << indent() << "break;" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default: " << endl;
-  indent_up();
-  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl << indent()
-              << "retval = new ___undefined();" << endl;
-  indent(out) << "break;" << endl;
-  indent_down();
-
-  scope_down(out);
-
-  indent(out) << "iprot.ReadFieldEnd();" << endl;
-
-  inde

<TRUNCATED>

[27/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_swift_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_swift_generator.cc b/compiler/cpp/src/generate/t_swift_generator.cc
deleted file mode 100644
index 6e48bca..0000000
--- a/compiler/cpp/src/generate/t_swift_generator.cc
+++ /dev/null
@@ -1,2209 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <set>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_oop_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ostream;
-using std::ofstream;
-using std::ostringstream;
-using std::set;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Swift code generator.
- *
- * Designed from the Objective-C (aka Cocoa) generator.
- */
-class t_swift_generator : public t_oop_generator {
-public:
-  t_swift_generator(t_program* program,
-                    const map<string, string>& parsed_options,
-                    const string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    map<string, string>::const_iterator iter;
-
-    log_unexpected_ = false;
-    async_clients_ = false;
-    promise_kit_ = false;
-    debug_descriptions_ = false;
-
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("log_unexpected") == 0) {
-        log_unexpected_ = true;
-      } else if( iter->first.compare("async_clients") == 0) {
-        async_clients_ = true;
-      } else if( iter->first.compare("promise_kit") == 0) {
-        promise_kit_ = true;
-      } else if( iter->first.compare("debug_descriptions") == 0) {
-        debug_descriptions_ = true;
-      } else {
-        throw "unknown option swift:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-swift";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(ostream& out,
-                         string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool defval = false,
-                         bool is_property = false);
-  void render_const_value(ostream& out,
-                          t_type* type,
-                          t_const_value* value);
-
-  void generate_swift_struct(ofstream& out,
-                             t_struct* tstruct,
-                             bool is_private);
-  void generate_swift_struct_init(ofstream& out,
-                                  t_struct* tstruct,
-                                  bool all,
-                                  bool is_private);
-  
-  void generate_swift_struct_implementation(ofstream& out,
-                                            t_struct* tstruct,
-                                            bool is_result,
-                                            bool is_private);
-  void generate_swift_struct_hashable_extension(ofstream& out,
-                                                t_struct* tstruct,
-                                                bool is_private);
-  void generate_swift_struct_equatable_extension(ofstream& out,
-                                                 t_struct* tstruct,
-                                                 bool is_private);
-  void generate_swift_struct_thrift_extension(ofstream& out,
-                                              t_struct* tstruct,
-                                              bool is_result,
-                                              bool is_private);
-  void generate_swift_struct_reader(ofstream& out, t_struct* tstruct, bool is_private);
-  void generate_swift_struct_writer(ofstream& out,t_struct* tstruct, bool is_private);
-  void generate_swift_struct_result_writer(ofstream& out, t_struct* tstruct);
-  void generate_swift_struct_printable_extension(ofstream& out, t_struct* tstruct);
-
-  string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
-  string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
-  void generate_function_helpers(t_service *tservice, t_function* tfunction);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_swift_service_protocol(ofstream& out, t_service* tservice);
-  void generate_swift_service_protocol_async(ofstream& out, t_service* tservice);
-
-  void generate_swift_service_client(ofstream& out, t_service* tservice);
-  void generate_swift_service_client_async(ofstream& out, t_service* tservice);
-
-  void generate_swift_service_client_send_function_implementation(ofstream& out,
-                                                                  t_service* tservice,
-                                                                  t_function* tfunction,
-                                                                  bool needs_protocol);
-  void generate_swift_service_client_send_function_invocation(ofstream& out, t_function* tfunction);
-  void generate_swift_service_client_send_async_function_invocation(ofstream& out,
-                                                                    t_function* tfunction);
-  void generate_swift_service_client_recv_function_implementation(ofstream& out,
-                                                                  t_service* tservice,
-                                                                  t_function* tfunction,
-                                                                  bool needs_protocol);
-  void generate_swift_service_client_implementation(ofstream& out, t_service* tservice);
-  void generate_swift_service_client_async_implementation(ofstream& out, t_service* tservice);
-
-  void generate_swift_service_server(ofstream& out, t_service* tservice);
-  void generate_swift_service_server_implementation(ofstream& out, t_service* tservice);
-  void generate_swift_service_helpers(t_service* tservice);
-
-  /**
-   * Helper rendering functions
-   */
-
-  string swift_imports();
-  string swift_thrift_imports();
-  string type_name(t_type* ttype, bool is_optional=false, bool is_forced=false);
-  string base_type_name(t_base_type* tbase);
-  string declare_property(t_field* tfield, bool is_private);
-  string function_signature(t_function* tfunction);
-  string async_function_signature(t_function* tfunction);
-  string promise_function_signature(t_function* tfunction);
-  string function_name(t_function* tfunction);
-  string argument_list(t_struct* tstruct, string protocol_name, bool is_internal);
-  string type_to_enum(t_type* ttype, bool qualified=false);
-  string maybe_escape_identifier(const string& identifier);
-  void populate_reserved_words();
-
-private:
-  
-  void block_open(ostream& out) {
-    out << " {" << endl;
-    indent_up();
-  }
-  
-  void block_close(ostream& out, bool end_line=true) {
-    indent_down();
-    indent(out) << "}";
-    if (end_line) out << endl;
-  }
-
-  
-  bool field_is_optional(t_field* tfield) {
-    return tfield->get_req() == t_field::T_OPTIONAL;
-  }
-  
-  bool struct_has_required_fields(t_struct* tstruct) {
-    const vector<t_field*>& members = tstruct->get_members();
-    vector<t_field*>::const_iterator m_iter;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (!field_is_optional(*m_iter)) {
-        return true;
-      }
-    }
-    return false;
-  }
-  
-  bool struct_has_optional_fields(t_struct* tstruct) {
-    const vector<t_field*>& members = tstruct->get_members();
-    vector<t_field*>::const_iterator m_iter;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (field_is_optional(*m_iter)) {
-        return true;
-      }
-    }
-    return false;
-  }
-  
-  string constants_declarations_;
-
-  /**
-   * File streams
-   */
-
-  ofstream f_decl_;
-  ofstream f_impl_;
-
-  bool log_unexpected_;
-  bool async_clients_;
-  bool promise_kit_;
-  bool debug_descriptions_;
-
-  set<string> swift_reserved_words_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- */
-void t_swift_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  populate_reserved_words();
-
-  // we have a .swift declarations file...
-  string f_decl_name = capitalize(program_name_) + ".swift";
-  string f_decl_fullname = get_out_dir() + f_decl_name;
-  f_decl_.open(f_decl_fullname.c_str());
-
-  f_decl_ << autogen_comment() << endl;
-
-  f_decl_ << swift_imports() << swift_thrift_imports() << endl;
-
-  // ...and a .swift implementation extensions file
-  string f_impl_name = capitalize(program_name_) + "+Exts.swift";
-  string f_impl_fullname = get_out_dir() + f_impl_name;
-  f_impl_.open(f_impl_fullname.c_str());
-
-  f_impl_ << autogen_comment() << endl;
-
-  f_impl_ << swift_imports() << swift_thrift_imports() << endl;
-
-}
-
-/**
- * Prints standard Cocoa imports
- *
- * @return List of imports for Cocoa libraries
- */
-string t_swift_generator::swift_imports() {
-
-  vector<string> includes_list;
-  includes_list.push_back("Foundation");
-  
-  ostringstream includes;
-  
-  vector<string>::const_iterator i_iter;
-  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) {
-    includes << "import " << *i_iter << endl;
-  }
-  
-  includes << endl;
-  
-  return includes.str();
-}
-
-/**
- * Prints Thrift runtime imports
- *
- * @return List of imports necessary for Thrift runtime
- */
-string t_swift_generator::swift_thrift_imports() {
-
-  vector<string> includes_list;
-  includes_list.push_back("Thrift");
-  
-  if (promise_kit_) {
-    includes_list.push_back("PromiseKit");
-  }
-
-  ostringstream includes;
-
-  vector<string>::const_iterator i_iter;
-  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) {
-    includes << "import " << *i_iter << endl;
-  }
-  
-  includes << endl;
-
-  return includes.str();
-}
-
-/**
- * Finish up generation.
- */
-void t_swift_generator::close_generator() {
-  // stick our constants declarations at the end of the header file
-  // since they refer to things we are defining.
-  f_decl_ << constants_declarations_ << endl;
-}
-
-/**
- * Generates a typedef. This is just a simple 1-liner in Swift
- *
- * @param ttypedef The type definition
- */
-void t_swift_generator::generate_typedef(t_typedef* ttypedef) {
-  f_decl_ << indent() << "public typealias " << ttypedef->get_symbolic()
-          << " = " << type_name(ttypedef->get_type()) << endl;
-  f_decl_ << endl;
-}
-
-/**
- * Generates code for an enumerated type. In Swift, this is
- * essentially the same as the thrift definition itself, using
- * Swift syntax.
- *
- * @param tenum The enumeration
- */
-void t_swift_generator::generate_enum(t_enum* tenum) {
-  f_decl_ << indent() << "public enum " << tenum->get_name() << " : Int32";
-  block_open(f_decl_);
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    f_decl_ << indent() << "case " << (*c_iter)->get_name()
-            << " = " << (*c_iter)->get_value() << endl;
-  }
-
-  f_decl_ << endl;
-  f_decl_ << indent() << "public init() { self.init(rawValue: " << constants.front()->get_value() << ")! }" << endl;
-  
-  block_close(f_decl_);
-  f_decl_ << endl;
-  
-  f_impl_ << indent() << "extension " << tenum->get_name() << " : TEnum";
-  block_open(f_impl_);
-
-  f_impl_ << endl;
-  
-  f_impl_ << indent() << "public static func readValueFromProtocol(proto: TProtocol) throws -> " << tenum->get_name();
-  block_open(f_impl_);
-  f_impl_ << indent() << "var raw = Int32()" << endl
-          << indent() << "try proto.readI32(&raw)" << endl
-          << indent() << "return " << tenum->get_name() << "(rawValue: raw)!" << endl;
-  block_close(f_impl_);
-  f_impl_ << endl;
-  
-  f_impl_ << indent() << "public static func writeValue(value: " << tenum->get_name() << ", toProtocol proto: TProtocol) throws";
-  block_open(f_impl_);
-  f_impl_ << indent() << "try proto.writeI32(value.rawValue)" << endl;
-  block_close(f_impl_);
-  f_impl_ << endl;
-  
-  block_close(f_impl_);
-  f_impl_ << endl;
-}
-
-/**
- * Generates public constants for all Thrift constants.
- * 
- * @param consts Constants to generate
- */
-void t_swift_generator::generate_consts(vector<t_const*> consts) {
-
-  ostringstream const_interface;
-
-  // Public constants for base types & strings
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    t_type* type = (*c_iter)->get_type();
-    const_interface << "public let " << capitalize((*c_iter)->get_name()) << " : " << type_name(type) << " = ";
-    render_const_value(const_interface, type, (*c_iter)->get_value());
-    const_interface << endl << endl;
-  }
-  
-  // this gets spit into the header file in ::close_generator
-  constants_declarations_ = const_interface.str();
-  
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is a struct
- * with public members. Optional types are used for optional properties to
- * allow them to be tested for availability. Separate inits are included for
- * required properties & all properties.
- * 
- * Generates extensions to provide conformance to TStruct, TSerializable,
- * Hashable & Equatable
- *
- * @param tstruct The struct definition
- */
-void t_swift_generator::generate_struct(t_struct* tstruct) {
-  generate_swift_struct(f_decl_, tstruct, false);
-  generate_swift_struct_implementation(f_impl_, tstruct, false, false);
-}
-
-/**
- * Exceptions are structs, but they conform to ErrorType
- *
- * @param tstruct The struct definition
- */
-void t_swift_generator::generate_xception(t_struct* txception) {
-  generate_swift_struct(f_decl_, txception, false);
-  generate_swift_struct_implementation(f_impl_, txception, false, false);
-}
-
-/**
- * Generate the interface for a struct. Only properties and 
- * init methods are included.
- *
- * @param tstruct The struct definition
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct(ofstream& out,
-                                              t_struct* tstruct,
-                                              bool is_private) {
-  
-  string visibility = is_private ? "private" : "public";
-  
-  out << indent() << visibility << " final class " << tstruct->get_name();
-
-  if (tstruct->is_xception()) {
-    out << " : ErrorType";
-  }
-  
-  block_open(out);
-
-  // properties
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    out << endl;
-    out << indent() << declare_property(*m_iter, is_private) << endl;
-  }
-  
-  out << endl;
-  
-  // init
-  
-  indent(out) << visibility << " init()";
-  block_open(out);
-  block_close(out);
-  
-  out << endl;
-  
-  if (struct_has_required_fields(tstruct)) {
-    generate_swift_struct_init(out, tstruct, false, is_private);
-  }
-  if (struct_has_optional_fields(tstruct)) {
-    generate_swift_struct_init(out, tstruct, true, is_private);
-  }
-
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generate struct init for properties
- *
- * @param tstruct The structure definition
- * @param all     Generate init with all or just required properties
- * @param is_private
- *                Is the initializer public or private
- */
-void t_swift_generator::generate_swift_struct_init(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   bool all,
-                                                   bool is_private) {
-
-  string visibility = is_private ? "private" : "public";
-
-  indent(out) << visibility << " init(";
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  
-  bool first=true;
-  for (m_iter = members.begin(); m_iter != members.end();) {
-    if (all || !field_is_optional(*m_iter)) {
-      if (first) {
-        first = false;
-      }
-      else {
-        out << ", ";
-      }
-      out << (*m_iter)->get_name() << ": "
-          << maybe_escape_identifier(type_name((*m_iter)->get_type(), field_is_optional(*m_iter)));
-    }
-    ++m_iter;
-  }
-  out << ")";
-  
-  block_open(out);
-  
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (all || (*m_iter)->get_req() == t_field::T_REQUIRED || (*m_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
-      out << indent() << "self." << maybe_escape_identifier((*m_iter)->get_name()) << " = "
-          << maybe_escape_identifier((*m_iter)->get_name()) << endl;
-    }
-  }
-  
-  block_close(out);
- 
-  out << endl;
-}
-
-/**
- * Generate the hashable protocol implmentation
- *
- * @param tstruct The structure definition
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_hashable_extension(ofstream& out,
-                                                                 t_struct* tstruct,
-                                                                 bool is_private) {
-
-  string visibility = is_private ? "private" : "public";
-
-  indent(out) << "extension " << tstruct->get_name() << " : Hashable";
-  
-  block_open(out);
-  
-  out << endl;
-  
-  indent(out) << visibility << " var hashValue : Int";
-  
-  block_open(out);
-  
-  
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  if (!members.empty()) {
-    indent(out) << "let prime = 31" << endl;
-    indent(out) << "var result = 1" << endl;
-    
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_field* tfield = *m_iter;
-      string accessor = field_is_optional(tfield) ? "?." : ".";
-      string defaultor = field_is_optional(tfield) ? " ?? 0" : "";
-      indent(out) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield->get_name()) << accessor
-                  <<  "hashValue" << defaultor << ")" << endl;
-    }
-    
-    indent(out) << "return result" << endl;
-  }
-  else {
-    indent(out) << "return 31" << endl;
-  }
-
-  block_close(out);
-  
-  out << endl;
-  
-  block_close(out);
-
-  out << endl;
-}
-
-/**
- * Generate the equatable protocol implementation
- *
- * @param tstruct The structure definition
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_equatable_extension(ofstream& out,
-                                                                  t_struct* tstruct,
-                                                                  bool is_private) {
-
-  string visibility = is_private ? "private" : "public";
-  
-  indent(out) << visibility << " func ==(lhs: " << type_name(tstruct) << ", rhs: " << type_name(tstruct) << ") -> Bool";
-  
-  block_open(out);
-  
-  indent(out) << "return";
-  
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  if (members.size()) {
-    
-    out << endl;
-  
-    indent_up();
-  
-    for (m_iter = members.begin(); m_iter != members.end();) {
-      t_field* tfield = *m_iter;
-      indent(out) << "(lhs." << maybe_escape_identifier(tfield->get_name())
-                  << " ?== rhs." << maybe_escape_identifier(tfield->get_name()) << ")";
-      if (++m_iter != members.end()) {
-        out << " &&";
-      }
-      out << endl;
-    }
-  
-    indent_down();
-    
-  }
-  else {
-    out << " true" << endl;
-  }
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generate struct implementation. Produces extensions that
- * fulfill the requisite protocols to complete the value.
- *
- * @param tstruct The struct definition
- * @param is_result
- *                If this is a result it needs a different writer
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_implementation(ofstream& out,
-                                                             t_struct* tstruct,
-                                                             bool is_result,
-                                                             bool is_private) {
-  
-  generate_swift_struct_equatable_extension(out, tstruct, is_private);
-  
-  if (!is_private && !is_result) {
-    generate_swift_struct_printable_extension(out, tstruct);
-  }
-  
-  generate_swift_struct_hashable_extension(out, tstruct, is_private);
-  generate_swift_struct_thrift_extension(out, tstruct, is_result, is_private);
-
-  out << endl << endl;
-}
-
-/**
- * Generate the TStruct protocol implementation.
- *
- * @param tstruct The structure definition
- * @param is_result
- *                Is the struct a result value
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_thrift_extension(ofstream& out,
-                                                               t_struct* tstruct,
-                                                               bool is_result,
-                                                               bool is_private) {
-  
-  indent(out) << "extension " << tstruct->get_name() << " : TStruct";
-  
-  block_open(out);
-  
-  out << endl;
-  
-  generate_swift_struct_reader(out, tstruct, is_private);
-  
-  if (is_result) {
-    generate_swift_struct_result_writer(out, tstruct);
-  }
-  else {
-    generate_swift_struct_writer(out, tstruct, is_private);
-  }
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a function to read a struct from
- * from a protocol. (TStruct compliance)
- *
- * @param tstruct The structure definition
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_reader(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_private) {
-  
-  string visibility = is_private ? "private" : "public";
-  
-  indent(out) << visibility << " static func readValueFromProtocol(__proto: TProtocol) throws -> "
-              << tstruct->get_name();
-  
-  block_open(out);
-  
-  out << endl;
-  
-  indent(out) << "try __proto.readStructBegin()" << endl << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool optional = field_is_optional(*f_iter);
-    indent(out) << "var " << maybe_escape_identifier((*f_iter)->get_name()) << " : "
-                << type_name((*f_iter)->get_type(), optional, !optional) << endl;
-  }
-  
-  out << endl;
-  
-  // Loop over reading in fields
-  indent(out) << "fields: while true";
-  
-  block_open(out);
-  
-  out << endl;
-
-  indent(out) << "let (_, fieldType, fieldID) = try __proto.readFieldBegin()" << endl << endl;
-  indent(out) << "switch (fieldID, fieldType)";
-  
-  block_open(out);
-  
-  indent(out) << "case (_, .STOP):" << endl;
-  indent_up();
-  indent(out) << "break fields" << endl << endl;
-  indent_down();
-  
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-
-    indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):" << endl;
-    indent_up();
-    indent(out) << maybe_escape_identifier((*f_iter)->get_name()) << " = try __proto.readValue() as "
-                << type_name((*f_iter)->get_type()) << endl << endl;
-    indent_down();
-    
-  }
-
-  indent(out) << "case let (_, unknownType):" << endl;
-  indent_up();
-  indent(out) << "try __proto.skipType(unknownType)" << endl;
-  indent_down();
-  
-  block_close(out);
-  
-  out << endl;
-
-  // Read field end marker
-  indent(out) << "try __proto.readFieldEnd()" << endl;
-  
-  block_close(out);
-
-  out << endl;
-  
-  indent(out) << "try __proto.readStructEnd()" << endl;
-
-  out << endl;
-  
-  if (struct_has_required_fields(tstruct)) {
-    // performs various checks (e.g. check that all required fields are set)
-    indent(out) << "// Required fields" << endl;
-    
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (field_is_optional(*f_iter)) {
-        continue;
-      }
-      indent(out) << "try __proto.validateValue(" << (*f_iter)->get_name() << ", "
-                  << "named: \"" << (*f_iter)->get_name() << "\")" << endl;
-    }
-  }
-  
-  out << endl;
-    
-  indent(out) << "return " << tstruct->get_name() << "(";
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    out << (*f_iter)->get_name() << ": " << maybe_escape_identifier((*f_iter)->get_name());
-    if (++f_iter != fields.end()) {
-      out << ", ";
-    }
-  }
-  out << ")" << endl;
-
-  block_close(out);
-
-  out << endl;
-}
-
-/**
- * Generates a function to write a struct to
- * a protocol. (TStruct compliance)
- *
- * @param tstruct The structure definition
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_writer(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_private) {
-  
-  string visibility = is_private ? "private" : "public";
-  
-  indent(out) << visibility << " static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws";
-  
-  block_open(out);
-  
-  out << endl;
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "try __proto.writeStructBeginWithName(\"" << name << "\")" << endl;
-  
-  out << endl;
-  
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field *tfield = *f_iter;
-    
-    bool optional = field_is_optional(tfield);
-    if (optional) {
-      indent(out) << "if let " << maybe_escape_identifier(tfield->get_name())
-                  << " = __value." << maybe_escape_identifier(tfield->get_name());
-      block_open(out);
-    }
-    
-    indent(out) << "try __proto.writeFieldValue("
-                << (optional ? "" : "__value.") << maybe_escape_identifier(tfield->get_name()) << ", "
-                << "name: \"" << tfield->get_name() << "\", "
-                << "type: " << type_to_enum(tfield->get_type()) << ", "
-                << "id: " << tfield->get_key() << ")" << endl;
-
-    if (optional) {
-      block_close(out);
-    }
-
-    out << endl;
-  }
-
-  indent(out) << "try __proto.writeFieldStop()" << endl << endl;
-  
-  indent(out) << "try __proto.writeStructEnd()" << endl;
-
-  block_close(out);
-
-  out << endl;
-}
-
-/**
- * Generates a function to read a struct from
- * from a protocol. (TStruct compliance)
- *
- * This is specifically a function result. Only
- * the first available field is written.
- *
- * @param tstruct The structure definition
- */
-void t_swift_generator::generate_swift_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  
-  indent(out) << "private static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws";
-  
-  block_open(out);
-  
-  out << endl;
-  
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  
-  indent(out) << "try __proto.writeStructBeginWithName(\"" << name << "\")" << endl;
-  
-  out << endl;
-  
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field *tfield = *f_iter;
-    
-    indent(out) << "if let result = __value." << (*f_iter)->get_name();
-    
-    block_open(out);
-    
-    indent(out) << "try __proto.writeFieldValue(result, "
-                << "name: \"" << tfield->get_name() << "\", "
-                << "type: " << type_to_enum(tfield->get_type()) << ", "
-                << "id: " << tfield->get_key() << ")" << endl;
-
-    block_close(out);
-  }
-  // Write the struct map
-  indent(out) << "try __proto.writeFieldStop()" << endl << endl;
-  
-  indent(out) << "try __proto.writeStructEnd()" << endl;
-
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a description method for the given struct
- *
- * @param tstruct The struct definition
- */
-void t_swift_generator::generate_swift_struct_printable_extension(ofstream& out, t_struct* tstruct) {
-  
-  // Allow use of debugDescription so the app can add description via a cateogory/extension
-
-  indent(out) << "extension " << tstruct->get_name() << " : "
-              << (debug_descriptions_ ? "CustomDebugStringConvertible" : "CustomStringConvertible");
-
-  block_open(out);
-  
-  out << endl;
-  
-  indent(out) << "public var description : String";
-  
-  block_open(out);
-  
-  indent(out) << "var desc = \"" << tstruct->get_name() << "(\"" << endl;
-  
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    indent(out) << "desc += \"" << (*f_iter)->get_name()
-                << "=\\(self." << maybe_escape_identifier((*f_iter)->get_name()) << ")";
-    if (++f_iter != fields.end()) {
-      out << ", ";
-    }
-    out << "\"" << endl;
-  }
-  indent(out) << "desc += \")\"" << endl;
-  indent(out) << "return desc" << endl;
-
-  block_close(out);
-  
-  out << endl;
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a thrift service.  In Swift this consists of a
- * protocol definition and a client (with it's implementation
- * separated into exts file).
- *
- * @param tservice The service definition
- */
-void t_swift_generator::generate_service(t_service* tservice) {
-  
-  generate_swift_service_protocol(f_decl_, tservice);
-  generate_swift_service_client(f_decl_, tservice);
-  if (async_clients_) {
-    generate_swift_service_protocol_async(f_decl_, tservice);
-    generate_swift_service_client_async(f_decl_, tservice);
-  }
-  generate_swift_service_server(f_decl_, tservice);
-
-  generate_swift_service_helpers(tservice);
-  
-  generate_swift_service_client_implementation(f_impl_, tservice);
-  if (async_clients_) {
-    generate_swift_service_client_async_implementation(f_impl_, tservice);
-  }
-  generate_swift_service_server_implementation(f_impl_, tservice);
-}
-
-/**
- * Generates structs for all the service return types
- *
- * @param tservice The service
- */
-void t_swift_generator::generate_swift_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    
-    t_struct* ts = (*f_iter)->get_arglist();
-    
-    string qname = function_args_helper_struct_type(tservice, *f_iter);
-    
-    t_struct qname_ts = t_struct(ts->get_program(), qname);
-
-    const vector<t_field*>& members = ts->get_members();
-    vector<t_field*>::const_iterator m_iter;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      qname_ts.append(*m_iter);
-    }
-    
-    generate_swift_struct(f_impl_, &qname_ts, true);
-    generate_swift_struct_implementation(f_impl_, &qname_ts, false, true);
-    generate_function_helpers(tservice, *f_iter);
-  }
-}
-
-string t_swift_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return tservice->get_name() + "_" + tfunction->get_name();
-  } else {
-    return tservice->get_name() + "_" + tfunction->get_name() + "_result";
-  }
-}
-
-string t_swift_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) {
-  return tservice->get_name() + "_" + tfunction->get_name() + "_args";
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_swift_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  // create a result struct with a success field of the return type,
-  // and a field for each type of exception thrown
-  t_struct result(program_, function_result_helper_struct_type(tservice, tfunction));
-  if (!tfunction->get_returntype()->is_void()) {
-    t_field* success = new t_field(tfunction->get_returntype(), "success", 0);
-    success->set_req(t_field::T_OPTIONAL);
-    result.append(success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field *x = *f_iter;
-    t_field *ox = new t_field(x->get_type(), x->get_name(), x->get_key());
-    ox->set_req(t_field::T_OPTIONAL);
-    result.append(ox);
-  }
-
-  // generate the result struct
-  generate_swift_struct(f_impl_, &result, true);
-  generate_swift_struct_implementation(f_impl_, &result, true, true);
-  
-  for (f_iter = result.get_members().begin(); f_iter != result.get_members().end(); ++f_iter) {
-    delete *f_iter;
-  }
-}
-
-/**
- * Generates a service protocol definition.
- *
- * @param tservice The service to generate a protocol definition for
- */
-void t_swift_generator::generate_swift_service_protocol(ofstream& out, t_service* tservice) {
-
-  indent(out) << "public protocol " << tservice->get_name();
-
-  block_open(out);
-  
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << endl;
-    indent(out) << function_signature(*f_iter) << "  // exceptions: ";
-    t_struct* xs = (*f_iter)->get_xceptions();
-    const vector<t_field*>& xceptions = xs->get_members();
-    vector<t_field*>::const_iterator x_iter;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      out << type_name((*x_iter)->get_type()) + ", ";
-    }
-    out << endl;
-  }
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates an asynchronous service protocol definition.
- *
- * @param tservice The service to generate a protocol definition for
- */
-void t_swift_generator::generate_swift_service_protocol_async(ofstream& out, t_service* tservice) {
-  
-  indent(out) << "public protocol " << tservice->get_name() << "Async";
-
-  block_open(out);
-  
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << endl;
-    indent(out) << async_function_signature(*f_iter) << endl;
-    if (promise_kit_) {
-      indent(out) << promise_function_signature(*f_iter) << endl;
-    }
-    out << endl;
-  }
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a service client interface definition.
- *
- * @param tservice The service to generate a client interface definition for
- */
-void t_swift_generator::generate_swift_service_client(ofstream& out,
-                                                                t_service* tservice) {
-  
-  indent(out) << "public class " << tservice->get_name() << "Client /* : " << tservice->get_name() << " */";
-  
-  block_open(out);
-  
-  out << endl;
-
-  indent(out) << "let __inProtocol : TProtocol" << endl << endl;
-  
-  indent(out) << "let __outProtocol : TProtocol" << endl << endl;
-  
-  indent(out) << "public init(inoutProtocol: TProtocol)";
-  
-  block_open(out);
-  
-  indent(out) << "__inProtocol = inoutProtocol" << endl;
-         
-  indent(out) << "__outProtocol = inoutProtocol" << endl;
-                
-  block_close(out);
-  
-  out << endl;
-  
-  indent(out) << "public init(inProtocol: TProtocol, outProtocol: TProtocol)";
-  
-  block_open(out);
-  
-  indent(out) << "__inProtocol = inProtocol" << endl;
-  
-  indent(out) << "__outProtocol = outProtocol" << endl;
-  
-  block_close(out);
-  
-  out << endl;
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a service client interface definition.
- *
- * @param tservice The service to generate a client interface definition for
- */
-void t_swift_generator::generate_swift_service_client_async(ofstream& out,
-                                                                      t_service* tservice) {
-  
-  indent(out) << "public class " << tservice->get_name() << "AsyncClient /* : " << tservice->get_name() << " */";
-  
-  block_open(out);
-  
-  out << endl;
-  
-  indent(out) << "let __protocolFactory : TProtocolFactory" << endl << endl;
-  
-  indent(out) << "let __transportFactory : TAsyncTransportFactory" << endl << endl;
-  
-  indent(out) << "public init(protocolFactory: TProtocolFactory, transportFactory: TAsyncTransportFactory)";
-  
-  block_open(out);
-  
-  indent(out) << "__protocolFactory = protocolFactory" << endl;
-  
-  indent(out) << "__transportFactory = transportFactory" << endl;
-  
-  block_close(out);
-  
-  out << endl;
-  
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a service server interface definition. In other words, 
- * the TProcess implementation for the service definition.
- *
- * @param tservice The service to generate a client interface definition for
- */
-void t_swift_generator::generate_swift_service_server(ofstream& out,
-                                                                t_service* tservice) {
-  
-  indent(out) << "public class " << tservice->get_name() << "Processor : NSObject /* " << tservice->get_name() << " */";
-
-  block_open(out);
-  
-  out << endl;
-  
-  out << indent() << "typealias ProcessorHandlerDictionary = "
-                  << "[String: (Int, TProtocol, TProtocol, " << tservice->get_name() << ") throws -> Void]" << endl
-      << endl
-      << indent() << "let service : " << tservice->get_name() << endl
-      << endl
-      << indent() << "public init(service: " << tservice->get_name() << ")";
-  block_open(out);
-  indent(out) << "self.service = service" << endl;
-  block_close(out);
-
-  out << endl;
-
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a function that will send the arguments
- * for a service function via a protocol.
- *
- * @param tservice  The service to generate
- * @param tfunction The function to generate
- * @param needs_protocol
- *                  Wether the first parameter must be a protocol or if
- *                  the protocol is to be assumed
- */
-void t_swift_generator::generate_swift_service_client_send_function_implementation(ofstream& out,
-                                                                                   t_service *tservice,
-                                                                                   t_function* tfunction,
-                                                                                   bool needs_protocol) {
-  
-  string funname = tfunction->get_name();
-
-  t_function send_function(g_type_bool,
-                           "send_" + tfunction->get_name(),
-                           tfunction->get_arglist());
-
-  string argsname = function_args_helper_struct_type(tservice, tfunction);
-  t_struct* arg_struct = tfunction->get_arglist();
-  
-  // Open function
-  indent(out) << "private func " << send_function.get_name() << "(" << argument_list(tfunction->get_arglist(), needs_protocol ? "__outProtocol" : "", true) << ") throws";
-  block_open(out);
-  
-  out << endl;
-
-  // Serialize the request
-  indent(out) << "try __outProtocol.writeMessageBeginWithName(\"" << funname << "\", "
-              << "type: " << (tfunction->is_oneway() ? ".ONEWAY" : ".CALL") << ", "
-              << "sequenceID: 0)" << endl;
-
-  out << endl;
-  
-  indent(out) << "let __args = " << argsname << "(";
-  
-  // write out function parameters
-  
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    t_field *tfield = (*f_iter);
-    out << tfield->get_name() << ": " << tfield->get_name();
-    if (++f_iter != fields.end()) {
-      out << ", ";
-    }
-  }
-  out << ")" << endl;
-  indent(out) << "try " << argsname << ".writeValue(__args, toProtocol: __outProtocol)" << endl << endl;
-  
-  indent(out) << "try __outProtocol.writeMessageEnd()" << endl;
-
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a function that will recv the result for a
- * service function via a protocol.
- *
- * @param tservice  The service to generate
- * @param tfunction The function to generate
- * @param needs_protocol
- *                  Wether the first parameter must be a protocol or if
- *                  the protocol is to be assumed
- */
-void t_swift_generator::generate_swift_service_client_recv_function_implementation(ofstream& out,
-                                                                                   t_service* tservice,
-                                                                                   t_function* tfunction,
-                                                                                   bool needs_protocol) {
-  
-  // Open function
-  indent(out) << "private func recv_" << tfunction->get_name() << "(";
-  
-  if (needs_protocol) {
-    out << "__inProtocol: TProtocol";
-  }
-  
-  out << ") throws";
-  
-  if (!tfunction->get_returntype()->is_void()) {
-    out << " -> " << type_name(tfunction->get_returntype());
-  }
-  
-  block_open(out);
-
-  // check for an exception
-  
-  out << endl;
-  
-  indent(out) << "try __inProtocol.readResultMessageBegin() " << endl << endl;
-  
-  string resultname = function_result_helper_struct_type(tservice, tfunction);
-  indent(out);
-  if (!tfunction->get_returntype()->is_void() || !tfunction->get_xceptions()->get_members().empty()) {
-    out << "let __result = ";
-  }
-  out << "try " << resultname << ".readValueFromProtocol(__inProtocol)" << endl << endl;
-  
-  indent(out) << "try __inProtocol.readMessageEnd()" << endl << endl;
-
-  // Careful, only return _result if not a void function
-  if (!tfunction->get_returntype()->is_void()) {
-    indent(out) << "if let __success = __result.success";
-    block_open(out);
-    indent(out) << "return __success" << endl;
-    block_close(out);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-  
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-    indent(out) << "if let " << (*x_iter)->get_name() << " = __result." << (*x_iter)->get_name();
-    block_open(out);
-    indent(out) << "throw " << (*x_iter)->get_name() << endl;
-    block_close(out);
-  }
-
-  // If you get here it's an exception, unless a void function
-  if (!tfunction->get_returntype()->is_void()) {
-    indent(out) << "throw NSError(" << endl;
-    indent_up();
-    indent(out) << "domain: TApplicationErrorDomain, " << endl;
-    indent(out) << "code: Int(TApplicationError.MissingResult.rawValue)," << endl;
-    indent(out) << "userInfo: [TApplicationErrorMethodKey: \"" << tfunction->get_name() << "\"])" << endl;
-    indent_down();
-  }
-
-  // Close function
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates an invocation of a given the send function for the
- * service function.
- *
- * @param tfunction The service to generate an implementation for
- */
-void t_swift_generator::generate_swift_service_client_send_function_invocation(ofstream& out,
-                                                                               t_function* tfunction) {
-  
-  indent(out) << "try send_" << tfunction->get_name() << "(";
-  
-  t_struct* arg_struct = tfunction->get_arglist();
-  
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    out << (*f_iter)->get_name() << ": " << (*f_iter)->get_name();
-    if (++f_iter != fields.end()) {
-      out << ", ";
-    }
-  }
-  
-  out << ")" << endl;
-}
-
-/**
- * Generates an invocation of a given the send function for the
- * service function. This is for asynchronous protocols.
- *
- * @param tfunction The service to generate an implementation for
- */
-void t_swift_generator::generate_swift_service_client_send_async_function_invocation(ofstream& out,
-                                                                                     t_function* tfunction) {
-  
-  t_struct* arg_struct = tfunction->get_arglist();
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  
-  indent(out) << "try send_" << tfunction->get_name() << "(__protocol";
-  
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    out << ", " << (*f_iter)->get_name() << ": " << (*f_iter)->get_name();
-  }
-  
-  out << ")" << endl;
-}
-
-/**
- * Generates a service client protocol implementation via extension.
- *
- * @param tservice The service to generate an implementation for
- */
-void t_swift_generator::generate_swift_service_client_implementation(ofstream& out,
-                                                                     t_service* tservice) {
-  
-  string name = tservice->get_name() + "Client";
-  
-  indent(out) << "extension " << name << " : " << tservice->get_name();
-  
-  block_open(out);
-  
-  out << endl;
-  
-  // generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-
-    generate_swift_service_client_send_function_implementation(out, tservice, *f_iter, false);
-
-    if (!(*f_iter)->is_oneway()) {
-      generate_swift_service_client_recv_function_implementation(out, tservice, *f_iter, false);
-    }
-
-    // Open function
-    indent(out) << "public " << function_signature(*f_iter);
-    
-    block_open(out);
-    
-    out << endl;
-    
-    generate_swift_service_client_send_function_invocation(out, *f_iter);
-
-    out << endl;
-
-    indent(out) << "try __outProtocol.transport().flush()" << endl << endl;
-    
-    if (!(*f_iter)->is_oneway()) {
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(out) << "try recv_" << (*f_iter)->get_name() << "()" << endl;
-      } else {
-        indent(out) << "return try recv_" << (*f_iter)->get_name() << "()" << endl;
-      }
-    }
-    
-    block_close(out);
-    
-    out << endl;
-  }
-
-  block_close(out);
-  
-  out << endl;
-}
-
-/**
- * Generates a service asynchronous client protocol implementation via extension.
- *
- * @param tservice The service to generate an implementation for
- */
-void t_swift_generator::generate_swift_service_client_async_implementation(ofstream& out,
-                                                                           t_service* tservice) {
-  
-  string name = tservice->get_name() + "AsyncClient";
-  string protocol_name = tservice->get_name() + "Async";
-
-  indent(out) << "extension " << name << " : " << protocol_name;
-  
-  block_open(out);
-  
-  out << endl;
-  
-  // generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-
-    generate_swift_service_client_send_function_implementation(out, tservice, *f_iter, true);
-
-    if (!(*f_iter)->is_oneway()) {
-      generate_swift_service_client_recv_function_implementation(out, tservice, *f_iter, true);
-    }
-    
-    indent(out) << "public " << async_function_signature(*f_iter);
-    block_open(out);
-    
-    out << endl;
-
-    out << indent() << "let __transport = __transportFactory.newTransport()" << endl
-        << indent() << "let __protocol = __protocolFactory.newProtocolOnTransport(__transport)" << endl
-        << endl;
-
-    generate_swift_service_client_send_async_function_invocation(out, *f_iter);
-    
-    out << endl;
-    
-    indent(out) << "__transport.flushWithCompletion(";
-    
-    if ((*f_iter)->is_oneway()) {
-      out << "success, failure: failure)" << endl;
-    }
-    else {
-      block_open(out);
-      indent(out) << "do";
-      block_open(out);
-
-      indent(out);
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        out << "let result = ";
-      }
-      out << "try self.recv_" << (*f_iter)->get_name() << "(__protocol)" << endl;
-      
-      out << indent() << "success(";
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        out << "result";
-      }
-      out << ")" << endl;
-      
-      block_close(out);
-      indent(out) << "catch let error";
-      block_open(out);
-      indent(out) << "failure(error as NSError)" << endl;
-      block_close(out);
-      block_close(out);
-      indent(out) << ", failure: failure)" << endl;
-    }
-    
-    
-    block_close(out);
-    
-    out << endl;
-
-    // Promise function
-    if (promise_kit_) {
-      
-      indent(out) << "public " << promise_function_signature(*f_iter);
-      block_open(out);
-      
-      out << indent() << "let (__promise, __fulfill, __reject) = Promise<" << type_name((*f_iter)->get_returntype()) << ">.pendingPromise()" << endl << endl
-          << indent() << "let __transport = __transportFactory.newTransport()" << endl
-          << indent() << "let __protocol = __protocolFactory.newProtocolOnTransport(__transport)" << endl
-          << endl;
-      
-      generate_swift_service_client_send_async_function_invocation(out, *f_iter);
-      
-      out << endl;
-      
-      indent(out) << "__transport.flushWithCompletion(";
-      
-      if ((*f_iter)->is_oneway()) {
-        out << "{ __fulfill() }, failure: { __reject($0) })" << endl;
-      }
-      else {
-        block_open(out);
-        indent(out) << "do";
-        block_open(out);
-        
-        indent(out);
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          out << "let result = ";
-        }
-        out << "try self.recv_" << (*f_iter)->get_name() << "(__protocol)" << endl;
-        
-        out << indent() << "__fulfill(";
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          out << "result";
-        }
-        out << ")" << endl;
-        
-        block_close(out);
-        indent(out) << "catch let error";
-        block_open(out);
-        indent(out) << "__reject(error)" << endl;
-        block_close(out);
-        block_close(out);
-        
-        indent(out) << ", failure: { error in " << endl;
-        indent_up();
-        indent(out) << "__reject(error)" << endl;
-        indent_down();
-        indent(out) << "})" << endl;
-      }
-
-      indent(out) << "return __promise" << endl;
-
-      block_close(out);
-      
-      out << endl;
-      
-    }
-    
-  }
-
-  block_close(out);
-
-  out << endl;
-}
-
-/**
- * Generates a service server implementation.
- *
- * Implemented by generating a block for each service function that
- * handles the processing of that function. The blocks are stored in
- * a map and looked up via function/message name.
- *
- * @param tservice The service to generate an implementation for
- */
-void t_swift_generator::generate_swift_service_server_implementation(ofstream& out,
-                                                                     t_service* tservice) {
-  
-  string name = tservice->get_name() + "Processor";
-
-  indent(out) << "extension " << name << " : TProcessor";
-  block_open(out);
-  
-  out << endl;
-  
-  indent(out) << "static let processorHandlers : ProcessorHandlerDictionary =";
-  block_open(out);
-  
-  out << endl;
-  
-  out << indent() << "var processorHandlers = ProcessorHandlerDictionary()" << endl << endl;
-  
-  // generate method map for routing incoming calls
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    
-    t_function* tfunction = *f_iter;
-    
-    string args_type = function_args_helper_struct_type(tservice, *f_iter);
-    
-    out << indent() << "processorHandlers[\"" << tfunction->get_name() << "\"] = { sequenceID, inProtocol, outProtocol, handler in" << endl
-        << endl;
-    
-    indent_up();
-    out << indent() << "let args = try " << args_type << ".readValueFromProtocol(inProtocol)" << endl
-        << endl
-        << indent() << "try inProtocol.readMessageEnd()" << endl
-        << endl;
-    
-    if (!tfunction->is_oneway() ) {
-      string result_type = function_result_helper_struct_type(tservice, tfunction);
-      indent(out) << "var result = " << result_type << "()" << endl;
-    
-      indent(out) << "do";
-      block_open(out);
-    
-      indent(out);
-      if (!tfunction->get_returntype()->is_void()) {
-        out << "result.success = ";
-      }
-      out << "try handler." << function_name(tfunction) << "(";
-    
-      t_struct* arg_struct = tfunction->get_arglist();
-      const vector<t_field*>& fields = arg_struct->get_members();
-      vector<t_field*>::const_iterator f_iter;
-
-      for (f_iter = fields.begin(); f_iter != fields.end();) {
-        string fieldName = (*f_iter)->get_name();
-        if (f_iter != fields.begin()) {
-          out << fieldName << ": ";
-        }
-        out << "args." << fieldName;
-        if (++f_iter != fields.end()) {
-          out << ", ";
-        }
-      }
-      
-      out << ")" << endl;
-      
-      block_close(out);
-      
-      t_struct* xs = tfunction->get_xceptions();
-      const vector<t_field*>& xfields = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      
-      for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) {
-        indent(out) << "catch let error as " << (*x_iter)->get_type()->get_name();
-        block_open(out);
-        indent(out) << "result." << (*x_iter)->get_name() << " = error" << endl;
-        block_close(out);
-      }
-      
-      indent(out) << "catch let error";
-      block_open(out);
-      out << indent() << "throw error" << endl;
-      block_close(out);
-      
-      out << endl;
-      
-      if (!tfunction->is_oneway()) {
-        out << indent() << "try outProtocol.writeMessageBeginWithName(\"" << tfunction->get_name() << "\", type: .REPLY, sequenceID: sequenceID)" << endl
-            << indent() << "try " << result_type << ".writeValue(result, toProtocol: outProtocol)" << endl
-            << indent() << "try outProtocol.writeMessageEnd()" << endl;
-      }
-    }
-    block_close(out);
-    
-  }
-  
-  indent(out) << "return processorHandlers" << endl;
-  
-  block_close(out,false);
-  out << "()" << endl;
-  
-  out << endl;
-  
-  indent(out) << "public func processOnInputProtocol(inProtocol: TProtocol, outputProtocol outProtocol: TProtocol) throws";
-  block_open(out);
-  
-  out << endl;
-  
-  out << indent() << "let (messageName, _, sequenceID) = try inProtocol.readMessageBegin()" << endl
-      << endl
-      << indent() << "if let processorHandler = " << name << ".processorHandlers[messageName]";
-  block_open(out);
-  out << indent() << "do";
-  block_open(out);
-  out << indent() << "try processorHandler(sequenceID, inProtocol, outProtocol, service)" << endl;
-  block_close(out);
-  out << indent() << "catch let error as NSError";
-  block_open(out);
-  out << indent() << "try outProtocol.writeExceptionForMessageName(messageName, sequenceID: sequenceID, ex: error)" << endl;
-  block_close(out);
-  block_close(out);
-  out << indent() << "else";
-  block_open(out);
-  out << indent() << "try inProtocol.skipType(.STRUCT)" << endl
-      << indent() << "try inProtocol.readMessageEnd()" << endl
-      << indent() << "try outProtocol.writeExceptionForMessageName(messageName," << endl;
-  indent_up();
-  out << indent() << "sequenceID: sequenceID," << endl
-      << indent() << "ex: NSError(" << endl;
-  indent_up();
-  out << indent() << "domain: TApplicationErrorDomain, " << endl
-      << indent() << "code: Int(TApplicationError.UnknownMethod.rawValue), " << endl
-      << indent() << "userInfo: [TApplicationErrorMethodKey: messageName]))" << endl;
-  indent_down();
-  indent_down();
-  block_close(out);
-  
-  block_close(out);
-  
-  block_close(out);
-  out << endl;
-}
-
-/**
- * Returns an Swift name
- *
- * @param ttype The type
- * @param class_ref Do we want a Class reference istead of a type reference?
- * @return Swift type name, i.e. Dictionary<Key,Value>
- */
-string t_swift_generator::type_name(t_type* ttype, bool is_optional, bool is_forced) {
-  string result;
-  if (ttype->is_base_type()) {
-    result = base_type_name((t_base_type*)ttype);
-  } else if (ttype->is_map()) {
-    t_map *map = (t_map *)ttype;
-    result = "TMap<" + type_name(map->get_key_type()) + ", " + type_name(map->get_val_type()) + ">";
-  } else if (ttype->is_set()) {
-    t_set *set = (t_set *)ttype;
-    result = "TSet<" + type_name(set->get_elem_type()) + ">";
-  } else if (ttype->is_list()) {
-    t_list *list = (t_list *)ttype;
-    result = "TList<" + type_name(list->get_elem_type()) + ">";
-  }
-  else {
-    result = ttype->get_name();
-  }
-  
-  if (is_optional) {
-    result += "?";
-  }
-  
-  if (is_forced) {
-    result += "!";
-  }
-  
-  return result;
-}
-
-/**
- * Returns the Swift type that corresponds to the thrift type.
- *
- * @param tbase The base type
- */
-string t_swift_generator::base_type_name(t_base_type* type) {
-  t_base_type::t_base tbase = type->get_base();
-
-  switch (tbase) {
-  case t_base_type::TYPE_VOID:
-    return "Void";
-  case t_base_type::TYPE_STRING:
-    if (type->is_binary()) {
-      return "TBinary";
-    } else {
-      return "String";
-    }
-  case t_base_type::TYPE_BOOL:
-    return "Bool";
-  case t_base_type::TYPE_I8:
-    return "Int8";
-  case t_base_type::TYPE_I16:
-    return "Int16";
-  case t_base_type::TYPE_I32:
-    return "Int32";
-  case t_base_type::TYPE_I64:
-    return "Int64";
-  case t_base_type::TYPE_DOUBLE:
-    return "Double";
-  default:
-    throw "compiler error: no Swift name for base type " + t_base_type::t_base_name(tbase);
-  }
-}
-
-/**
- * Renders full constant value (as would be seen after an '=')
- *
- */
-void t_swift_generator::render_const_value(ostream& out,
-                                             t_type* type,
-                                             t_const_value* value) {
-  type = get_true_type(type);
-  
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << "\"" << get_escaped_string(value) << "\"";
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << type_name(type) << "(" << value->get_integer() << ")";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      out << type_name(type) << "(";
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      out << ")";
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    out << value->get_identifier();
-  } else if (type->is_struct() || type->is_xception()) {
-    
-    out << type_name(type) << "(";
-    
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    for (f_iter = fields.begin(); f_iter != fields.end();) {
-      t_field* tfield = *f_iter;
-      t_const_value* value = NULL;
-      for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-        if (tfield->get_name() == v_iter->first->get_string()) {
-          value = v_iter->second;
-        }
-      }
-      
-      if (value) {
-        out << tfield->get_name() << ": ";
-        render_const_value(out, tfield->get_type(), value);
-      }
-      else if (!field_is_optional(tfield)) {
-        throw "constant error: required field " + type->get_name() + "." + tfield->get_name() + " has no value";
-      }
-      
-      if (++f_iter != fields.end()) {
-        out << ", ";
-      }
-    }
-    
-    out << ")";
-    
-  } else if (type->is_map()) {
-    
-    out << "[";
-    
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end();) {
-    
-      render_const_value(out, ktype, v_iter->first);
-      out << ": ";
-      render_const_value(out, vtype, v_iter->second);
-      
-      if (++v_iter != val.end()) {
-        out << ", ";
-      }
-    }
-    
-    out << "]";
-    
-  } else if (type->is_list()) {
-    
-    out << "[";
-    
-    t_type* etype = ((t_list*)type)->get_elem_type();
-    
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    
-    for (v_iter = val.begin(); v_iter != val.end();) {
-      
-      render_const_value(out, etype, v_iter->first);
-      
-      if (++v_iter != val.end()) {
-        out << ", ";
-      }
-    }
-    
-    out << "]";
-
-  } else if (type->is_set()) {
-
-    out << "[";
-    
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    
-    for (v_iter = val.begin(); v_iter != val.end();) {
-      
-      render_const_value(out, etype, v_iter->first);
-      
-      if (++v_iter != val.end()) {
-        out << ", ";
-      }
-    }
-    
-    out << "]";
-    
-  } else {
-    throw "compiler error: no const of type " + type->get_name();
-  }
-
-}
-
-/**
- * Declares an Swift property.
- *
- * @param tfield The field to declare a property for
- */
-string t_swift_generator::declare_property(t_field* tfield, bool is_private) {
-  
-  string visibility = is_private ? "private" : "public";
-  
-  ostringstream render;
-
-  render << visibility << " var " << maybe_escape_identifier(tfield->get_name());
-  
-  if (field_is_optional(tfield)) {
-    render << " : " << type_name(tfield->get_type(), true);
-  }
-  else {
-    render << " = " << type_name(tfield->get_type(), false) << "()";
-  }
-  
-  return render.str();
-}
-
-/**
- * Renders a function signature
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_swift_generator::function_signature(t_function* tfunction) {
-  
-  string result = "func " + function_name(tfunction);
-  
-  result += "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws";
-  
-  t_type* ttype = tfunction->get_returntype();
-  if (!ttype->is_void()) {
-    result += " -> " + type_name(ttype);
-  }
-  
-  return result;
-}
-
-/**
- * Renders a function signature that returns asynchronously via blocks.
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_swift_generator::async_function_signature(t_function* tfunction) {
-  t_type* ttype = tfunction->get_returntype();
-  t_struct* targlist = tfunction->get_arglist();
-  string response_param = "(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ") -> Void";
-  string result = "func " + function_name(tfunction);
-  result += "(" + argument_list(tfunction->get_arglist(), "", false)
-          + (targlist->get_members().size() ? ", " : "")
-          + "success: " + response_param + ", "
-          + "failure: (NSError) -> Void) throws";
-  return result;
-}
-
-/**
- * Renders a function signature that returns asynchronously via promises.
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_swift_generator::promise_function_signature(t_function* tfunction) {
-  return "func " + function_name(tfunction) + "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws "
-          + "-> Promise<" + type_name(tfunction->get_returntype()) + ">";
-}
-
-/**
- * Renders a verbose function name suitable for a Swift method
- */
-string t_swift_generator::function_name(t_function* tfunction) {
-  string name = tfunction->get_name();
-  if (!tfunction->get_arglist()->get_members().empty()) {
-    string first_arg = tfunction->get_arglist()->get_members().front()->get_name();
-    if (name.size() < first_arg.size() ||
-        lowercase(name.substr(name.size()-first_arg.size())) != lowercase(first_arg)) {
-      name += "With" + capitalize(tfunction->get_arglist()->get_members()[0]->get_name());
-    }
-  }
-  return name;
-}
-
-/**
- * Renders a Swift method argument list
- */
-string t_swift_generator::argument_list(t_struct* tstruct, string protocol_name, bool is_internal) {
-  string result = "";
-  bool include_protocol = !protocol_name.empty();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  
-  if (include_protocol) {
-    result += protocol_name + ": TProtocol";
-    if (!fields.empty()) {
-      result += ", ";
-    }
-  }
-  else if (!fields.empty() && is_internal) {
-    // Force first argument to be named
-    result += fields.front()->get_name() + " ";
-  }
-  
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    t_field* arg = *f_iter;
-    result += arg->get_name() + ": " + type_name(arg->get_type());
-    
-    if (++f_iter != fields.end()) {
-      result += ", ";
-    }
-  }
-  return result;
-}
-
-/**
- * https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html
- *
- */
-
-void t_swift_generator::populate_reserved_words() {
-  swift_reserved_words_.insert("Self");
-  swift_reserved_words_.insert("associatedtype");
-  swift_reserved_words_.insert("defer");
-  swift_reserved_words_.insert("deinit");
-  swift_reserved_words_.insert("dynamicType");
-  swift_reserved_words_.insert("enum");
-  swift_reserved_words_.insert("extension");
-  swift_reserved_words_.insert("fallthrough");
-  swift_reserved_words_.insert("false");
-  swift_reserved_words_.insert("func");
-  swift_reserved_words_.insert("guard");
-  swift_reserved_words_.insert("init");
-  swift_reserved_words_.insert("inout");
-  swift_reserved_words_.insert("internal");
-  swift_reserved_words_.insert("let");
-  swift_reserved_words_.insert("operator");
-  swift_reserved_words_.insert("protocol");
-  swift_reserved_words_.insert("repeat");
-  swift_reserved_words_.insert("rethrows");
-  swift_reserved_words_.insert("struct");
-  swift_reserved_words_.insert("subscript");
-  swift_reserved_words_.insert("throws");
-  swift_reserved_words_.insert("true");
-  swift_reserved_words_.insert("typealias");
-  swift_reserved_words_.insert("where");
-}
-
-string t_swift_generator::maybe_escape_identifier(const string& identifier) {
-  if (swift_reserved_words_.find(identifier) != swift_reserved_words_.end()) {
-    return "`" + identifier + "`";
-  }
-  return identifier;
-}
-
-/**
- * Converts the parse type to a Swift TType enumeration.
- */
-string t_swift_generator::type_to_enum(t_type* type, bool qualified) {
-  type = get_true_type(type);
-  
-  string result = qualified ? "TType." : ".";
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return result + "STRING";
-    case t_base_type::TYPE_BOOL:
-      return result + "BOOL";
-    case t_base_type::TYPE_I8:
-      return result + "BYTE";
-    case t_base_type::TYPE_I16:
-      return result + "I16";
-    case t_base_type::TYPE_I32:
-      return result + "I32";
-    case t_base_type::TYPE_I64:
-      return result + "I64";
-    case t_base_type::TYPE_DOUBLE:
-      return result + "DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return result + "I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return result + "STRUCT";
-  } else if (type->is_map()) {
-    return result + "MAP";
-  } else if (type->is_set()) {
-    return result + "SET";
-  } else if (type->is_list()) {
-    return result + "LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-
-THRIFT_REGISTER_GENERATOR(
-    swift,
-    "Swift",
-    "    log_unexpected:  Log every time an unexpected field ID or type is encountered.\n"
-    "    debug_descriptions:\n"
-    "                     Allow use of debugDescription so the app can add description via a cateogory/extension\n"
-    "    async_clients:   Generate clients which invoke asynchronously via block syntax.\n"
-    "    promise_kit:     Generate clients which invoke asynchronously via promises.\n")


[28/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_rb_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc
deleted file mode 100644
index abd3320..0000000
--- a/compiler/cpp/src/generate/t_rb_generator.cc
+++ /dev/null
@@ -1,1263 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <algorithm>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-
-#include "t_oop_generator.h"
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * A subclass of std::ofstream that includes indenting functionality.
- */
-class t_rb_ofstream : public std::ofstream {
-private:
-  int indent_;
-
-public:
-  t_rb_ofstream() : std::ofstream(), indent_(0) {}
-  explicit t_rb_ofstream(const char* filename,
-                         ios_base::openmode mode = ios_base::out,
-                         int indent = 0)
-    : std::ofstream(filename, mode), indent_(indent) {}
-
-  t_rb_ofstream& indent() {
-    for (int i = 0; i < indent_; ++i) {
-      *this << "  ";
-    }
-    return *this;
-  }
-
-  void indent_up() { indent_++; }
-  void indent_down() { indent_--; }
-};
-
-/**
- * Ruby code generator.
- *
- */
-class t_rb_generator : public t_oop_generator {
-public:
-  t_rb_generator(t_program* program,
-                 const std::map<std::string, std::string>& parsed_options,
-                 const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    require_rubygems_ = false;
-    namespaced_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("rubygems") == 0) {
-        require_rubygems_ = true;
-      } else if( iter->first.compare("namespaced") == 0) {
-        namespaced_ = true;
-      } else {
-        throw "unknown option ruby:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-rb";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_union(t_struct* tunion);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  t_rb_ofstream& render_const_value(t_rb_ofstream& out, t_type* type, t_const_value* value);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_rb_struct(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_rb_union(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_rb_union_validator(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_rb_function_helpers(t_function* tfunction);
-  void generate_rb_simple_constructor(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_rb_simple_exception_constructor(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_field_constants(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_field_constructors(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_field_defns(t_rb_ofstream& out, t_struct* tstruct);
-  void generate_field_data(t_rb_ofstream& out,
-                           t_type* field_type,
-                           const std::string& field_name,
-                           t_const_value* field_value,
-                           bool optional);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(t_rb_ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  bool inclass = false);
-
-  void generate_deserialize_struct(t_rb_ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(t_rb_ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(t_rb_ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(t_rb_ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(t_rb_ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(t_rb_ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(t_rb_ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(t_rb_ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(t_rb_ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(t_rb_ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(t_rb_ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_rdoc(t_rb_ofstream& out, t_doc* tdoc);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string rb_autogen_comment();
-  std::string render_require_thrift();
-  std::string render_includes();
-  std::string declare_field(t_field* tfield);
-  std::string type_name(const t_type* ttype);
-  std::string full_type_name(const t_type* ttype);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string rb_namespace_to_path_prefix(std::string rb_namespace);
-
-  std::vector<std::string> ruby_modules(const t_program* p) {
-    std::string ns = p->get_namespace("rb");
-    std::vector<std::string> modules;
-    if (ns.empty()) {
-      return modules;
-    }
-
-    std::string::iterator pos = ns.begin();
-    while (true) {
-      std::string::iterator delim = std::find(pos, ns.end(), '.');
-      modules.push_back(capitalize(std::string(pos, delim)));
-      pos = delim;
-      if (pos == ns.end()) {
-        break;
-      }
-      ++pos;
-    }
-
-    return modules;
-  }
-
-  void begin_namespace(t_rb_ofstream&, std::vector<std::string>);
-  void end_namespace(t_rb_ofstream&, std::vector<std::string>);
-
-private:
-  /**
-   * File streams
-   */
-
-  t_rb_ofstream f_types_;
-  t_rb_ofstream f_consts_;
-  t_rb_ofstream f_service_;
-
-  std::string namespace_dir_;
-  std::string require_prefix_;
-
-  /** If true, add a "require 'rubygems'" line to the top of each gen-rb file. */
-  bool require_rubygems_;
-
-  /** If true, generate files in idiomatic namespaced directories. */
-  bool namespaced_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_rb_generator::init_generator() {
-  string subdir = get_out_dir();
-
-  // Make output directory
-  MKDIR(subdir.c_str());
-
-  if (namespaced_) {
-    require_prefix_ = rb_namespace_to_path_prefix(program_->get_namespace("rb"));
-
-    string dir = require_prefix_;
-    string::size_type loc;
-
-    while ((loc = dir.find("/")) != string::npos) {
-      subdir = subdir + dir.substr(0, loc) + "/";
-      MKDIR(subdir.c_str());
-      dir = dir.substr(loc + 1);
-    }
-  }
-
-  namespace_dir_ = subdir;
-
-  // Make output file
-  string f_types_name = namespace_dir_ + underscore(program_name_) + "_types.rb";
-  f_types_.open(f_types_name.c_str());
-
-  string f_consts_name = namespace_dir_ + underscore(program_name_) + "_constants.rb";
-  f_consts_.open(f_consts_name.c_str());
-
-  // Print header
-  f_types_ << rb_autogen_comment() << endl << render_require_thrift() << render_includes() << endl;
-  begin_namespace(f_types_, ruby_modules(program_));
-
-  f_consts_ << rb_autogen_comment() << endl << render_require_thrift() << "require '"
-            << require_prefix_ << underscore(program_name_) << "_types'" << endl << endl;
-  begin_namespace(f_consts_, ruby_modules(program_));
-}
-
-/**
- * Renders the require of thrift itself, and possibly of the rubygems dependency.
- */
-string t_rb_generator::render_require_thrift() {
-  if (require_rubygems_) {
-    return "require 'rubygems'\nrequire 'thrift'\n";
-  } else {
-    return "require 'thrift'\n";
-  }
-}
-
-/**
- * Renders all the imports necessary for including another Thrift program
- */
-string t_rb_generator::render_includes() {
-  const vector<t_program*>& includes = program_->get_includes();
-  string result = "";
-  for (size_t i = 0; i < includes.size(); ++i) {
-    if (namespaced_) {
-      t_program* included = includes[i];
-      std::string included_require_prefix
-          = rb_namespace_to_path_prefix(included->get_namespace("rb"));
-      std::string included_name = included->get_name();
-      result += "require '" + included_require_prefix + underscore(included_name) + "_types'\n";
-    } else {
-      result += "require '" + underscore(includes[i]->get_name()) + "_types'\n";
-    }
-  }
-  if (includes.size() > 0) {
-    result += "\n";
-  }
-  return result;
-}
-
-/**
- * Autogen'd comment
- */
-string t_rb_generator::rb_autogen_comment() {
-  return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-         + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n";
-}
-
-/**
- * Closes the type files
- */
-void t_rb_generator::close_generator() {
-  // Close types file
-  end_namespace(f_types_, ruby_modules(program_));
-  end_namespace(f_consts_, ruby_modules(program_));
-  f_types_.close();
-  f_consts_.close();
-}
-
-/**
- * Generates a typedef. This is not done in Ruby, types are all implicit.
- *
- * @param ttypedef The type definition
- */
-void t_rb_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Generates code for an enumerated type. Done using a class to scope
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_rb_generator::generate_enum(t_enum* tenum) {
-  f_types_.indent() << "module " << capitalize(tenum->get_name()) << endl;
-  f_types_.indent_up();
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-
-    // Ruby class constants have to be capitalized... omg i am so on the fence
-    // about languages strictly enforcing capitalization why can't we just all
-    // agree and play nice.
-    string name = capitalize((*c_iter)->get_name());
-
-    generate_rdoc(f_types_, *c_iter);
-    f_types_.indent() << name << " = " << value << endl;
-  }
-
-  // Create a hash mapping values back to their names (as strings) since ruby has no native enum
-  // type
-  f_types_.indent() << "VALUE_MAP = {";
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    // Populate the hash
-    int value = (*c_iter)->get_value();
-    if (c_iter != constants.begin())
-      f_types_ << ", ";
-    f_types_ << value << " => \"" << capitalize((*c_iter)->get_name()) << "\"";
-  }
-  f_types_ << "}" << endl;
-
-  // Create a set with valid values for this enum
-  f_types_.indent() << "VALID_VALUES = Set.new([";
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    // Populate the set
-    if (c_iter != constants.begin())
-      f_types_ << ", ";
-    f_types_ << capitalize((*c_iter)->get_name());
-  }
-  f_types_ << "]).freeze" << endl;
-
-  f_types_.indent_down();
-  f_types_.indent() << "end" << endl << endl;
-}
-
-/**
- * Generate a constant value
- */
-void t_rb_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  name[0] = toupper(name[0]);
-
-  f_consts_.indent() << name << " = ";
-  render_const_value(f_consts_, type, value) << endl << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-t_rb_ofstream& t_rb_generator::render_const_value(t_rb_ofstream& out,
-                                                  t_type* type,
-                                                  t_const_value* value) {
-  type = get_true_type(type);
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << "%q\"" << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    out.indent() << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << full_type_name(type) << ".new({" << endl;
-    out.indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      out.indent();
-      render_const_value(out, g_type_string, v_iter->first) << " => ";
-      render_const_value(out, field_type, v_iter->second) << "," << endl;
-    }
-    out.indent_down();
-    out.indent() << "})";
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    out << "{" << endl;
-    out.indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out.indent();
-      render_const_value(out, ktype, v_iter->first) << " => ";
-      render_const_value(out, vtype, v_iter->second) << "," << endl;
-    }
-    out.indent_down();
-    out.indent() << "}";
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    if (type->is_set()) {
-      out << "Set.new([" << endl;
-    } else {
-      out << "[" << endl;
-    }
-    out.indent_up();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out.indent();
-      render_const_value(out, etype, *v_iter) << "," << endl;
-    }
-    out.indent_down();
-    if (type->is_set()) {
-      out.indent() << "])";
-    } else {
-      out.indent() << "]";
-    }
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-  return out;
-}
-
-/**
- * Generates a ruby struct
- */
-void t_rb_generator::generate_struct(t_struct* tstruct) {
-  if (tstruct->is_union()) {
-    generate_rb_union(f_types_, tstruct, false);
-  } else {
-    generate_rb_struct(f_types_, tstruct, false);
-  }
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_rb_generator::generate_xception(t_struct* txception) {
-  generate_rb_struct(f_types_, txception, true);
-}
-
-/**
- * Generates a ruby struct
- */
-void t_rb_generator::generate_rb_struct(t_rb_ofstream& out,
-                                        t_struct* tstruct,
-                                        bool is_exception = false) {
-  generate_rdoc(out, tstruct);
-  out.indent() << "class " << type_name(tstruct);
-  if (is_exception) {
-    out << " < ::Thrift::Exception";
-  }
-  out << endl;
-
-  out.indent_up();
-  out.indent() << "include ::Thrift::Struct, ::Thrift::Struct_Union" << endl;
-
-  if (is_exception) {
-    generate_rb_simple_exception_constructor(out, tstruct);
-  }
-
-  generate_field_constants(out, tstruct);
-  generate_field_defns(out, tstruct);
-  generate_rb_struct_required_validator(out, tstruct);
-
-  out.indent() << "::Thrift::Struct.generate_accessors self" << endl;
-
-  out.indent_down();
-  out.indent() << "end" << endl << endl;
-}
-
-/**
- * Generates a ruby union
- */
-void t_rb_generator::generate_rb_union(t_rb_ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_exception = false) {
-  (void)is_exception;
-  generate_rdoc(out, tstruct);
-  out.indent() << "class " << type_name(tstruct) << " < ::Thrift::Union" << endl;
-
-  out.indent_up();
-  out.indent() << "include ::Thrift::Struct_Union" << endl;
-
-  generate_field_constructors(out, tstruct);
-
-  generate_field_constants(out, tstruct);
-  generate_field_defns(out, tstruct);
-  generate_rb_union_validator(out, tstruct);
-
-  out.indent() << "::Thrift::Union.generate_accessors self" << endl;
-
-  out.indent_down();
-  out.indent() << "end" << endl << endl;
-}
-
-void t_rb_generator::generate_field_constructors(t_rb_ofstream& out, t_struct* tstruct) {
-
-  out.indent() << "class << self" << endl;
-  out.indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (f_iter != fields.begin()) {
-      out << endl;
-    }
-    std::string field_name = (*f_iter)->get_name();
-
-    out.indent() << "def " << field_name << "(val)" << endl;
-    out.indent() << "  " << tstruct->get_name() << ".new(:" << field_name << ", val)" << endl;
-    out.indent() << "end" << endl;
-  }
-
-  out.indent_down();
-  out.indent() << "end" << endl;
-
-  out << endl;
-}
-
-void t_rb_generator::generate_rb_simple_exception_constructor(t_rb_ofstream& out,
-                                                              t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-
-  if (members.size() == 1) {
-    vector<t_field*>::const_iterator m_iter = members.begin();
-
-    if ((*m_iter)->get_type()->is_string()) {
-      string name = (*m_iter)->get_name();
-
-      out.indent() << "def initialize(message=nil)" << endl;
-      out.indent_up();
-      out.indent() << "super()" << endl;
-      out.indent() << "self." << name << " = message" << endl;
-      out.indent_down();
-      out.indent() << "end" << endl << endl;
-
-      if (name != "message") {
-        out.indent() << "def message; " << name << " end" << endl << endl;
-      }
-    }
-  }
-}
-
-void t_rb_generator::generate_field_constants(t_rb_ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    std::string field_name = (*f_iter)->get_name();
-    std::string cap_field_name = upcase_string(field_name);
-
-    out.indent() << cap_field_name << " = " << (*f_iter)->get_key() << endl;
-  }
-  out << endl;
-}
-
-void t_rb_generator::generate_field_defns(t_rb_ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out.indent() << "FIELDS = {" << endl;
-  out.indent_up();
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (f_iter != fields.begin()) {
-      out << "," << endl;
-    }
-
-    // generate the field docstrings within the FIELDS constant. no real better place...
-    generate_rdoc(out, *f_iter);
-
-    out.indent() << upcase_string((*f_iter)->get_name()) << " => ";
-
-    generate_field_data(out,
-                        (*f_iter)->get_type(),
-                        (*f_iter)->get_name(),
-                        (*f_iter)->get_value(),
-                        (*f_iter)->get_req() == t_field::T_OPTIONAL);
-  }
-  out.indent_down();
-  out << endl;
-  out.indent() << "}" << endl << endl;
-
-  out.indent() << "def struct_fields; FIELDS; end" << endl << endl;
-}
-
-void t_rb_generator::generate_field_data(t_rb_ofstream& out,
-                                         t_type* field_type,
-                                         const std::string& field_name = "",
-                                         t_const_value* field_value = NULL,
-                                         bool optional = false) {
-  field_type = get_true_type(field_type);
-
-  // Begin this field's defn
-  out << "{:type => " << type_to_enum(field_type);
-
-  if (!field_name.empty()) {
-    out << ", :name => '" << field_name << "'";
-  }
-
-  if (field_value != NULL) {
-    out << ", :default => ";
-    render_const_value(out, field_type, field_value);
-  }
-
-  if (!field_type->is_base_type()) {
-    if (field_type->is_struct() || field_type->is_xception()) {
-      out << ", :class => " << full_type_name((t_struct*)field_type);
-    } else if (field_type->is_list()) {
-      out << ", :element => ";
-      generate_field_data(out, ((t_list*)field_type)->get_elem_type());
-    } else if (field_type->is_map()) {
-      out << ", :key => ";
-      generate_field_data(out, ((t_map*)field_type)->get_key_type());
-      out << ", :value => ";
-      generate_field_data(out, ((t_map*)field_type)->get_val_type());
-    } else if (field_type->is_set()) {
-      out << ", :element => ";
-      generate_field_data(out, ((t_set*)field_type)->get_elem_type());
-    }
-  } else {
-    if (((t_base_type*)field_type)->is_binary()) {
-      out << ", :binary => true";
-    }
-  }
-
-  if (optional) {
-    out << ", :optional => true";
-  }
-
-  if (field_type->is_enum()) {
-    out << ", :enum_class => " << full_type_name(field_type);
-  }
-
-  // End of this field's defn
-  out << "}";
-}
-
-void t_rb_generator::begin_namespace(t_rb_ofstream& out, vector<std::string> modules) {
-  for (vector<std::string>::iterator m_iter = modules.begin(); m_iter != modules.end(); ++m_iter) {
-    out.indent() << "module " << *m_iter << endl;
-    out.indent_up();
-  }
-}
-
-void t_rb_generator::end_namespace(t_rb_ofstream& out, vector<std::string> modules) {
-  for (vector<std::string>::reverse_iterator m_iter = modules.rbegin(); m_iter != modules.rend();
-       ++m_iter) {
-    out.indent_down();
-    out.indent() << "end" << endl;
-  }
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_rb_generator::generate_service(t_service* tservice) {
-  string f_service_name = namespace_dir_ + underscore(service_name_) + ".rb";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << rb_autogen_comment() << endl << render_require_thrift();
-
-  if (tservice->get_extends() != NULL) {
-    if (namespaced_) {
-      f_service_ << "require '" << rb_namespace_to_path_prefix(
-                                       tservice->get_extends()->get_program()->get_namespace("rb"))
-                 << underscore(tservice->get_extends()->get_name()) << "'" << endl;
-    } else {
-      f_service_ << "require '" << require_prefix_
-                 << underscore(tservice->get_extends()->get_name()) << "'" << endl;
-    }
-  }
-
-  f_service_ << "require '" << require_prefix_ << underscore(program_name_) << "_types'" << endl
-             << endl;
-
-  begin_namespace(f_service_, ruby_modules(tservice->get_program()));
-
-  f_service_.indent() << "module " << capitalize(tservice->get_name()) << endl;
-  f_service_.indent_up();
-
-  // Generate the three main parts of the service (well, two for now in PHP)
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-
-  f_service_.indent_down();
-  f_service_.indent() << "end" << endl << endl;
-
-  end_namespace(f_service_, ruby_modules(tservice->get_program()));
-
-  // Close service file
-  f_service_.close();
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_rb_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  f_service_.indent() << "# HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_rb_struct(f_service_, ts);
-    generate_rb_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_rb_generator::generate_rb_function_helpers(t_function* tfunction) {
-  t_struct result(program_, tfunction->get_name() + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-  generate_rb_struct(f_service_, &result);
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_rb_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = full_type_name(tservice->get_extends());
-    extends_client = " < " + extends + "::Client ";
-  }
-
-  f_service_.indent() << "class Client" << extends_client << endl;
-  f_service_.indent_up();
-
-  f_service_.indent() << "include ::Thrift::Client" << endl << endl;
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    f_service_.indent() << "def " << function_signature(*f_iter) << endl;
-    f_service_.indent_up();
-    f_service_.indent() << "send_" << funname << "(";
-
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << (*fld_iter)->get_name();
-    }
-    f_service_ << ")" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_service_.indent();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
-      }
-      f_service_ << "recv_" << funname << "()" << endl;
-    }
-    f_service_.indent_down();
-    f_service_.indent() << "end" << endl;
-    f_service_ << endl;
-
-    f_service_.indent() << "def send_" << function_signature(*f_iter) << endl;
-    f_service_.indent_up();
-
-    std::string argsname = capitalize((*f_iter)->get_name() + "_args");
-    std::string messageSendProc = (*f_iter)->is_oneway() ? "send_oneway_message" : "send_message";
-
-    f_service_.indent() << messageSendProc << "('" << funname << "', " << argsname;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << ", :" << (*fld_iter)->get_name() << " => " << (*fld_iter)->get_name();
-    }
-
-    f_service_ << ")" << endl;
-
-    f_service_.indent_down();
-    f_service_.indent() << "end" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = capitalize((*f_iter)->get_name() + "_result");
-      t_struct noargs(program_);
-
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs);
-      // Open function
-      f_service_ << endl;
-      f_service_.indent() << "def " << function_signature(&recv_function) << endl;
-      f_service_.indent_up();
-
-      // TODO(mcslee): Validate message reply here, seq ids etc.
-
-      f_service_.indent() << "result = receive_message(" << resultname << ")" << endl;
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_.indent() << "return result.success unless result.success.nil?" << endl;
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_.indent() << "raise result." << (*x_iter)->get_name() << " unless result."
-                            << (*x_iter)->get_name() << ".nil?" << endl;
-      }
-
-      // Careful, only return _result if not a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        f_service_.indent() << "return" << endl;
-      } else {
-        f_service_.indent() << "raise "
-                               "::Thrift::ApplicationException.new(::Thrift::ApplicationException::"
-                               "MISSING_RESULT, '" << (*f_iter)->get_name()
-                            << " failed: unknown result')" << endl;
-      }
-
-      // Close function
-      f_service_.indent_down();
-      f_service_.indent() << "end" << endl << endl;
-    }
-  }
-
-  f_service_.indent_down();
-  f_service_.indent() << "end" << endl << endl;
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_rb_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = full_type_name(tservice->get_extends());
-    extends_processor = " < " + extends + "::Processor ";
-  }
-
-  // Generate the header portion
-  f_service_.indent() << "class Processor" << extends_processor << endl;
-  f_service_.indent_up();
-
-  f_service_.indent() << "include ::Thrift::Processor" << endl << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  f_service_.indent_down();
-  f_service_.indent() << "end" << endl << endl;
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_rb_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open function
-  f_service_.indent() << "def process_" << tfunction->get_name() << "(seqid, iprot, oprot)" << endl;
-  f_service_.indent_up();
-
-  string argsname = capitalize(tfunction->get_name()) + "_args";
-  string resultname = capitalize(tfunction->get_name()) + "_result";
-
-  f_service_.indent() << "args = read_args(iprot, " << argsname << ")" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_.indent() << "result = " << resultname << ".new()" << endl;
-  }
-
-  // Try block for a function with exceptions
-  if (xceptions.size() > 0) {
-    f_service_.indent() << "begin" << endl;
-    f_service_.indent_up();
-  }
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_.indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "result.success = ";
-  }
-  f_service_ << "@handler." << tfunction->get_name() << "(";
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_service_ << ", ";
-    }
-    f_service_ << "args." << (*f_iter)->get_name();
-  }
-  f_service_ << ")" << endl;
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    f_service_.indent_down();
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_.indent() << "rescue " << full_type_name((*x_iter)->get_type()) << " => "
-                          << (*x_iter)->get_name() << endl;
-      if (!tfunction->is_oneway()) {
-        f_service_.indent_up();
-        f_service_.indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name()
-                            << endl;
-        f_service_.indent_down();
-      }
-    }
-    f_service_.indent() << "end" << endl;
-  }
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    f_service_.indent() << "return" << endl;
-    f_service_.indent_down();
-    f_service_.indent() << "end" << endl << endl;
-    return;
-  }
-
-  f_service_.indent() << "write_result(result, oprot, '" << tfunction->get_name() << "', seqid)"
-                      << endl;
-
-  // Close function
-  f_service_.indent_down();
-  f_service_.indent() << "end" << endl << endl;
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_rb_generator::function_signature(t_function* tfunction, string prefix) {
-  // TODO(mcslee): Nitpicky, no ',' if argument_list is empty
-  return prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")";
-}
-
-/**
- * Renders a field list
- */
-string t_rb_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    result += (*f_iter)->get_name();
-  }
-  return result;
-}
-
-string t_rb_generator::type_name(const t_type* ttype) {
-  string prefix = "";
-
-  string name = ttype->get_name();
-  if (ttype->is_struct() || ttype->is_xception() || ttype->is_enum()) {
-    name = capitalize(ttype->get_name());
-  }
-
-  return prefix + name;
-}
-
-string t_rb_generator::full_type_name(const t_type* ttype) {
-  string prefix = "::";
-  vector<std::string> modules = ruby_modules(ttype->get_program());
-  for (vector<std::string>::iterator m_iter = modules.begin(); m_iter != modules.end(); ++m_iter) {
-    prefix += *m_iter + "::";
-  }
-  return prefix + type_name(ttype);
-}
-
-/**
- * Converts the parse type to a Ruby tyoe
- */
-string t_rb_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "::Thrift::Types::STRING";
-    case t_base_type::TYPE_BOOL:
-      return "::Thrift::Types::BOOL";
-    case t_base_type::TYPE_I8:
-      return "::Thrift::Types::BYTE";
-    case t_base_type::TYPE_I16:
-      return "::Thrift::Types::I16";
-    case t_base_type::TYPE_I32:
-      return "::Thrift::Types::I32";
-    case t_base_type::TYPE_I64:
-      return "::Thrift::Types::I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "::Thrift::Types::DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "::Thrift::Types::I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "::Thrift::Types::STRUCT";
-  } else if (type->is_map()) {
-    return "::Thrift::Types::MAP";
-  } else if (type->is_set()) {
-    return "::Thrift::Types::SET";
-  } else if (type->is_list()) {
-    return "::Thrift::Types::LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-string t_rb_generator::rb_namespace_to_path_prefix(string rb_namespace) {
-  string namespaces_left = rb_namespace;
-  string::size_type loc;
-
-  string path_prefix = "";
-
-  while ((loc = namespaces_left.find(".")) != string::npos) {
-    path_prefix = path_prefix + underscore(namespaces_left.substr(0, loc)) + "/";
-    namespaces_left = namespaces_left.substr(loc + 1);
-  }
-  if (namespaces_left.size() > 0) {
-    path_prefix = path_prefix + underscore(namespaces_left) + "/";
-  }
-  return path_prefix;
-}
-
-void t_rb_generator::generate_rdoc(t_rb_ofstream& out, t_doc* tdoc) {
-  if (tdoc->has_doc()) {
-    out.indent();
-    generate_docstring_comment(out, "", "# ", tdoc->get_doc(), "");
-  }
-}
-
-void t_rb_generator::generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct) {
-  out.indent() << "def validate" << endl;
-  out.indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = (*f_iter);
-    if (field->get_req() == t_field::T_REQUIRED) {
-      out.indent() << "raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, "
-                      "'Required field " << field->get_name() << " is unset!')";
-      if (field->get_type()->is_bool()) {
-        out << " if @" << field->get_name() << ".nil?";
-      } else {
-        out << " unless @" << field->get_name();
-      }
-      out << endl;
-    }
-  }
-
-  // if field is an enum, check that its value is valid
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = (*f_iter);
-
-    if (field->get_type()->is_enum()) {
-      out.indent() << "unless @" << field->get_name() << ".nil? || "
-                   << full_type_name(field->get_type()) << "::VALID_VALUES.include?(@"
-                   << field->get_name() << ")" << endl;
-      out.indent_up();
-      out.indent() << "raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, "
-                      "'Invalid value of field " << field->get_name() << "!')" << endl;
-      out.indent_down();
-      out.indent() << "end" << endl;
-    }
-  }
-
-  out.indent_down();
-  out.indent() << "end" << endl << endl;
-}
-
-void t_rb_generator::generate_rb_union_validator(t_rb_ofstream& out, t_struct* tstruct) {
-  out.indent() << "def validate" << endl;
-  out.indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out.indent()
-      << "raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil?"
-      << endl;
-
-  // if field is an enum, check that its value is valid
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    const t_field* field = (*f_iter);
-
-    if (field->get_type()->is_enum()) {
-      out.indent() << "if get_set_field == :" << field->get_name() << endl;
-      out.indent() << "  raise "
-                      "::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, "
-                      "'Invalid value of field " << field->get_name() << "!') unless "
-                   << full_type_name(field->get_type()) << "::VALID_VALUES.include?(get_value)"
-                   << endl;
-      out.indent() << "end" << endl;
-    }
-  }
-
-  out.indent_down();
-  out.indent() << "end" << endl << endl;
-}
-
-THRIFT_REGISTER_GENERATOR(
-    rb,
-    "Ruby",
-    "    rubygems:        Add a \"require 'rubygems'\" line to the top of each generated file.\n"
-    "    namespaced:      Generate files in idiomatic namespaced directories.\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_st_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_st_generator.cc b/compiler/cpp/src/generate/t_st_generator.cc
deleted file mode 100644
index bc15d24..0000000
--- a/compiler/cpp/src/generate/t_st_generator.cc
+++ /dev/null
@@ -1,1055 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Smalltalk code generator.
- *
- */
-class t_st_generator : public t_oop_generator {
-public:
-  t_st_generator(t_program* program,
-                 const std::map<std::string, std::string>& parsed_options,
-                 const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option st:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-st";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-  void generate_class_side_definition();
-  void generate_force_consts();
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_st_struct(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_accessors(std::ofstream& out, t_struct* tstruct);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_client(t_service* tservice);
-
-  void generate_send_method(t_function* tfunction);
-  void generate_recv_method(t_function* tfunction);
-
-  std::string map_reader(t_map* tmap);
-  std::string list_reader(t_list* tlist);
-  std::string set_reader(t_set* tset);
-  std::string struct_reader(t_struct* tstruct, std::string clsName);
-
-  std::string map_writer(t_map* tmap, std::string name);
-  std::string list_writer(t_list* tlist, std::string name);
-  std::string set_writer(t_set* tset, std::string name);
-  std::string struct_writer(t_struct* tstruct, std::string fname);
-
-  std::string write_val(t_type* t, std::string fname);
-  std::string read_val(t_type* t);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string st_autogen_comment();
-
-  void st_class_def(std::ofstream& out, std::string name);
-  void st_method(std::ofstream& out, std::string cls, std::string name);
-  void st_method(std::ofstream& out, std::string cls, std::string name, std::string category);
-  void st_close_method(std::ofstream& out);
-  void st_class_method(std::ofstream& out, std::string cls, std::string name);
-  void st_class_method(std::ofstream& out, std::string cls, std::string name, std::string category);
-  void st_setter(std::ofstream& out, std::string cls, std::string name, std::string type);
-  void st_getter(std::ofstream& out, std::string cls, std::string name);
-  void st_accessors(std::ofstream& out, std::string cls, std::string name, std::string type);
-
-  std::string class_name();
-  static bool is_valid_namespace(const std::string& sub_namespace);
-  std::string client_class_name();
-  std::string prefix(std::string name);
-  std::string declare_field(t_field* tfield);
-  std::string type_name(t_type* ttype);
-
-  std::string function_signature(t_function* tfunction);
-  std::string argument_list(t_struct* tstruct);
-  std::string function_types_comment(t_function* fn);
-
-  std::string type_to_enum(t_type* ttype);
-  std::string a_type(t_type* type);
-  bool is_vowel(char c);
-  std::string temp_name();
-  std::string generated_category();
-
-private:
-  /**
-   * File streams
-   */
-  int temporary_var;
-  std::ofstream f_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_st_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  temporary_var = 0;
-
-  // Make output file
-  string f_name = get_out_dir() + "/" + program_name_ + ".st";
-  f_.open(f_name.c_str());
-
-  // Print header
-  f_ << st_autogen_comment() << endl;
-
-  st_class_def(f_, program_name_);
-  generate_class_side_definition();
-
-  // Generate enums
-  vector<t_enum*> enums = program_->get_enums();
-  vector<t_enum*>::iterator en_iter;
-  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-    generate_enum(*en_iter);
-  }
-}
-
-string t_st_generator::class_name() {
-  return capitalize(program_name_);
-}
-
-bool t_st_generator::is_valid_namespace(const std::string& sub_namespace) {
-  return sub_namespace == "prefix" || sub_namespace == "category";
-}
-
-string t_st_generator::prefix(string class_name) {
-  string prefix = program_->get_namespace("smalltalk.prefix");
-  string name = capitalize(class_name);
-  name = prefix.empty() ? name : (prefix + name);
-  return name;
-}
-
-string t_st_generator::client_class_name() {
-  return capitalize(service_name_) + "Client";
-}
-
-/**
- * Autogen'd comment
- */
-string t_st_generator::st_autogen_comment() {
-  return std::string("'") + "Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "\n"
-         + "DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "'!\n";
-}
-
-void t_st_generator::generate_force_consts() {
-  f_ << prefix(class_name()) << " enums keysAndValuesDo: [:k :v | " << prefix(class_name())
-     << " enums at: k put: v value].!" << endl;
-
-  f_ << prefix(class_name()) << " constants keysAndValuesDo: [:k :v | " << prefix(class_name())
-     << " constants at: k put: v value].!" << endl;
-}
-
-void t_st_generator::close_generator() {
-  generate_force_consts();
-  f_.close();
-}
-
-string t_st_generator::generated_category() {
-  string cat = program_->get_namespace("smalltalk.category");
-  // For compatibility with the Thrift grammar, the category must
-  // be punctuated by dots.  Replaces them with dashes here.
-  for (string::iterator iter = cat.begin(); iter != cat.end(); ++iter) {
-    if (*iter == '.') {
-      *iter = '-';
-    }
-  }
-  return cat.size() ? cat : "Generated-" + class_name();
-}
-
-/**
- * Generates a typedef. This is not done in Smalltalk, types are all implicit.
- *
- * @param ttypedef The type definition
- */
-void t_st_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-void t_st_generator::st_class_def(std::ofstream& out, string name) {
-  out << "Object subclass: #" << prefix(name) << endl;
-  indent_up();
-  out << indent() << "instanceVariableNames: ''" << endl << indent() << "classVariableNames: ''"
-      << endl << indent() << "poolDictionaries: ''" << endl << indent() << "category: '"
-      << generated_category() << "'!" << endl << endl;
-}
-
-void t_st_generator::st_method(std::ofstream& out, string cls, string name) {
-  st_method(out, cls, name, "as yet uncategorized");
-}
-
-void t_st_generator::st_class_method(std::ofstream& out, string cls, string name) {
-  st_method(out, cls + " class", name);
-}
-
-void t_st_generator::st_class_method(std::ofstream& out, string cls, string name, string category) {
-  st_method(out, cls, name, category);
-}
-
-void t_st_generator::st_method(std::ofstream& out, string cls, string name, string category) {
-  char timestr[50];
-  time_t rawtime;
-  struct tm* tinfo;
-
-  time(&rawtime);
-  tinfo = localtime(&rawtime);
-  strftime(timestr, 50, "%m/%d/%Y %H:%M", tinfo);
-
-  out << "!" << prefix(cls) << " methodsFor: '" + category + "' stamp: 'thrift " << timestr
-      << "'!\n" << name << endl;
-
-  indent_up();
-  out << indent();
-}
-
-void t_st_generator::st_close_method(std::ofstream& out) {
-  out << "! !" << endl << endl;
-  indent_down();
-}
-
-void t_st_generator::st_setter(std::ofstream& out,
-                               string cls,
-                               string name,
-                               string type = "anObject") {
-  st_method(out, cls, name + ": " + type);
-  out << name << " := " + type;
-  st_close_method(out);
-}
-
-void t_st_generator::st_getter(std::ofstream& out, string cls, string name) {
-  st_method(out, cls, name + "");
-  out << "^ " << name;
-  st_close_method(out);
-}
-
-void t_st_generator::st_accessors(std::ofstream& out,
-                                  string cls,
-                                  string name,
-                                  string type = "anObject") {
-  st_setter(out, cls, name, type);
-  st_getter(out, cls, name);
-}
-
-void t_st_generator::generate_class_side_definition() {
-  f_ << prefix(class_name()) << " class" << endl << "\tinstanceVariableNames: 'constants enums'!"
-     << endl << endl;
-
-  st_accessors(f_, class_name() + " class", "enums");
-  st_accessors(f_, class_name() + " class", "constants");
-
-  f_ << prefix(class_name()) << " enums: Dictionary new!" << endl;
-  f_ << prefix(class_name()) << " constants: Dictionary new!" << endl;
-
-  f_ << endl;
-}
-
-/**
- * Generates code for an enumerated type. Done using a class to scope
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_st_generator::generate_enum(t_enum* tenum) {
-  string cls_name = program_name_ + capitalize(tenum->get_name());
-
-  f_ << prefix(class_name()) << " enums at: '" << tenum->get_name() << "' put: ["
-     << "(Dictionary new " << endl;
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    f_ << "\tat: '" << (*c_iter)->get_name() << "' put: " << value << ";" << endl;
-  }
-
-  f_ << "\tyourself)]!" << endl << endl;
-}
-
-/**
- * Generate a constant value
- */
-void t_st_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  f_ << prefix(class_name()) << " constants at: '" << name << "' put: ["
-     << render_const_value(type, value) << "]!" << endl << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_st_generator::render_const_value(t_type* type, t_const_value* value) {
-  type = get_true_type(type);
-  std::ostringstream out;
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    indent(out) << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << "(" << capitalize(type->get_name()) << " new " << endl;
-    indent_up();
-
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-
-      out << indent() << v_iter->first->get_string() << ": "
-          << render_const_value(field_type, v_iter->second) << ";" << endl;
-    }
-    out << indent() << "yourself)";
-
-    indent_down();
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    out << "(Dictionary new" << endl;
-    indent_up();
-    indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent() << indent();
-      out << "at: " << render_const_value(ktype, v_iter->first);
-      out << " put: ";
-      out << render_const_value(vtype, v_iter->second);
-      out << ";" << endl;
-    }
-    out << indent() << indent() << "yourself)";
-    indent_down();
-    indent_down();
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    if (type->is_set()) {
-      out << "(Set new" << endl;
-    } else {
-      out << "(OrderedCollection new" << endl;
-    }
-    indent_up();
-    indent_up();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent() << indent();
-      out << "add: " << render_const_value(etype, *v_iter);
-      out << ";" << endl;
-    }
-    out << indent() << indent() << "yourself)";
-    indent_down();
-    indent_down();
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-  return out.str();
-}
-
-/**
- * Generates a Smalltalk struct
- */
-void t_st_generator::generate_struct(t_struct* tstruct) {
-  generate_st_struct(f_, tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_st_generator::generate_xception(t_struct* txception) {
-  generate_st_struct(f_, txception, true);
-}
-
-/**
- * Generates a smalltalk class to represent a struct
- */
-void t_st_generator::generate_st_struct(std::ofstream& out,
-                                        t_struct* tstruct,
-                                        bool is_exception = false) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  if (is_exception)
-    out << "Error";
-  else
-    out << "Object";
-
-  out << " subclass: #" << prefix(type_name(tstruct)) << endl << "\tinstanceVariableNames: '";
-
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (m_iter != members.begin())
-        out << " ";
-      out << camelcase((*m_iter)->get_name());
-    }
-  }
-
-  out << "'\n"
-      << "\tclassVariableNames: ''\n"
-      << "\tpoolDictionaries: ''\n"
-      << "\tcategory: '" << generated_category() << "'!\n\n";
-
-  generate_accessors(out, tstruct);
-}
-
-bool t_st_generator::is_vowel(char c) {
-  switch (tolower(c)) {
-  case 'a':
-  case 'e':
-  case 'i':
-  case 'o':
-  case 'u':
-    return true;
-  }
-  return false;
-}
-
-string t_st_generator::a_type(t_type* type) {
-  string prefix;
-
-  if (is_vowel(type_name(type)[0]))
-    prefix = "an";
-  else
-    prefix = "a";
-
-  return prefix + capitalize(type_name(type));
-}
-
-void t_st_generator::generate_accessors(std::ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  string type;
-  string prefix;
-
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      st_accessors(out,
-                   capitalize(type_name(tstruct)),
-                   camelcase((*m_iter)->get_name()),
-                   a_type((*m_iter)->get_type()));
-    }
-    out << endl;
-  }
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_st_generator::generate_service(t_service* tservice) {
-  generate_service_client(tservice);
-  // generate_service_server(tservice);
-}
-
-string t_st_generator::temp_name() {
-  std::ostringstream out;
-  out << "temp" << temporary_var++;
-  return out.str();
-}
-
-string t_st_generator::map_writer(t_map* tmap, string fname) {
-  std::ostringstream out;
-  string key = temp_name();
-  string val = temp_name();
-
-  out << "[oprot writeMapBegin: (TMap new keyType: " << type_to_enum(tmap->get_key_type())
-      << "; valueType: " << type_to_enum(tmap->get_val_type()) << "; size: " << fname << " size)."
-      << endl;
-  indent_up();
-
-  out << indent() << fname << " keysAndValuesDo: [:" << key << " :" << val << " |" << endl;
-  indent_up();
-
-  out << indent() << write_val(tmap->get_key_type(), key) << "." << endl << indent()
-      << write_val(tmap->get_val_type(), val);
-  indent_down();
-
-  out << "]." << endl << indent() << "oprot writeMapEnd] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::map_reader(t_map* tmap) {
-  std::ostringstream out;
-  string desc = temp_name();
-  string val = temp_name();
-
-  out << "[|" << desc << " " << val << "| " << endl;
-  indent_up();
-
-  out << indent() << desc << " := iprot readMapBegin." << endl << indent() << val
-      << " := Dictionary new." << endl << indent() << desc << " size timesRepeat: [" << endl;
-
-  indent_up();
-  out << indent() << val << " at: " << read_val(tmap->get_key_type())
-      << " put: " << read_val(tmap->get_val_type());
-  indent_down();
-
-  out << "]." << endl << indent() << "iprot readMapEnd." << endl << indent() << val << "] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::list_writer(t_list* tlist, string fname) {
-  std::ostringstream out;
-  string val = temp_name();
-
-  out << "[oprot writeListBegin: (TList new elemType: " << type_to_enum(tlist->get_elem_type())
-      << "; size: " << fname << " size)." << endl;
-  indent_up();
-
-  out << indent() << fname << " do: [:" << val << "|" << endl;
-  indent_up();
-
-  out << indent() << write_val(tlist->get_elem_type(), val) << endl;
-  indent_down();
-
-  out << "]." << endl << indent() << "oprot writeListEnd] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::list_reader(t_list* tlist) {
-  std::ostringstream out;
-  string desc = temp_name();
-  string val = temp_name();
-
-  out << "[|" << desc << " " << val << "| " << desc << " := iprot readListBegin." << endl;
-  indent_up();
-
-  out << indent() << val << " := OrderedCollection new." << endl << indent() << desc
-      << " size timesRepeat: [" << endl;
-
-  indent_up();
-  out << indent() << val << " add: " << read_val(tlist->get_elem_type());
-  indent_down();
-
-  out << "]." << endl << indent() << "iprot readListEnd." << endl << indent() << val << "] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::set_writer(t_set* tset, string fname) {
-  std::ostringstream out;
-  string val = temp_name();
-
-  out << "[oprot writeSetBegin: (TSet new elemType: " << type_to_enum(tset->get_elem_type())
-      << "; size: " << fname << " size)." << endl;
-  indent_up();
-
-  out << indent() << fname << " do: [:" << val << "|" << endl;
-  indent_up();
-
-  out << indent() << write_val(tset->get_elem_type(), val) << endl;
-  indent_down();
-
-  out << "]." << endl << indent() << "oprot writeSetEnd] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::set_reader(t_set* tset) {
-  std::ostringstream out;
-  string desc = temp_name();
-  string val = temp_name();
-
-  out << "[|" << desc << " " << val << "| " << desc << " := iprot readSetBegin." << endl;
-  indent_up();
-
-  out << indent() << val << " := Set new." << endl << indent() << desc << " size timesRepeat: ["
-      << endl;
-
-  indent_up();
-  out << indent() << val << " add: " << read_val(tset->get_elem_type());
-  indent_down();
-
-  out << "]." << endl << indent() << "iprot readSetEnd." << endl << indent() << val << "] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::struct_writer(t_struct* tstruct, string sname) {
-  std::ostringstream out;
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator fld_iter;
-
-  out << "[oprot writeStructBegin: "
-      << "(TStruct new name: '" + tstruct->get_name() + "')." << endl;
-  indent_up();
-
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-    bool optional = (*fld_iter)->get_req() == t_field::T_OPTIONAL;
-    string fname = camelcase((*fld_iter)->get_name());
-    string accessor = sname + " " + camelcase(fname);
-
-    if (optional) {
-      out << indent() << accessor << " ifNotNil: [" << endl;
-      indent_up();
-    }
-
-    out << indent() << "oprot writeFieldBegin: (TField new name: '" << fname
-        << "'; type: " << type_to_enum((*fld_iter)->get_type())
-        << "; id: " << (*fld_iter)->get_key() << ")." << endl;
-
-    out << indent() << write_val((*fld_iter)->get_type(), accessor) << "." << endl << indent()
-        << "oprot writeFieldEnd";
-
-    if (optional) {
-      out << "]";
-      indent_down();
-    }
-
-    out << "." << endl;
-  }
-
-  out << indent() << "oprot writeFieldStop; writeStructEnd] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::struct_reader(t_struct* tstruct, string clsName = "") {
-  std::ostringstream out;
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator fld_iter;
-  string val = temp_name();
-  string desc = temp_name();
-  string found = temp_name();
-
-  if (clsName.size() == 0) {
-    clsName = tstruct->get_name();
-  }
-
-  out << "[|" << desc << " " << val << "|" << endl;
-  indent_up();
-
-  // This is nasty, but without it we'll break things by prefixing TResult.
-  string name = ((capitalize(clsName) == "TResult") ? capitalize(clsName) : prefix(clsName));
-  out << indent() << val << " := " << name << " new." << endl;
-
-  out << indent() << "iprot readStructBegin." << endl << indent() << "[" << desc
-      << " := iprot readFieldBegin." << endl << indent() << desc
-      << " type = TType stop] whileFalse: [|" << found << "|" << endl;
-  indent_up();
-
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-    out << indent() << desc << " id = " << (*fld_iter)->get_key() << " ifTrue: [" << endl;
-    indent_up();
-
-    out << indent() << found << " := true." << endl << indent() << val << " "
-        << camelcase((*fld_iter)->get_name()) << ": " << read_val((*fld_iter)->get_type());
-    indent_down();
-
-    out << "]." << endl;
-  }
-
-  out << indent() << found << " ifNil: [iprot skip: " << desc << " type]]." << endl;
-  indent_down();
-
-  out << indent() << "oprot readStructEnd." << endl << indent() << val << "] value";
-  indent_down();
-
-  return out.str();
-}
-
-string t_st_generator::write_val(t_type* t, string fname) {
-  t = get_true_type(t);
-
-  if (t->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_DOUBLE:
-      return "iprot writeDouble: " + fname + " asFloat";
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      return "iprot write" + capitalize(type_name(t)) + ": " + fname + " asInteger";
-    default:
-      return "iprot write" + capitalize(type_name(t)) + ": " + fname;
-    }
-  } else if (t->is_map()) {
-    return map_writer((t_map*)t, fname);
-  } else if (t->is_struct() || t->is_xception()) {
-    return struct_writer((t_struct*)t, fname);
-  } else if (t->is_list()) {
-    return list_writer((t_list*)t, fname);
-  } else if (t->is_set()) {
-    return set_writer((t_set*)t, fname);
-  } else if (t->is_enum()) {
-    return "iprot writeI32: " + fname;
-  } else {
-    throw "Sorry, I don't know how to write this: " + type_name(t);
-  }
-}
-
-string t_st_generator::read_val(t_type* t) {
-  t = get_true_type(t);
-
-  if (t->is_base_type()) {
-    return "iprot read" + capitalize(type_name(t));
-  } else if (t->is_map()) {
-    return map_reader((t_map*)t);
-  } else if (t->is_struct() || t->is_xception()) {
-    return struct_reader((t_struct*)t);
-  } else if (t->is_list()) {
-    return list_reader((t_list*)t);
-  } else if (t->is_set()) {
-    return set_reader((t_set*)t);
-  } else if (t->is_enum()) {
-    return "iprot readI32";
-  } else {
-    throw "Sorry, I don't know how to read this: " + type_name(t);
-  }
-}
-
-void t_st_generator::generate_send_method(t_function* function) {
-  string funname = function->get_name();
-  string signature = function_signature(function);
-  t_struct* arg_struct = function->get_arglist();
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator fld_iter;
-
-  st_method(f_, client_class_name(), "send" + capitalize(signature));
-  f_ << "oprot writeMessageBegin:" << endl;
-  indent_up();
-
-  f_ << indent() << "(TCallMessage new" << endl;
-  indent_up();
-
-  f_ << indent() << "name: '" << funname << "'; " << endl << indent() << "seqid: self nextSeqid)."
-     << endl;
-  indent_down();
-  indent_down();
-
-  f_ << indent() << "oprot writeStructBegin: "
-     << "(TStruct new name: '" + capitalize(camelcase(funname)) + "_args')." << endl;
-
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-    string fname = camelcase((*fld_iter)->get_name());
-
-    f_ << indent() << "oprot writeFieldBegin: (TField new name: '" << fname
-       << "'; type: " << type_to_enum((*fld_iter)->get_type()) << "; id: " << (*fld_iter)->get_key()
-       << ")." << endl;
-
-    f_ << indent() << write_val((*fld_iter)->get_type(), fname) << "." << endl << indent()
-       << "oprot writeFieldEnd." << endl;
-  }
-
-  f_ << indent() << "oprot writeFieldStop; writeStructEnd; writeMessageEnd." << endl;
-  f_ << indent() << "oprot transport flush";
-
-  st_close_method(f_);
-}
-
-// We only support receiving TResult structures (so this won't work on the server side)
-void t_st_generator::generate_recv_method(t_function* function) {
-  string funname = camelcase(function->get_name());
-  string signature = function_signature(function);
-
-  t_struct result(program_, "TResult");
-  t_field success(function->get_returntype(), "success", 0);
-  result.append(&success);
-
-  t_struct* xs = function->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    // duplicate the field, but call it "exception"... we don't need a dynamic name
-    t_field* exception = new t_field((*f_iter)->get_type(), "exception", (*f_iter)->get_key());
-    result.append(exception);
-  }
-
-  st_method(f_, client_class_name(), "recv" + capitalize(funname));
-  f_ << "| f msg res | " << endl << indent() << "msg := oprot readMessageBegin." << endl << indent()
-     << "self validateRemoteMessage: msg." << endl << indent()
-     << "res := " << struct_reader(&result) << "." << endl << indent() << "oprot readMessageEnd."
-     << endl << indent() << "oprot transport flush." << endl << indent()
-     << "res exception ifNotNil: [res exception signal]." << endl << indent() << "^ res";
-  st_close_method(f_);
-}
-
-string t_st_generator::function_types_comment(t_function* fn) {
-  std::ostringstream out;
-  const vector<t_field*>& fields = fn->get_arglist()->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << "\"";
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    out << camelcase((*f_iter)->get_name()) << ": " << type_name((*f_iter)->get_type());
-    if ((f_iter + 1) != fields.end()) {
-      out << ", ";
-    }
-  }
-
-  out << "\"";
-
-  return out.str();
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_st_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "TClient";
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_client = extends + "Client";
-  }
-
-  f_ << extends_client << " subclass: #" << prefix(client_class_name()) << endl
-     << "\tinstanceVariableNames: ''\n"
-     << "\tclassVariableNames: ''\n"
-     << "\tpoolDictionaries: ''\n"
-     << "\tcategory: '" << generated_category() << "'!\n\n";
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = camelcase((*f_iter)->get_name());
-    string signature = function_signature(*f_iter);
-
-    st_method(f_, client_class_name(), signature);
-    f_ << function_types_comment(*f_iter) << endl << indent() << "self send"
-       << capitalize(signature) << "." << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_ << indent() << "^ self recv" << capitalize(funname) << " success " << endl;
-    }
-
-    st_close_method(f_);
-
-    generate_send_method(*f_iter);
-    if (!(*f_iter)->is_oneway()) {
-      generate_recv_method(*f_iter);
-    }
-  }
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_st_generator::function_signature(t_function* tfunction) {
-  return camelcase(tfunction->get_name()) + capitalize(argument_list(tfunction->get_arglist()));
-}
-
-/**
- * Renders a field list
- */
-string t_st_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += " ";
-    }
-    string name = camelcase((*f_iter)->get_name());
-    result += name + ": " + name;
-  }
-  return result;
-}
-
-string t_st_generator::type_name(t_type* ttype) {
-  string prefix = "";
-  t_program* program = ttype->get_program();
-  if (program != NULL && program != program_) {
-    if (!ttype->is_service()) {
-      prefix = program->get_name() + "_types.";
-    }
-  }
-
-  string name = ttype->get_name();
-  if (ttype->is_struct() || ttype->is_xception()) {
-    name = capitalize(ttype->get_name());
-  }
-
-  return prefix + name;
-}
-
-/* Convert t_type to Smalltalk type code */
-string t_st_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "TType string";
-    case t_base_type::TYPE_BOOL:
-      return "TType bool";
-    case t_base_type::TYPE_I8:
-      return "TType byte";
-    case t_base_type::TYPE_I16:
-      return "TType i16";
-    case t_base_type::TYPE_I32:
-      return "TType i32";
-    case t_base_type::TYPE_I64:
-      return "TType i64";
-    case t_base_type::TYPE_DOUBLE:
-      return "TType double";
-    }
-  } else if (type->is_enum()) {
-    return "TType i32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType struct";
-  } else if (type->is_map()) {
-    return "TType map";
-  } else if (type->is_set()) {
-    return "TType set";
-  } else if (type->is_list()) {
-    return "TType list";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-THRIFT_REGISTER_GENERATOR(st, "Smalltalk", "")


[33/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_json_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_json_generator.cc b/compiler/cpp/src/generate/t_json_generator.cc
deleted file mode 100644
index 447bc6d..0000000
--- a/compiler/cpp/src/generate/t_json_generator.cc
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <limits>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-
-#include "t_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-using std::stack;
-
-static const string endl = "\n";
-static const string quot = "\"";
-static const bool NO_INDENT = false;
-static const bool FORCE_STRING = true;
-
-class t_json_generator : public t_generator {
-public:
-  t_json_generator(t_program* program,
-                   const std::map<std::string, std::string>& parsed_options,
-                   const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    should_merge_includes_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("merge") == 0) {
-        should_merge_includes_ = true;
-      } else {
-        throw "unknown option json:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-json";
-  }
-
-  virtual ~t_json_generator() {}
-
-  /**
-  * Init and close methods
-  */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_program();
-  void generate_function(t_function* tfunc);
-  void generate_field(t_field* field);
-
-  void generate_service(t_service* tservice);
-  void generate_struct(t_struct* tstruct);
-
-private:
-  bool should_merge_includes_;
-
-  std::ofstream f_json_;
-  std::stack<bool> comma_needed_;
-
-  template <typename T>
-  string number_to_string(T t) {
-    std::ostringstream out;
-    out.imbue(std::locale::classic());
-    out.precision(std::numeric_limits<T>::digits10);
-    out << t;
-    return out.str();
-  }
-
-  template <typename T>
-  void write_number(T n) {
-    f_json_ << number_to_string(n);
-  }
-
-  string get_type_name(t_type* ttype);
-  string get_qualified_name(t_type* ttype);
-
-  void start_object(bool should_indent = true);
-  void start_array();
-  void end_object();
-  void end_array();
-  void write_comma_if_needed();
-  void indicate_comma_needed();
-  string escape_json_string(const string& input);
-  string json_str(const string& str);
-  void merge_includes(t_program*);
-
-  void generate_constant(t_const* con);
-
-  void write_type_spec_entry(const char* name, t_type* ttype);
-  void write_type_spec_object(const char* name, t_type* ttype);
-  void write_type_spec(t_type* ttype);
-  void write_string(const string& value);
-  void write_value(t_type* tvalue);
-  void write_const_value(t_const_value* value, bool force_string = false);
-  void write_key_and(string key);
-  void write_key_and_string(string key, string val);
-  void write_key_and_integer(string key, int val);
-  void write_key_and_bool(string key, bool val);
-};
-
-void t_json_generator::init_generator() {
-  MKDIR(get_out_dir().c_str());
-
-  string f_json_name = get_out_dir() + program_->get_name() + ".json";
-  f_json_.open(f_json_name.c_str());
-
-  // Merge all included programs into this one so we can output one big file.
-  if (should_merge_includes_) {
-    merge_includes(program_);
-  }
-}
-
-string t_json_generator::escape_json_string(const string& input) {
-  std::ostringstream ss;
-  for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
-    switch (*iter) {
-    case '\\':
-      ss << "\\\\";
-      break;
-    case '"':
-      ss << "\\\"";
-      break;
-    case '/':
-      ss << "\\/";
-      break;
-    case '\b':
-      ss << "\\b";
-      break;
-    case '\f':
-      ss << "\\f";
-      break;
-    case '\n':
-      ss << "\\n";
-      break;
-    case '\r':
-      ss << "\\r";
-      break;
-    case '\t':
-      ss << "\\t";
-      break;
-    default:
-      ss << *iter;
-      break;
-    }
-  }
-  return ss.str();
-}
-
-void t_json_generator::start_object(bool should_indent) {
-  f_json_ << (should_indent ? indent() : "") << "{" << endl;
-  indent_up();
-  comma_needed_.push(false);
-}
-
-void t_json_generator::start_array() {
-  f_json_ << "[" << endl;
-  indent_up();
-  comma_needed_.push(false);
-}
-
-void t_json_generator::write_comma_if_needed() {
-  if (comma_needed_.top()) {
-    f_json_ << "," << endl;
-  }
-}
-
-void t_json_generator::indicate_comma_needed() {
-  comma_needed_.pop();
-  comma_needed_.push(true);
-}
-
-void t_json_generator::write_key_and(string key) {
-  write_comma_if_needed();
-  indent(f_json_) << json_str(key) << ": ";
-  indicate_comma_needed();
-}
-
-void t_json_generator::write_key_and_integer(string key, int val) {
-  write_comma_if_needed();
-  indent(f_json_) << json_str(key) << ": " << number_to_string(val);
-  indicate_comma_needed();
-}
-
-void t_json_generator::write_key_and_string(string key, string val) {
-  write_comma_if_needed();
-  indent(f_json_) << json_str(key) << ": " << json_str(val);
-  indicate_comma_needed();
-}
-
-void t_json_generator::write_key_and_bool(string key, bool val) {
-  write_comma_if_needed();
-  indent(f_json_) << json_str(key) << ": " << (val ? "true" : "false");
-  indicate_comma_needed();
-}
-
-void t_json_generator::end_object() {
-  indent_down();
-  f_json_ << endl << indent() << "}";
-  comma_needed_.pop();
-}
-
-void t_json_generator::end_array() {
-  indent_down();
-  if (comma_needed_.top()) {
-    f_json_ << endl;
-  }
-  indent(f_json_) << "]";
-  comma_needed_.pop();
-}
-
-void t_json_generator::write_type_spec_object(const char* name, t_type* ttype) {
-  ttype = ttype->get_true_type();
-  if (ttype->is_struct() || ttype->is_xception() || ttype->is_container()) {
-    write_key_and(name);
-    start_object(NO_INDENT);
-    write_key_and("typeId");
-    write_type_spec(ttype);
-    end_object();
-  }
-}
-
-void t_json_generator::write_type_spec_entry(const char* name, t_type* ttype) {
-  write_key_and(name);
-  write_type_spec(ttype);
-}
-
-void t_json_generator::write_type_spec(t_type* ttype) {
-  ttype = ttype->get_true_type();
-
-  write_string(get_type_name(ttype));
-
-  if (ttype->is_struct() || ttype->is_xception()) {
-    write_key_and_string("class", get_qualified_name(ttype));
-  } else if (ttype->is_map()) {
-    t_type* ktype = ((t_map*)ttype)->get_key_type();
-    t_type* vtype = ((t_map*)ttype)->get_val_type();
-    write_key_and_string("keyTypeId", get_type_name(ktype));
-    write_key_and_string("valueTypeId", get_type_name(vtype));
-    write_type_spec_object("keyType", ktype);
-    write_type_spec_object("valueType", vtype);
-  } else if (ttype->is_list() || ttype->is_set()) {
-    t_type* etype = ((t_list*)ttype)->get_elem_type();
-    write_key_and_string("elemTypeId", get_type_name(etype));
-    write_type_spec_object("elemType", etype);
-  }
-}
-
-void t_json_generator::close_generator() {
-  f_json_ << endl;
-  f_json_.close();
-}
-
-void t_json_generator::merge_includes(t_program* program) {
-  vector<t_program*> includes = program->get_includes();
-  vector<t_program*>::iterator inc_iter;
-  for (inc_iter = includes.begin(); inc_iter != includes.end(); ++inc_iter) {
-    t_program* include = *inc_iter;
-    // recurse in case we get crazy
-    merge_includes(include);
-    // merge enums
-    vector<t_enum*> enums = include->get_enums();
-    vector<t_enum*>::iterator en_iter;
-    for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-      program->add_enum(*en_iter);
-    }
-    // merge typedefs
-    vector<t_typedef*> typedefs = include->get_typedefs();
-    vector<t_typedef*>::iterator td_iter;
-    for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-      program->add_typedef(*td_iter);
-    }
-    // merge structs
-    vector<t_struct*> objects = include->get_objects();
-    vector<t_struct*>::iterator o_iter;
-    for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-      program->add_struct(*o_iter);
-    }
-    // merge constants
-    vector<t_const*> consts = include->get_consts();
-    vector<t_const*>::iterator c_iter;
-    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      program->add_const(*c_iter);
-    }
-
-    // merge services
-    vector<t_service*> services = include->get_services();
-    vector<t_service*>::iterator sv_iter;
-    for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-      program->add_service(*sv_iter);
-    }
-  }
-}
-
-void t_json_generator::generate_program() {
-
-  init_generator();
-
-  start_object();
-  write_key_and_string("name", program_->get_name());
-  if (program_->has_doc()) {
-    write_key_and_string("doc", program_->get_doc());
-  }
-
-  // When merging includes, the "namespaces" and "includes" sections
-  // become ambiguous, so just skip them.
-  if (!should_merge_includes_) {
-    // Generate namespaces
-    write_key_and("namespaces");
-    start_object(NO_INDENT);
-    const map<string, string>& namespaces = program_->get_namespaces();
-    map<string, string>::const_iterator ns_it;
-    for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) {
-      write_key_and_string(ns_it->first, ns_it->second);
-      indicate_comma_needed();
-    }
-    end_object();
-
-    // Generate includes
-    write_key_and("includes");
-    start_array();
-    const vector<t_program*> includes = program_->get_includes();
-    vector<t_program*>::const_iterator inc_it;
-    for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) {
-      write_comma_if_needed();
-      write_string((*inc_it)->get_name());
-      indicate_comma_needed();
-    }
-    end_array();
-  }
-
-  // Generate enums
-  write_key_and("enums");
-  start_array();
-  vector<t_enum*> enums = program_->get_enums();
-  vector<t_enum*>::iterator en_iter;
-  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-    write_comma_if_needed();
-    generate_enum(*en_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  // Generate typedefs
-  write_key_and("typedefs");
-  start_array();
-  vector<t_typedef*> typedefs = program_->get_typedefs();
-  vector<t_typedef*>::iterator td_iter;
-  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-    write_comma_if_needed();
-    generate_typedef(*td_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  // Generate structs, exceptions, and unions in declared order
-  write_key_and("structs");
-  start_array();
-  vector<t_struct*> objects = program_->get_objects();
-  vector<t_struct*>::iterator o_iter;
-  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-    write_comma_if_needed();
-    if ((*o_iter)->is_xception()) {
-      generate_xception(*o_iter);
-    } else {
-      generate_struct(*o_iter);
-    }
-    indicate_comma_needed();
-  }
-  end_array();
-
-  // Generate constants
-  write_key_and("constants");
-  start_array();
-  vector<t_const*> consts = program_->get_consts();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    write_comma_if_needed();
-    generate_constant(*c_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  // Generate services
-  write_key_and("services");
-  start_array();
-  vector<t_service*> services = program_->get_services();
-  vector<t_service*>::iterator sv_iter;
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    write_comma_if_needed();
-    generate_service(*sv_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  end_object();
-
-  // Close the generator
-  close_generator();
-}
-
-void t_json_generator::generate_typedef(t_typedef* ttypedef) {
-  start_object();
-  write_key_and_string("name", get_qualified_name(ttypedef));
-  write_key_and_string("typeId", get_type_name(ttypedef->get_true_type()));
-  write_type_spec_object("type", ttypedef->get_true_type());
-  if (ttypedef->has_doc()) {
-    write_key_and_string("doc", ttypedef->get_doc());
-  }
-  end_object();
-}
-
-void t_json_generator::write_string(const string& value) {
-  f_json_ << quot << escape_json_string(value) << quot;
-}
-
-void t_json_generator::write_const_value(t_const_value* value, bool should_force_string) {
-
-  switch (value->get_type()) {
-
-  case t_const_value::CV_IDENTIFIER:
-  case t_const_value::CV_INTEGER:
-    if (should_force_string) {
-      write_string(number_to_string(value->get_integer()));
-    } else {
-      write_number(value->get_integer());
-    }
-    break;
-
-  case t_const_value::CV_DOUBLE:
-    if (should_force_string) {
-      write_string(number_to_string(value->get_double()));
-    } else {
-      write_number(value->get_double());
-    }
-    break;
-
-  case t_const_value::CV_STRING:
-    write_string(value->get_string());
-    break;
-
-  case t_const_value::CV_LIST: {
-    start_array();
-    std::vector<t_const_value*> list = value->get_list();
-    std::vector<t_const_value*>::iterator lit;
-    for (lit = list.begin(); lit != list.end(); ++lit) {
-      write_comma_if_needed();
-      f_json_ << indent();
-      write_const_value(*lit);
-      indicate_comma_needed();
-    }
-    end_array();
-    break;
-  }
-
-  case t_const_value::CV_MAP: {
-    start_object(NO_INDENT);
-    std::map<t_const_value*, t_const_value*> map = value->get_map();
-    std::map<t_const_value*, t_const_value*>::iterator mit;
-    for (mit = map.begin(); mit != map.end(); ++mit) {
-      write_comma_if_needed();
-      f_json_ << indent();
-      // JSON objects only allow string keys
-      write_const_value(mit->first, FORCE_STRING);
-      f_json_ << ": ";
-      write_const_value(mit->second);
-      indicate_comma_needed();
-    }
-    end_object();
-    break;
-  }
-
-  default:
-    f_json_ << "null";
-    break;
-  }
-}
-
-string t_json_generator::json_str(const string& str) {
-  return quot + escape_json_string(str) + quot;
-}
-
-void t_json_generator::generate_constant(t_const* con) {
-  start_object();
-
-  write_key_and_string("name", con->get_name());
-  write_key_and_string("typeId", get_type_name(con->get_type()));
-  write_type_spec_object("type", con->get_type());
-
-  if (con->has_doc()) {
-    write_key_and_string("doc", con->get_doc());
-  }
-
-  write_key_and("value");
-  write_const_value(con->get_value());
-
-  end_object();
-}
-
-void t_json_generator::generate_enum(t_enum* tenum) {
-  start_object();
-
-  write_key_and_string("name", tenum->get_name());
-
-  if (tenum->has_doc()) {
-    write_key_and_string("doc", tenum->get_doc());
-  }
-
-  write_key_and("members");
-  start_array();
-  vector<t_enum_value*> values = tenum->get_constants();
-  vector<t_enum_value*>::iterator val_iter;
-  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
-    write_comma_if_needed();
-    t_enum_value* val = (*val_iter);
-    start_object();
-    write_key_and_string("name", val->get_name());
-    write_key_and_integer("value", val->get_value());
-    if (val->has_doc()) {
-      write_key_and_string("doc", val->get_doc());
-    }
-    end_object();
-    indicate_comma_needed();
-  }
-  end_array();
-
-  end_object();
-}
-
-void t_json_generator::generate_struct(t_struct* tstruct) {
-  start_object();
-
-  write_key_and_string("name", tstruct->get_name());
-
-  if (tstruct->has_doc()) {
-    write_key_and_string("doc", tstruct->get_doc());
-  }
-
-  write_key_and_bool("isException", tstruct->is_xception());
-
-  write_key_and_bool("isUnion", tstruct->is_union());
-
-  write_key_and("fields");
-  start_array();
-  vector<t_field*> members = tstruct->get_members();
-  vector<t_field*>::iterator mem_iter;
-  for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) {
-    write_comma_if_needed();
-    generate_field(*mem_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  end_object();
-}
-
-void t_json_generator::generate_service(t_service* tservice) {
-  start_object();
-
-  write_key_and_string("name", get_qualified_name(tservice));
-
-  if (tservice->get_extends()) {
-    write_key_and_string("extends", get_qualified_name(tservice->get_extends()));
-  }
-
-  if (tservice->has_doc()) {
-    write_key_and_string("doc", tservice->get_doc());
-  }
-
-  write_key_and("functions");
-  start_array();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator fn_iter = functions.begin();
-  for (; fn_iter != functions.end(); fn_iter++) {
-    write_comma_if_needed();
-    generate_function(*fn_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  end_object();
-}
-
-void t_json_generator::generate_function(t_function* tfunc) {
-  start_object();
-
-  write_key_and_string("name", tfunc->get_name());
-
-  write_key_and_string("returnTypeId", get_type_name(tfunc->get_returntype()));
-  write_type_spec_object("returnType", tfunc->get_returntype());
-
-  write_key_and_bool("oneway", tfunc->is_oneway());
-
-  if (tfunc->has_doc()) {
-    write_key_and_string("doc", tfunc->get_doc());
-  }
-
-  write_key_and("arguments");
-  start_array();
-  vector<t_field*> members = tfunc->get_arglist()->get_members();
-  vector<t_field*>::iterator mem_iter = members.begin();
-  for (; mem_iter != members.end(); mem_iter++) {
-    write_comma_if_needed();
-    generate_field(*mem_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  write_key_and("exceptions");
-  start_array();
-  vector<t_field*> excepts = tfunc->get_xceptions()->get_members();
-  vector<t_field*>::iterator ex_iter = excepts.begin();
-  for (; ex_iter != excepts.end(); ex_iter++) {
-    write_comma_if_needed();
-    generate_field(*ex_iter);
-    indicate_comma_needed();
-  }
-  end_array();
-
-  end_object();
-}
-
-void t_json_generator::generate_field(t_field* field) {
-  start_object();
-
-  write_key_and_integer("key", field->get_key());
-  write_key_and_string("name", field->get_name());
-  write_key_and_string("typeId", get_type_name(field->get_type()));
-  write_type_spec_object("type", field->get_type());
-
-  if (field->has_doc()) {
-    write_key_and_string("doc", field->get_doc());
-  }
-
-  write_key_and("required");
-  switch (field->get_req()) {
-  case t_field::T_REQUIRED:
-    write_string("required");
-    break;
-  case t_field::T_OPT_IN_REQ_OUT:
-    write_string("req_out");
-    break;
-  default:
-    write_string("optional");
-    break;
-  }
-
-  if (field->get_value()) {
-    write_key_and("default");
-    write_const_value(field->get_value());
-  }
-
-  end_object();
-}
-
-string t_json_generator::get_type_name(t_type* ttype) {
-  ttype = ttype->get_true_type();
-  if (ttype->is_list()) {
-    return "list";
-  }
-  if (ttype->is_set()) {
-    return "set";
-  }
-  if (ttype->is_map()) {
-    return "map";
-  }
-  if (ttype->is_enum()) {
-    return "i32";
-  }
-  if (ttype->is_struct()) {
-    return ((t_struct*)ttype)->is_union() ? "union" : "struct";
-  }
-  if (ttype->is_xception()) {
-    return "exception";
-  }
-  if (ttype->is_base_type()) {
-    t_base_type* tbasetype = (t_base_type*)ttype;
-    return tbasetype->is_binary() ? "binary" : t_base_type::t_base_name(tbasetype->get_base());
-  }
-
-  return "(unknown)";
-}
-
-string t_json_generator::get_qualified_name(t_type* ttype) {
-  if (should_merge_includes_ || ttype->get_program() == program_) {
-    return ttype->get_name();
-  }
-  return ttype->get_program()->get_name() + "." + ttype->get_name();
-}
-
-THRIFT_REGISTER_GENERATOR(json,
-                          "JSON",
-                          "    merge:           Generate output with included files merged\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_lua_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_lua_generator.cc b/compiler/cpp/src/generate/t_lua_generator.cc
deleted file mode 100644
index c6fb493..0000000
--- a/compiler/cpp/src/generate/t_lua_generator.cc
+++ /dev/null
@@ -1,1138 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <sstream>
-#include "t_oop_generator.h"
-#include "platform.h"
-
-using std::ofstream;
-using std::string;
-using std::vector;
-using std::map;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * LUA code generator.
- *
- */
-class t_lua_generator : public t_oop_generator {
-public:
-  t_lua_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    gen_requires_ = true;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("omit_requires") == 0) {
-        gen_requires_ = false;
-      } else {
-        throw "unknown option lua:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-lua";
-  }
-
-  /**
-   * Init and close methods
-   */
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-
-private:
-  /**
-   * True iff we should generate lua require statements.
-   */
-  bool gen_requires_;
-
-  /**
-   * Struct-level generation functions
-   */
-  void generate_lua_struct_definition(std::ofstream& out,
-                                      t_struct* tstruct,
-                                      bool is_xception = false);
-  void generate_lua_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_lua_struct_writer(std::ofstream& out, t_struct* tstruct);
-
-  /**
-   * Service-level generation functions
-   */
-  void generate_service_client(std::ofstream& out, t_service* tservice);
-  void generate_service_interface(std::ofstream& out, t_service* tservice);
-  void generate_service_processor(std::ofstream& out, t_service* tservice);
-  void generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction);
-  void generate_service_helpers(ofstream& out, t_service* tservice);
-  void generate_function_helpers(ofstream& out, t_function* tfunction);
-
-  /**
-   * Deserialization (Read)
-   */
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  bool local,
-                                  std::string prefix = "");
-
-  void generate_deserialize_struct(std::ofstream& out,
-                                   t_struct* tstruct,
-                                   bool local,
-                                   std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out,
-                                      t_type* ttype,
-                                      bool local,
-                                      std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  /**
-   * Serialization (Write)
-   */
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  /**
-   * Helper rendering functions
-   */
-  std::string lua_includes();
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string argument_list(t_struct* tstruct, std::string prefix = "");
-  std::string type_to_enum(t_type* ttype);
-  static std::string get_namespace(const t_program* program);
-
-  std::string autogen_comment() {
-    return std::string("--\n") + "-- Autogenerated by Thrift\n" + "--\n"
-           + "-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "-- @"
-                                                                                       "generated\n"
-           + "--\n";
-  }
-
-  /**
-   * File streams
-   */
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_service_;
-};
-
-/**
- * Init and close methods
- */
-void t_lua_generator::init_generator() {
-  // Make output directory
-  string outdir = get_out_dir();
-  MKDIR(outdir.c_str());
-
-  // Make output files
-  string cur_namespace = get_namespace(program_);
-  string f_consts_name = outdir + cur_namespace + "constants.lua";
-  f_consts_.open(f_consts_name.c_str());
-  string f_types_name = outdir + cur_namespace + "ttypes.lua";
-  f_types_.open(f_types_name.c_str());
-
-  // Add headers
-  f_consts_ << autogen_comment() << lua_includes();
-  f_types_ << autogen_comment() << lua_includes();
-  if (gen_requires_) {
-    f_types_ << endl << "require '" << cur_namespace << "constants'";
-  }
-}
-
-void t_lua_generator::close_generator() {
-  // Close types file
-  f_types_.close();
-  f_consts_.close();
-}
-
-/**
- * Generate a typedef (essentially a constant)
- */
-void t_lua_generator::generate_typedef(t_typedef* ttypedef) {
-  f_types_ << endl << endl << indent() << ttypedef->get_symbolic() << " = "
-           << ttypedef->get_type()->get_name();
-}
-
-/**
- * Generates code for an enumerated type (table)
- */
-void t_lua_generator::generate_enum(t_enum* tenum) {
-  f_types_ << endl << endl << tenum->get_name() << " = {" << endl;
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end();) {
-    int32_t value = (*c_iter)->get_value();
-
-    f_types_ << "  " << (*c_iter)->get_name() << " = " << value;
-    ++c_iter;
-    if (c_iter != constants.end()) {
-      f_types_ << ",";
-    }
-    f_types_ << endl;
-  }
-  f_types_ << "}";
-}
-
-/**
- * Generate a constant (non-local) value
- */
-void t_lua_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  f_consts_ << endl << endl << name << " = ";
-  f_consts_ << render_const_value(type, value);
-}
-
-/**
- * Prints the value of a constant with the given type.
- */
-string t_lua_generator::render_const_value(t_type* type, t_const_value* value) {
-  std::ostringstream out;
-
-  type = get_true_type(type);
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << "'" << value->get_string() << "'";
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      out << "lualongnumber.new('" << value->get_string() << "')";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    out << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << type->get_name() << " = {" << endl;
-    indent_up();
-
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end();) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-
-      indent(out);
-      out << render_const_value(g_type_string, v_iter->first);
-      out << " = ";
-      out << render_const_value(field_type, v_iter->second);
-      ++v_iter;
-      if (v_iter != val.end()) {
-        out << ",";
-      }
-    }
-
-    out << "}";
-    indent_down();
-  } else if (type->is_map()) {
-    out << type->get_name() << "{" << endl;
-    indent_up();
-
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end();) {
-      indent(out) << "[" << render_const_value(ktype, v_iter->first)
-                  << "] = " << render_const_value(vtype, v_iter->second);
-      ++v_iter;
-      if (v_iter != val.end()) {
-        out << ",";
-      }
-      out << endl;
-    }
-    indent_down();
-    indent(out) << "}";
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    out << type->get_name() << " = {" << endl;
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end();) {
-      indent(out);
-      out << "[" << render_const_value(etype, *v_iter) << "]";
-      if (type->is_set()) {
-        out << " = true";
-      } else {
-        out << " = false";
-      }
-      ++v_iter;
-      if (v_iter != val.end()) {
-        out << "," << endl;
-      }
-    }
-    out << "}";
-  }
-  return out.str();
-}
-
-/**
- * Generate a thrift struct
- */
-void t_lua_generator::generate_struct(t_struct* tstruct) {
-  generate_lua_struct_definition(f_types_, tstruct, false);
-}
-
-/**
- * Generate a thrift exception
- */
-void t_lua_generator::generate_xception(t_struct* txception) {
-  generate_lua_struct_definition(f_types_, txception, true);
-}
-
-/**
- * Generate a thrift struct or exception (lua table)
- */
-void t_lua_generator::generate_lua_struct_definition(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_exception) {
-  vector<t_field*>::const_iterator m_iter;
-  const vector<t_field*>& members = tstruct->get_members();
-
-  indent(out) << endl << endl << tstruct->get_name();
-  if (is_exception) {
-    out << " = TException:new{" << endl << indent() << "  __type = '" << tstruct->get_name() << "'";
-    if (members.size() > 0) {
-      out << ",";
-    }
-    out << endl;
-  } else {
-    out << " = __TObject:new{" << endl;
-  }
-  indent_up();
-  for (m_iter = members.begin(); m_iter != members.end();) {
-    indent(out);
-    out << (*m_iter)->get_name();
-    ++m_iter;
-    if (m_iter != members.end()) {
-      out << "," << endl;
-    }
-  }
-  indent_down();
-  indent(out);
-  out << endl << "}";
-
-  generate_lua_struct_reader(out, tstruct);
-  generate_lua_struct_writer(out, tstruct);
-}
-
-/**
- * Generate a struct/exception reader
- */
-void t_lua_generator::generate_lua_struct_reader(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // function
-  indent(out) << endl << endl << "function " << tstruct->get_name() << ":read(iprot)" << endl;
-  indent_up();
-
-  indent(out) << "iprot:readStructBegin()" << endl;
-
-  // while: Read in fields
-  indent(out) << "while true do" << endl;
-  indent_up();
-
-  // if: Check what to read
-  indent(out) << "local fname, ftype, fid = iprot:readFieldBegin()" << endl;
-  indent(out) << "if ftype == TType.STOP then" << endl;
-  indent_up();
-  indent(out) << "break" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent_down();
-    indent(out) << "elseif fid == " << (*f_iter)->get_key() << " then" << endl;
-    indent_up();
-    indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << " then" << endl;
-    indent_up();
-
-    // Read field contents
-    generate_deserialize_field(out, *f_iter, false, "self.");
-
-    indent_down();
-    indent(out) << "else" << endl;
-    indent(out) << "  iprot:skip(ftype)" << endl;
-    indent(out) << "end" << endl;
-  }
-
-  // end if
-  indent_down();
-  indent(out) << "else" << endl;
-  indent(out) << "  iprot:skip(ftype)" << endl;
-  indent(out) << "end" << endl;
-  indent(out) << "iprot:readFieldEnd()" << endl;
-
-  // end while
-  indent_down();
-  indent(out) << "end" << endl;
-  indent(out) << "iprot:readStructEnd()" << endl;
-
-  // end function
-  indent_down();
-  indent(out);
-  out << "end";
-}
-
-/**
- * Generate a struct/exception writer
- */
-void t_lua_generator::generate_lua_struct_writer(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // function
-  indent(out) << endl << endl << "function " << tstruct->get_name() << ":write(oprot)" << endl;
-  indent_up();
-
-  indent(out) << "oprot:writeStructBegin('" << tstruct->get_name() << "')" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    // To check element of self whether nil or not.
-    // avoid the value(false) of BOOL is lost.
-    indent(out) << "if self." << (*f_iter)->get_name() << " ~= nil then" << endl;
-    indent_up();
-    indent(out) << "oprot:writeFieldBegin('" << (*f_iter)->get_name() << "', "
-                << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ")"
-                << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "self.");
-
-    indent(out) << "oprot:writeFieldEnd()" << endl;
-    indent_down();
-    indent(out) << "end" << endl;
-  }
-  indent(out) << "oprot:writeFieldStop()" << endl;
-  indent(out) << "oprot:writeStructEnd()" << endl;
-
-  // end function
-  indent_down();
-  indent(out);
-  out << "end";
-}
-
-/**
- * Generate a thrift service
- */
-void t_lua_generator::generate_service(t_service* tservice) {
-  // Get output directory
-  string outdir = get_out_dir();
-
-  // Open the file for writing
-  string cur_ns = get_namespace(program_);
-  string f_service_name = outdir + cur_ns + tservice->get_name() + ".lua";
-  f_service_.open(f_service_name.c_str());
-
-  // Headers
-  f_service_ << autogen_comment() << lua_includes();
-  if (gen_requires_) {
-    f_service_ << endl << "require '" << cur_ns << "ttypes'" << endl;
-
-    if (tservice->get_extends() != NULL) {
-      f_service_ << "require '" << get_namespace(tservice->get_extends()->get_program())
-                 << tservice->get_extends()->get_name() << "'" << endl;
-    }
-  }
-
-  f_service_ << endl;
-
-  generate_service_client(f_service_, tservice);
-  generate_service_interface(f_service_, tservice);
-  generate_service_processor(f_service_, tservice);
-  generate_service_helpers(f_service_, tservice);
-
-  // Close the file
-  f_service_.close();
-}
-
-void t_lua_generator::generate_service_interface(ofstream& out, t_service* tservice) {
-  string classname = tservice->get_name() + "Iface";
-  t_service* extends_s = tservice->get_extends();
-
-  // Interface object definition
-  out << classname << " = ";
-  if (extends_s) {
-    out << extends_s->get_name() << "Iface:new{" << endl;
-  } else {
-    out << "__TObject:new{" << endl;
-  }
-  out << "  __type = '" << classname << "'" << endl << "}" << endl << endl;
-}
-
-void t_lua_generator::generate_service_client(ofstream& out, t_service* tservice) {
-  string classname = tservice->get_name() + "Client";
-  t_service* extends_s = tservice->get_extends();
-
-  // Client object definition
-  out << classname << " = __TObject.new(";
-  if (extends_s != NULL) {
-    out << extends_s->get_name() << "Client";
-  } else {
-    out << "__TClient";
-  }
-  out << ", {" << endl << "  __type = '" << classname << "'" << endl << "})" << endl;
-
-  // Send/Recv functions
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string sig = function_signature(*f_iter);
-    string funcname = (*f_iter)->get_name();
-
-    // Wrapper function
-    indent(out) << endl << "function " << classname << ":" << sig << endl;
-    indent_up();
-
-    indent(out) << "self:send_" << sig << endl << indent();
-    if (!(*f_iter)->is_oneway()) {
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        out << "return ";
-      }
-      out << "self:recv_" << sig << endl;
-    }
-
-    indent_down();
-    indent(out) << "end" << endl;
-
-    // Send function
-    indent(out) << endl << "function " << classname << ":send_" << sig << endl;
-    indent_up();
-
-    indent(out) << "self.oprot:writeMessageBegin('" << funcname << "', "
-                << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
-                << ", self._seqid)" << endl;
-    indent(out) << "local args = " << funcname << "_args:new{}" << endl;
-
-    // Set the args
-    const vector<t_field*>& args = (*f_iter)->get_arglist()->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    for (fld_iter = args.begin(); fld_iter != args.end(); ++fld_iter) {
-      std::string argname = (*fld_iter)->get_name();
-      indent(out) << "args." << argname << " = " << argname << endl;
-    }
-
-    indent(out) << "args:write(self.oprot)" << endl;
-    indent(out) << "self.oprot:writeMessageEnd()" << endl;
-    indent(out) << "self.oprot.trans:flush()" << endl;
-
-    indent_down();
-    indent(out) << "end" << endl;
-
-    // Recv function
-    if (!(*f_iter)->is_oneway()) {
-      indent(out) << endl << "function " << classname << ":recv_" << sig << endl;
-      indent_up();
-
-      out << indent() << "local fname, mtype, rseqid = self.iprot:"
-          << "readMessageBegin()" << endl << indent() << "if mtype == TMessageType.EXCEPTION then"
-          << endl << indent() << "  local x = TApplicationException:new{}" << endl << indent()
-          << "  x:read(self.iprot)" << endl << indent() << "  self.iprot:readMessageEnd()" << endl
-          << indent() << "  error(x)" << endl << indent() << "end" << endl << indent()
-          << "local result = " << funcname << "_result:new{}" << endl << indent()
-          << "result:read(self.iprot)" << endl << indent() << "self.iprot:readMessageEnd()" << endl;
-
-      // Return the result if it's not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        out << indent() << "if result.success ~= nil then" << endl << indent() << "  return result.success"
-            << endl;
-
-        // Throw custom exceptions
-        const std::vector<t_field*>& xf = (*f_iter)->get_xceptions()->get_members();
-        vector<t_field*>::const_iterator x_iter;
-        for (x_iter = xf.begin(); x_iter != xf.end(); ++x_iter) {
-          out << indent() << "elseif result." << (*x_iter)->get_name() << " then" << endl
-              << indent() << "  error(result." << (*x_iter)->get_name() << ")" << endl;
-        }
-
-        out << indent() << "end" << endl << indent()
-            << "error(TApplicationException:new{errorCode = "
-            << "TApplicationException.MISSING_RESULT})" << endl;
-      }
-
-      indent_down();
-      indent(out) << "end" << endl;
-    }
-  }
-}
-
-void t_lua_generator::generate_service_processor(ofstream& out, t_service* tservice) {
-  string classname = tservice->get_name() + "Processor";
-  t_service* extends_s = tservice->get_extends();
-
-  // Define processor table
-  out << endl << classname << " = __TObject.new(";
-  if (extends_s != NULL) {
-    out << extends_s << "Processor" << endl;
-  } else {
-    out << "__TProcessor" << endl;
-  }
-  out << ", {" << endl << " __type = '" << classname << "'" << endl << "})" << endl;
-
-  // Process function
-  indent(out) << endl << "function " << classname << ":process(iprot, oprot, server_ctx)" << endl;
-  indent_up();
-
-  indent(out) << "local name, mtype, seqid = iprot:readMessageBegin()" << endl;
-  indent(out) << "local func_name = 'process_' .. name" << endl;
-  indent(out) << "if not self[func_name] or ttype(self[func_name]) ~= 'function' then";
-  indent_up();
-  out << endl << indent() << "iprot:skip(TType.STRUCT)" << endl << indent()
-      << "iprot:readMessageEnd()" << endl << indent() << "x = TApplicationException:new{" << endl
-      << indent() << "  errorCode = TApplicationException.UNKNOWN_METHOD" << endl << indent() << "}"
-      << endl << indent() << "oprot:writeMessageBegin(name, TMessageType.EXCEPTION, "
-      << "seqid)" << endl << indent() << "x:write(oprot)" << endl << indent()
-      << "oprot:writeMessageEnd()" << endl << indent() << "oprot.trans:flush()" << endl;
-  indent_down();
-  indent(out) << "else" << endl << indent()
-              << "  self[func_name](self, seqid, iprot, oprot, server_ctx)" << endl << indent()
-              << "end" << endl;
-
-  indent_down();
-  indent(out) << "end" << endl;
-
-  // Generate the process subfunctions
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(out, tservice, *f_iter);
-  }
-}
-
-void t_lua_generator::generate_process_function(ofstream& out,
-                                                t_service* tservice,
-                                                t_function* tfunction) {
-  string classname = tservice->get_name() + "Processor";
-  string argsname = tfunction->get_name() + "_args";
-  string resultname = tfunction->get_name() + "_result";
-  string fn_name = tfunction->get_name();
-
-  indent(out) << endl << "function " << classname << ":process_" << fn_name
-              << "(seqid, iprot, oprot, server_ctx)" << endl;
-  indent_up();
-
-  // Read the request
-  out << indent() << "local args = " << argsname << ":new{}" << endl << indent()
-      << "local reply_type = TMessageType.REPLY" << endl << indent() << "args:read(iprot)" << endl
-      << indent() << "iprot:readMessageEnd()" << endl << indent() << "local result = " << resultname
-      << ":new{}" << endl << indent() << "local status, res = pcall(self.handler." << fn_name
-      << ", self.handler";
-
-  // Print arguments
-  t_struct* args = tfunction->get_arglist();
-  if (args->get_members().size() > 0) {
-    out << ", " << argument_list(args, "args.");
-  }
-
-  // Check for errors
-  out << ")" << endl << indent() << "if not status then" << endl << indent()
-      << "  reply_type = TMessageType.EXCEPTION" << endl << indent()
-      << "  result = TApplicationException:new{message = res}" << endl;
-
-  // Handle custom exceptions
-  const std::vector<t_field*>& xf = tfunction->get_xceptions()->get_members();
-  if (xf.size() > 0) {
-    vector<t_field*>::const_iterator x_iter;
-    for (x_iter = xf.begin(); x_iter != xf.end(); ++x_iter) {
-      out << indent() << "elseif ttype(res) == '" << (*x_iter)->get_type()->get_name() << "' then"
-          << endl << indent() << "  result." << (*x_iter)->get_name() << " = res" << endl;
-    }
-  }
-
-  // Set the result and write the reply
-  out << indent() << "else" << endl << indent() << "  result.success = res" << endl << indent()
-      << "end" << endl << indent() << "oprot:writeMessageBegin('" << fn_name << "', reply_type, "
-      << "seqid)" << endl << indent() << "result:write(oprot)" << endl << indent()
-      << "oprot:writeMessageEnd()" << endl << indent() << "oprot.trans:flush()" << endl;
-
-  indent_down();
-  indent(out) << "end" << endl;
-}
-
-// Service helpers
-void t_lua_generator::generate_service_helpers(ofstream& out, t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  out << endl << "-- HELPER FUNCTIONS AND STRUCTURES";
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_lua_struct_definition(out, ts, false);
-    generate_function_helpers(out, *f_iter);
-  }
-}
-
-void t_lua_generator::generate_function_helpers(ofstream& out, t_function* tfunction) {
-  if (!tfunction->is_oneway()) {
-    t_struct result(program_, tfunction->get_name() + "_result");
-    t_field success(tfunction->get_returntype(), "success", 0);
-    if (!tfunction->get_returntype()->is_void()) {
-      result.append(&success);
-    }
-
-    t_struct* xs = tfunction->get_xceptions();
-    const vector<t_field*>& fields = xs->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      result.append(*f_iter);
-    }
-    generate_lua_struct_definition(out, &result, false);
-  }
-}
-
-/**
- * Deserialize (Read)
- */
-void t_lua_generator::generate_deserialize_field(ofstream& out,
-                                                 t_field* tfield,
-                                                 bool local,
-                                                 string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, local, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, local, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-    indent(out) << (local ? "local " : "") << name << " = iprot:";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << "readString()";
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool()";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte()";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16()";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32()";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64()";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble()";
-        break;
-      default:
-        throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32()";
-    }
-    out << endl;
-
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-void t_lua_generator::generate_deserialize_struct(ofstream& out,
-                                                  t_struct* tstruct,
-                                                  bool local,
-                                                  string prefix) {
-  indent(out) << (local ? "local " : "") << prefix << " = " << tstruct->get_name() << ":new{}"
-              << endl << indent() << prefix << ":read(iprot)" << endl;
-}
-
-void t_lua_generator::generate_deserialize_container(ofstream& out,
-                                                     t_type* ttype,
-                                                     bool local,
-                                                     string prefix) {
-  string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
-
-  t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  // Declare variables, read header
-  indent(out) << (local ? "local " : "") << prefix << " = {}" << endl;
-  if (ttype->is_map()) {
-    indent(out) << "local " << ktype << ", " << vtype << ", " << size << " = iprot:readMapBegin() "
-                << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "local " << etype << ", " << size << " = iprot:readSetBegin()" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "local " << etype << ", " << size << " = iprot:readListBegin()" << endl;
-  }
-
-  // Deserialize
-  indent(out) << "for _i=1," << size << " do" << endl;
-  indent_up();
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  indent_down();
-  indent(out) << "end" << endl;
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "iprot:readMapEnd()" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "iprot:readSetEnd()" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "iprot:readListEnd()" << endl;
-  }
-}
-
-void t_lua_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  // A map is represented by a table indexable by any lua type
-  string key = tmp("_key");
-  string val = tmp("_val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  generate_deserialize_field(out, &fkey, true);
-  generate_deserialize_field(out, &fval, true);
-
-  indent(out) << prefix << "[" << key << "] = " << val << endl;
-}
-
-void t_lua_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  // A set is represented by a table indexed by the value
-  string elem = tmp("_elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  generate_deserialize_field(out, &felem, true);
-
-  indent(out) << prefix << "[" << elem << "] = " << elem << endl;
-}
-
-void t_lua_generator::generate_deserialize_list_element(ofstream& out,
-                                                        t_list* tlist,
-                                                        string prefix) {
-  // A list is represented by a table indexed by integer values
-  // LUA natively provides all of the functions required to maintain a list
-  string elem = tmp("_elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  generate_deserialize_field(out, &felem, true);
-
-  indent(out) << "table.insert(" << prefix << ", " << elem << ")" << endl;
-}
-
-/**
- * Serialize (Write)
- */
-void t_lua_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-  string name = prefix + tfield->get_name();
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-    indent(out) << "oprot:";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << "writeString(" << name << ")";
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ")";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ")";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ")";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ")";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ")";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ")";
-        break;
-      default:
-        throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32(" << name << ")";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
-           name.c_str(),
-           type->get_name().c_str());
-  }
-}
-
-void t_lua_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << prefix << ":write(oprot)" << endl;
-}
-
-void t_lua_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  // Begin writing
-  if (ttype->is_map()) {
-    indent(out) << "oprot:writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
-                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
-                << "ttable_size(" << prefix << "))" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot:writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
-                << "ttable_size(" << prefix << "))" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot:writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
-                << ", "
-                << "#" << prefix << ")" << endl;
-  }
-
-  // Serialize
-  if (ttype->is_map()) {
-    string kiter = tmp("kiter");
-    string viter = tmp("viter");
-    indent(out) << "for " << kiter << "," << viter << " in pairs(" << prefix << ") do" << endl;
-    indent_up();
-    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
-    indent_down();
-    indent(out) << "end" << endl;
-  } else if (ttype->is_set()) {
-    string iter = tmp("iter");
-    indent(out) << "for " << iter << ",_ in pairs(" << prefix << ") do" << endl;
-    indent_up();
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-    indent_down();
-    indent(out) << "end" << endl;
-  } else if (ttype->is_list()) {
-    string iter = tmp("iter");
-    indent(out) << "for _," << iter << " in ipairs(" << prefix << ") do" << endl;
-    indent_up();
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-    indent_down();
-    indent(out) << "end" << endl;
-  }
-
-  // Finish writing
-  if (ttype->is_map()) {
-    indent(out) << "oprot:writeMapEnd()" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot:writeSetEnd()" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot:writeListEnd()" << endl;
-  }
-}
-
-void t_lua_generator::generate_serialize_map_element(ofstream& out,
-                                                     t_map* tmap,
-                                                     string kiter,
-                                                     string viter) {
-  t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(out, &kfield, "");
-
-  t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(out, &vfield, "");
-}
-
-void t_lua_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-void t_lua_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- *  Helper rendering functions
- */
-string t_lua_generator::lua_includes() {
-  if (gen_requires_) {
-    return "\n\nrequire 'Thrift'";
-  } else {
-    return "";
-  }
-}
-
-string t_lua_generator::get_namespace(const t_program* program) {
-  std::string real_module = program->get_namespace("lua");
-  if (real_module.empty()) {
-    return program->get_name() + "_";
-  }
-  return real_module + "_";
-}
-
-string t_lua_generator::function_signature(t_function* tfunction, string prefix) {
-  (void)prefix;
-  std::string ret = tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")";
-  return ret;
-}
-
-string t_lua_generator::argument_list(t_struct* tstruct, string prefix) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator fld_iter;
-  std::string ret = "";
-  for (fld_iter = fields.begin(); fld_iter != fields.end();) {
-    ret += prefix + (*fld_iter)->get_name();
-    ++fld_iter;
-    if (fld_iter != fields.end()) {
-      ret += ", ";
-    }
-  }
-  return ret;
-}
-
-string t_lua_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "TType.I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_list()) {
-    return "TType.LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-THRIFT_REGISTER_GENERATOR(
-    lua,
-    "Lua",
-    "    omit_requires:   Suppress generation of require 'somefile'.\n")


[54/55] [abbrv] thrift git commit: Ensuring that HTTP failures will clear the http transport outbuf var

Posted by ns...@apache.org.
Ensuring that HTTP failures will clear the http transport outbuf var

This closes #1048


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/eacbd65f
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/eacbd65f
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/eacbd65f

Branch: refs/heads/master
Commit: eacbd65f1d5aaae6cd2a4cdac89ffbba049f3558
Parents: a400c69
Author: John Thomas <th...@vt.edu>
Authored: Tue Jul 12 08:06:19 2016 -0700
Committer: Nobuaki Sukegawa <ns...@apache.org>
Committed: Mon Sep 26 01:42:02 2016 +0900

----------------------------------------------------------------------
 lib/rb/lib/thrift/transport/http_client_transport.rb |  1 +
 lib/rb/spec/http_client_spec.rb                      | 15 +++++++++++++++
 2 files changed, 16 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/eacbd65f/lib/rb/lib/thrift/transport/http_client_transport.rb
----------------------------------------------------------------------
diff --git a/lib/rb/lib/thrift/transport/http_client_transport.rb b/lib/rb/lib/thrift/transport/http_client_transport.rb
index 77ffe35..c9c4fec 100644
--- a/lib/rb/lib/thrift/transport/http_client_transport.rb
+++ b/lib/rb/lib/thrift/transport/http_client_transport.rb
@@ -50,6 +50,7 @@ module Thrift
       data = resp.body
       data = Bytes.force_binary_encoding(data)
       @inbuf = StringIO.new data
+    ensure
       @outbuf = Bytes.empty_byte_buffer
     end
   end

http://git-wip-us.apache.org/repos/asf/thrift/blob/eacbd65f/lib/rb/spec/http_client_spec.rb
----------------------------------------------------------------------
diff --git a/lib/rb/spec/http_client_spec.rb b/lib/rb/spec/http_client_spec.rb
index 793fc73..5e8da24 100644
--- a/lib/rb/spec/http_client_spec.rb
+++ b/lib/rb/spec/http_client_spec.rb
@@ -67,6 +67,21 @@ describe 'Thrift::HTTPClientTransport' do
       end
       @client.flush
     end
+
+    it 'should reset the outbuf on HTTP failures' do
+      @client.write "test"
+
+      Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
+        mock("Net::HTTP").tap do |http|
+          http.should_receive(:use_ssl=).with(false)
+          http.should_receive(:post).with("/path/to/service?param=value", "test", {"Content-Type"=>"application/x-thrift"}) { raise Net::ReadTimeout }
+        end
+      end
+
+      @client.flush  rescue
+      @client.instance_variable_get(:@outbuf).should eq(Thrift::Bytes.empty_byte_buffer)
+    end
+
   end
 
   describe 'ssl enabled' do


[34/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_js_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_js_generator.cc b/compiler/cpp/src/generate/t_js_generator.cc
deleted file mode 100644
index af0f284..0000000
--- a/compiler/cpp/src/generate/t_js_generator.cc
+++ /dev/null
@@ -1,2231 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <map>
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <list>
-#include <cassert>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-#include "t_oop_generator.h"
-
-
-/**
- * JS code generator.
- */
-class t_js_generator : public t_oop_generator {
-public:
-  t_js_generator(t_program* program,
-                 const std::map<std::string, std::string>& parsed_options,
-                 const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    gen_node_ = false;
-    gen_jquery_ = false;
-    gen_ts_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("node") == 0) {
-        gen_node_ = true;
-      } else if( iter->first.compare("jquery") == 0) {
-        gen_jquery_ = true;
-      } else if( iter->first.compare("ts") == 0) {
-        gen_ts_ = true;
-      } else {
-        throw "unknown option js:" + iter->first; 
-      }
-    }
-
-    if (gen_node_ && gen_ts_) {
-      throw "Invalid switch: [-gen js:node,ts] options not compatible";
-    }
-
-    if (gen_node_ && gen_jquery_) {
-      throw "Invalid switch: [-gen js:node,jquery] options not compatible, try: [-gen js:node -gen "
-            "js:jquery]";
-    }
-
-    if (gen_node_) {
-      out_dir_base_ = "gen-nodejs";
-    } else {
-      out_dir_base_ = "gen-js";
-    }
-
-    escape_['\''] = "\\'";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_recv_throw(std::string var);
-  std::string render_recv_return(std::string var);
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-
-  /**
-   * Structs!
-   */
-  void generate_js_struct(t_struct* tstruct, bool is_exception);
-  void generate_js_struct_definition(std::ofstream& out,
-                                     t_struct* tstruct,
-                                     bool is_xception = false,
-                                     bool is_exported = true);
-  void generate_js_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_js_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_js_function_helpers(t_function* tfunction);
-
-  /**
-   * Service-level generation functions
-   */
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_rest(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_processor(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  bool inclass = false);
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string js_includes();
-  std::string render_includes();
-  std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
-  std::string function_signature(t_function* tfunction,
-                                 std::string prefix = "",
-                                 bool include_callback = false);
-  std::string argument_list(t_struct* tstruct, bool include_callback = false);
-  std::string type_to_enum(t_type* ttype);
-  std::string make_valid_nodeJs_identifier(std::string const& name);
-
-  std::string autogen_comment() {
-    return std::string("//\n") + "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-           + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
-           + "//\n";
-  }
-
-  t_type* get_contained_type(t_type* t);
-
-  std::vector<std::string> js_namespace_pieces(t_program* p) {
-    std::string ns = p->get_namespace("js");
-
-    std::string::size_type loc;
-    std::vector<std::string> pieces;
-
-    if (ns.size() > 0) {
-      while ((loc = ns.find(".")) != std::string::npos) {
-        pieces.push_back(ns.substr(0, loc));
-        ns = ns.substr(loc + 1);
-      }
-    }
-
-    if (ns.size() > 0) {
-      pieces.push_back(ns);
-    }
-
-    return pieces;
-  }
-
-  std::string js_type_namespace(t_program* p) {
-    if (gen_node_) {
-      if (p != NULL && p != program_) {
-        return make_valid_nodeJs_identifier(p->get_name()) + "_ttypes.";
-      }
-      return "ttypes.";
-    }
-    return js_namespace(p);
-  }
-
-  std::string js_export_namespace(t_program* p) {
-    if (gen_node_) {
-      return "exports.";
-    }
-    return js_namespace(p);
-  }
-
-  bool has_js_namespace(t_program* p) {
-    std::string ns = p->get_namespace("js");
-    return (ns.size() > 0);
-  }
-
-  std::string js_namespace(t_program* p) {
-    std::string ns = p->get_namespace("js");
-    if (ns.size() > 0) {
-      ns += ".";
-    }
-
-    return ns;
-  }
-
-  /**
-   * TypeScript Definition File helper functions
-   */
-
-  string ts_function_signature(t_function* tfunction, bool include_callback);
-  string ts_get_type(t_type* type);
-
-  /**
-   * Special indentation for TypeScript Definitions because of the module.
-   * Returns the normal indentation + "  " if a module was defined.
-   * @return string
-   */
-  string ts_indent() { return indent() + (!ts_module_.empty() ? "  " : ""); }
-
-  /**
-   * Returns "declare " if no module was defined.
-   * @return string
-   */
-  string ts_declare() { return (ts_module_.empty() ? "declare " : ""); }
-
-  /**
-   * Returns "?" if the given field is optional.
-   * @param t_field The field to check
-   * @return string
-   */
-  string ts_get_req(t_field* field) { return (field->get_req() == t_field::T_OPTIONAL ? "?" : ""); }
-
-  /**
-   * Returns the documentation, if the provided documentable object has one.
-   * @param t_doc The object to get the documentation from
-   * @return string The documentation
-   */
-  string ts_print_doc(t_doc* tdoc) {
-    string result = endl;
-
-    if (tdoc->has_doc()) {
-      std::stringstream doc(tdoc->get_doc());
-      string item;
-
-      result += ts_indent() + "/**" + endl;
-      while (std::getline(doc, item)) {
-        result += ts_indent() + " * " + item + endl;
-      }
-      result += ts_indent() + " */" + endl;
-    }
-    return result;
-  }
-
-private:
-  /**
-   * True if we should generate NodeJS-friendly RPC services.
-   */
-  bool gen_node_;
-
-  /**
-   * True if we should generate services that use jQuery ajax (async/sync).
-   */
-  bool gen_jquery_;
-
-  /**
-   * True if we should generate a TypeScript Definition File for each service.
-   */
-  bool gen_ts_;
-
-  /**
-   * The name of the defined module(s), for TypeScript Definition Files.
-   */
-  string ts_module_;
-
-  /**
-   * File streams
-   */
-  std::ofstream f_types_;
-  std::ofstream f_service_;
-  std::ofstream f_types_ts_;
-  std::ofstream f_service_ts_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_js_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  string outdir = get_out_dir();
-
-  // Make output file(s)
-  string f_types_name = outdir + program_->get_name() + "_types.js";
-  f_types_.open(f_types_name.c_str());
-
-  if (gen_ts_) {
-    string f_types_ts_name = outdir + program_->get_name() + "_types.d.ts";
-    f_types_ts_.open(f_types_ts_name.c_str());
-  }
-
-  // Print header
-  f_types_ << autogen_comment() << js_includes() << endl << render_includes() << endl;
-
-  if (gen_ts_) {
-    f_types_ts_ << autogen_comment() << endl;
-  }
-
-  if (gen_node_) {
-    f_types_ << "var ttypes = module.exports = {};" << endl;
-  }
-
-  string pns;
-
-  // setup the namespace
-  // TODO should the namespace just be in the directory structure for node?
-  vector<string> ns_pieces = js_namespace_pieces(program_);
-  if (ns_pieces.size() > 0) {
-    for (size_t i = 0; i < ns_pieces.size(); ++i) {
-      pns += ((i == 0) ? "" : ".") + ns_pieces[i];
-      f_types_ << "if (typeof " << pns << " === 'undefined') {" << endl;
-      f_types_ << "  " << pns << " = {};" << endl;
-      f_types_ << "}" << endl;
-    }
-    if (gen_ts_) {
-      ts_module_ = pns;
-      f_types_ts_ << "declare module " << ts_module_ << " {";
-    }
-  }
-}
-
-/**
- * Prints standard js imports
- */
-string t_js_generator::js_includes() {
-  if (gen_node_) {
-    return string(
-        "var thrift = require('thrift');\n"
-        "var Thrift = thrift.Thrift;\n"
-        "var Q = thrift.Q;\n");
-  }
-
-  return "";
-}
-
-/**
- * Renders all the imports necessary for including another Thrift program
- */
-string t_js_generator::render_includes() {
-  string result = "";
-
-  if (gen_node_) {
-    const vector<t_program*>& includes = program_->get_includes();
-    for (size_t i = 0; i < includes.size(); ++i) {
-      result += "var " + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name()
-                + "_types');\n";
-    }
-    if (includes.size() > 0) {
-      result += "\n";
-    }
-  }
-
-  return result;
-}
-
-/**
- * Close up (or down) some filez.
- */
-void t_js_generator::close_generator() {
-  // Close types file(s)
-
-  f_types_.close();
-
-  if (gen_ts_) {
-    if (!ts_module_.empty()) {
-      f_types_ts_ << "}";
-    }
-    f_types_ts_.close();
-  }
-}
-
-/**
- * Generates a typedef. This is not done in JS, types are all implicit.
- *
- * @param ttypedef The type definition
- */
-void t_js_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Generates code for an enumerated type. Since define is expensive to lookup
- * in JS, we use a global array for this.
- *
- * @param tenum The enumeration
- */
-void t_js_generator::generate_enum(t_enum* tenum) {
-  f_types_ << js_type_namespace(tenum->get_program()) << tenum->get_name() << " = {" << endl;
-
-  if (gen_ts_) {
-    f_types_ts_ << ts_print_doc(tenum) << ts_indent() << ts_declare() << "enum "
-                << tenum->get_name() << " {" << endl;
-  }
-
-  indent_up();
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    if (gen_ts_) {
-      f_types_ts_ << ts_indent() << (*c_iter)->get_name() << " = " << value << "," << endl;
-      // add 'value: key' in addition to 'key: value' for TypeScript enums
-      f_types_ << indent() << "'" << value << "' : '" << (*c_iter)->get_name() << "'," << endl;
-    }
-    f_types_ << indent() << "'" << (*c_iter)->get_name() << "' : " << value;
-    if (c_iter != constants.end() - 1) {
-      f_types_ << ",";
-    }
-    f_types_ << endl;
-  }
-
-  indent_down();
-
-  f_types_ << "};" << endl;
-
-  if (gen_ts_) {
-    f_types_ts_ << ts_indent() << "}" << endl;
-  }
-}
-
-/**
- * Generate a constant value
- */
-void t_js_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  f_types_ << js_type_namespace(program_) << name << " = ";
-  f_types_ << render_const_value(type, value) << ";" << endl;
-
-  if (gen_ts_) {
-    f_types_ts_ << ts_print_doc(tconst) << ts_indent() << ts_declare() << "var " << name << ": "
-                << ts_get_type(type) << ";" << endl;
-  }
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_js_generator::render_const_value(t_type* type, t_const_value* value) {
-  std::ostringstream out;
-
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << "'" << get_escaped_string(value) << "'";
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    out << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << "new " << js_type_namespace(type->get_program()) << type->get_name() << "({" << endl;
-    indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      if (v_iter != val.begin())
-        out << ",";
-      out << render_const_value(g_type_string, v_iter->first);
-      out << " : ";
-      out << render_const_value(field_type, v_iter->second);
-    }
-
-    out << "})";
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    out << "{" << endl;
-    indent_up();
-
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      if (v_iter != val.begin())
-        out << "," << endl;
-
-      out << indent() << render_const_value(ktype, v_iter->first);
-
-      out << " : ";
-      out << render_const_value(vtype, v_iter->second);
-    }
-
-    indent_down();
-    out << endl << "}";
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    out << "[";
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      if (v_iter != val.begin())
-        out << ",";
-      out << render_const_value(etype, *v_iter);
-    }
-    out << "]";
-  }
-  return out.str();
-}
-
-/**
- * Make a struct
- */
-void t_js_generator::generate_struct(t_struct* tstruct) {
-  generate_js_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_js_generator::generate_xception(t_struct* txception) {
-  generate_js_struct(txception, true);
-}
-
-/**
- * Structs can be normal or exceptions.
- */
-void t_js_generator::generate_js_struct(t_struct* tstruct, bool is_exception) {
-  generate_js_struct_definition(f_types_, tstruct, is_exception);
-}
-
-/**
- * Return type of contained elements for a container type. For maps
- * this is type of value (keys are always strings in js)
- */
-t_type* t_js_generator::get_contained_type(t_type* t) {
-  t_type* etype;
-  if (t->is_list()) {
-    etype = ((t_list*)t)->get_elem_type();
-  } else if (t->is_set()) {
-    etype = ((t_set*)t)->get_elem_type();
-  } else {
-    etype = ((t_map*)t)->get_val_type();
-  }
-  return etype;
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is nothing in JS
- * where the objects are all just associative arrays (unless of course we
- * decide to start using objects for them...)
- *
- * @param tstruct The struct definition
- */
-void t_js_generator::generate_js_struct_definition(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   bool is_exception,
-                                                   bool is_exported) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  if (gen_node_) {
-    string prefix = has_js_namespace(tstruct->get_program()) ? js_namespace(tstruct->get_program()) : "var ";
-    if (is_exported) {
-      out << prefix << tstruct->get_name() << " = "
-          << "module.exports." << tstruct->get_name() << " = function(args) {" << endl;
-    } else {
-      out << prefix << tstruct->get_name() << " = function(args) {"
-          << endl;
-    }
-  } else {
-    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = function(args) {"
-        << endl;
-    if (gen_ts_) {
-      f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class "
-                  << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "")
-                  << " {" << endl;
-    }
-  }
-
-  indent_up();
-
-  if (gen_node_ && is_exception) {
-    out << indent() << "Thrift.TException.call(this, \"" << js_namespace(tstruct->get_program())
-        << tstruct->get_name() << "\")" << endl;
-    out << indent() << "this.name = \"" << js_namespace(tstruct->get_program())
-        << tstruct->get_name() << "\"" << endl;
-  }
-
-  // members with arguments
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    string dval = declare_field(*m_iter, false, true);
-    t_type* t = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
-      dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
-      out << indent() << "this." << (*m_iter)->get_name() << " = " << dval << ";" << endl;
-    } else {
-      out << indent() << dval << ";" << endl;
-    }
-    if (gen_ts_) {
-      f_types_ts_ << ts_indent() << (*m_iter)->get_name() << ": "
-                  << ts_get_type((*m_iter)->get_type()) << ";" << endl;
-    }
-  }
-
-  // Generate constructor from array
-  if (members.size() > 0) {
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
-        indent(out) << "this." << (*m_iter)->get_name() << " = "
-                    << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
-      }
-    }
-
-    // Early returns for exceptions
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      if (t->is_xception()) {
-        out << indent() << "if (args instanceof " << js_type_namespace(t->get_program())
-            << t->get_name() << ") {" << endl << indent() << indent() << "this."
-            << (*m_iter)->get_name() << " = args;" << endl << indent() << indent() << "return;"
-            << endl << indent() << "}" << endl;
-      }
-    }
-
-    out << indent() << "if (args) {" << endl;
-    if (gen_ts_) {
-      f_types_ts_ << endl << ts_indent() << "constructor(args?: { ";
-    }
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      out << indent() << indent() << "if (args." << (*m_iter)->get_name() << " !== undefined && args." << (*m_iter)->get_name() << " !== null) {"
-          << endl << indent() << indent() << indent() << "this." << (*m_iter)->get_name();
-
-      if (t->is_struct()) {
-        out << (" = new " + js_type_namespace(t->get_program()) + t->get_name() +
-                "(args."+(*m_iter)->get_name() +");");
-        out << endl;
-      } else if (t->is_container()) {
-        t_type* etype = get_contained_type(t);
-        string copyFunc = t->is_map() ? "Thrift.copyMap" : "Thrift.copyList";
-        string type_list = "";
-
-        while (etype->is_container()) {
-          if (type_list.length() > 0) {
-            type_list += ", ";
-          }
-          type_list += etype->is_map() ? "Thrift.copyMap" : "Thrift.copyList";
-          etype = get_contained_type(etype);
-        }
-
-        if (etype->is_struct()) {
-          if (type_list.length() > 0) {
-            type_list += ", ";
-          }
-          type_list += js_type_namespace(etype->get_program()) + etype->get_name();
-        }
-        else {
-          if (type_list.length() > 0) {
-            type_list += ", ";
-          }
-          type_list += "null";
-        }
-
-        out << (" = " + copyFunc + "(args." + (*m_iter)->get_name() +
-                ", [" + type_list + "]);");
-        out << endl;
-      } else {
-        out << " = args." << (*m_iter)->get_name() << ";" << endl;
-      }
-
-      if (!(*m_iter)->get_req()) {
-        out << indent() << indent() << "} else {" << endl << indent() << indent() << indent()
-            << "throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.UNKNOWN, "
-               "'Required field " << (*m_iter)->get_name() << " is unset!');" << endl;
-      }
-      out << indent() << indent() << "}" << endl;
-      if (gen_ts_) {
-        f_types_ts_ << (*m_iter)->get_name() << ts_get_req(*m_iter) << ": "
-                    << ts_get_type((*m_iter)->get_type()) << "; ";
-      }
-    }
-
-    out << indent() << "}" << endl;
-    if (gen_ts_) {
-      f_types_ts_ << "});" << endl;
-    }
-  }
-
-  indent_down();
-  out << "};" << endl;
-  if (gen_ts_) {
-    f_types_ts_ << ts_indent() << "}" << endl;
-  }
-
-  if (is_exception) {
-    out << "Thrift.inherits(" << js_namespace(tstruct->get_program()) << tstruct->get_name()
-        << ", Thrift.TException);" << endl;
-    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.name = '"
-        << tstruct->get_name() << "';" << endl;
-  } else {
-    // init prototype
-    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype = {};"
-        << endl;
-  }
-
-  generate_js_struct_reader(out, tstruct);
-  generate_js_struct_writer(out, tstruct);
-}
-
-/**
- * Generates the read() method for a struct
- */
-void t_js_generator::generate_js_struct_reader(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << js_namespace(tstruct->get_program()) << tstruct->get_name()
-      << ".prototype.read = function(input) {" << endl;
-
-  indent_up();
-
-  indent(out) << "input.readStructBegin();" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-
-  scope_up(out);
-
-  indent(out) << "var ret = input.readFieldBegin();" << endl;
-  indent(out) << "var fname = ret.fname;" << endl;
-  indent(out) << "var ftype = ret.ftype;" << endl;
-  indent(out) << "var fid = ret.fid;" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if (ftype == Thrift.Type.STOP) {" << endl;
-  indent_up();
-  indent(out) << "break;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-  if (!fields.empty()) {
-    // Switch statement on the field we are reading
-    indent(out) << "switch (fid)" << endl;
-
-    scope_up(out);
-
-    // Generate deserialization code for known cases
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-
-      indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
-      indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-
-      indent_up();
-      generate_deserialize_field(out, *f_iter, "this.");
-      indent_down();
-
-      indent(out) << "} else {" << endl;
-
-      indent(out) << "  input.skip(ftype);" << endl;
-
-      out << indent() << "}" << endl << indent() << "break;" << endl;
-    }
-    if (fields.size() == 1) {
-      // pseudo case to make jslint happy
-      indent(out) << "case 0:" << endl;
-      indent(out) << "  input.skip(ftype);" << endl;
-      indent(out) << "  break;" << endl;
-    }
-    // In the default case we skip the field
-    indent(out) << "default:" << endl;
-    indent(out) << "  input.skip(ftype);" << endl;
-
-    scope_down(out);
-  } else {
-    indent(out) << "input.skip(ftype);" << endl;
-  }
-
-  indent(out) << "input.readFieldEnd();" << endl;
-
-  scope_down(out);
-
-  indent(out) << "input.readStructEnd();" << endl;
-
-  indent(out) << "return;" << endl;
-
-  indent_down();
-  out << indent() << "};" << endl << endl;
-}
-
-/**
- * Generates the write() method for a struct
- */
-void t_js_generator::generate_js_struct_writer(ofstream& out, t_struct* tstruct) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << js_namespace(tstruct->get_program()) << tstruct->get_name()
-      << ".prototype.write = function(output) {" << endl;
-
-  indent_up();
-
-  indent(out) << "output.writeStructBegin('" << name << "');" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    out << indent() << "if (this." << (*f_iter)->get_name() << " !== null && this."
-        << (*f_iter)->get_name() << " !== undefined) {" << endl;
-    indent_up();
-
-    indent(out) << "output.writeFieldBegin("
-                << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
-                << ", " << (*f_iter)->get_key() << ");" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    indent(out) << "output.writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}" << endl;
-  }
-
-  out << indent() << "output.writeFieldStop();" << endl << indent() << "output.writeStructEnd();"
-      << endl;
-
-  out << indent() << "return;" << endl;
-
-  indent_down();
-  out << indent() << "};" << endl << endl;
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_js_generator::generate_service(t_service* tservice) {
-  string f_service_name = get_out_dir() + service_name_ + ".js";
-  f_service_.open(f_service_name.c_str());
-
-  if (gen_ts_) {
-    string f_service_ts_name = get_out_dir() + service_name_ + ".d.ts";
-    f_service_ts_.open(f_service_ts_name.c_str());
-  }
-
-  f_service_ << autogen_comment() << js_includes() << endl << render_includes() << endl;
-
-  if (gen_ts_) {
-    if (tservice->get_extends() != NULL) {
-      f_service_ts_ << "/// <reference path=\"" << tservice->get_extends()->get_name()
-                    << ".d.ts\" />" << endl;
-    }
-    f_service_ts_ << autogen_comment() << endl;
-    if (!ts_module_.empty()) {
-      f_service_ts_ << "declare module " << ts_module_ << " {";
-    }
-  }
-
-  if (gen_node_) {
-    if (tservice->get_extends() != NULL) {
-      f_service_ << "var " << tservice->get_extends()->get_name() << " = require('./"
-                 << tservice->get_extends()->get_name() << "');" << endl << "var "
-                 << tservice->get_extends()->get_name()
-                 << "Client = " << tservice->get_extends()->get_name() << ".Client;" << endl
-                 << "var " << tservice->get_extends()->get_name()
-                 << "Processor = " << tservice->get_extends()->get_name() << ".Processor;" << endl;
-    }
-
-    f_service_ << "var ttypes = require('./" + program_->get_name() + "_types');" << endl;
-  }
-
-  generate_service_helpers(tservice);
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-
-  if (gen_node_) {
-    generate_service_processor(tservice);
-  }
-
-  f_service_.close();
-  if (gen_ts_) {
-    if (!ts_module_.empty()) {
-      f_service_ts_ << "}";
-    }
-    f_service_ts_.close();
-  }
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_js_generator::generate_service_processor(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  if (gen_node_) {
-    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : "var ";
-    f_service_ << prefix << service_name_ << "Processor = " << "exports.Processor = function(handler) ";
-  } else {
-    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Processor = "
-             << "exports.Processor = function(handler) ";
-  }
-
-  scope_up(f_service_);
-
-  f_service_ << indent() << "this._handler = handler" << endl;
-
-  scope_down(f_service_);
-
-  if (tservice->get_extends() != NULL) {
-    indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
-                       << service_name_ << "Processor, " << tservice->get_extends()->get_name()
-                       << "Processor)" << endl;
-  }
-
-  // Generate the server implementation
-  indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                     << "Processor.prototype.process = function(input, output) ";
-
-  scope_up(f_service_);
-
-  f_service_ << indent() << "var r = input.readMessageBegin();" << endl << indent()
-             << "if (this['process_' + r.fname]) {" << endl << indent()
-             << "  return this['process_' + r.fname].call(this, r.rseqid, input, output);" << endl
-             << indent() << "} else {" << endl << indent() << "  input.skip(Thrift.Type.STRUCT);"
-             << endl << indent() << "  input.readMessageEnd();" << endl << indent()
-             << "  var x = new "
-                "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN_METHOD, "
-                "'Unknown function ' + r.fname);" << endl << indent()
-             << "  output.writeMessageBegin(r.fname, Thrift.MessageType.EXCEPTION, r.rseqid);"
-             << endl << indent() << "  x.write(output);" << endl << indent()
-             << "  output.writeMessageEnd();" << endl << indent() << "  output.flush();" << endl
-             << indent() << "}" << endl;
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_js_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                     << "Processor.prototype.process_" + tfunction->get_name()
-                        + " = function(seqid, input, output) ";
-
-  scope_up(f_service_);
-
-  string argsname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name() + "_args";
-  string resultname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name()
-                      + "_result";
-
-  f_service_ << indent() << "var args = new " << argsname << "();" << endl << indent()
-             << "args.read(input);" << endl << indent() << "input.readMessageEnd();" << endl;
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    indent(f_service_) << "this._handler." << tfunction->get_name() << "(";
-
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-
-    f_service_ << ")" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-    return;
-  }
-
-  f_service_ << indent() << "if (this._handler." << tfunction->get_name()
-             << ".length === " << fields.size() << ") {" << endl;
-  indent_up();
-  indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name();
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    f_service_ << ", args." << (*f_iter)->get_name();
-  }
-
-  f_service_ << ")" << endl;
-  indent_up();
-  indent(f_service_) << ".then(function(result) {" << endl;
-  indent_up();
-  f_service_ << indent() << "var result = new " << resultname << "({success: result});" << endl
-             << indent() << "output.writeMessageBegin(\"" << tfunction->get_name()
-             << "\", Thrift.MessageType.REPLY, seqid);" << endl << indent()
-             << "result.write(output);" << endl << indent() << "output.writeMessageEnd();" << endl
-             << indent() << "output.flush();" << endl;
-  indent_down();
-  indent(f_service_) << "}, function (err) {" << endl;
-  indent_up();
-
-  bool has_exception = false;
-  t_struct* exceptions = tfunction->get_xceptions();
-  if (exceptions) {
-    const vector<t_field*>& members = exceptions->get_members();
-    for (vector<t_field*>::const_iterator it = members.begin(); it != members.end(); ++it) {
-      t_type* t = get_true_type((*it)->get_type());
-      if (t->is_xception()) {
-        if (!has_exception) {
-          has_exception = true;
-          indent(f_service_) << "if (err instanceof " << js_type_namespace(t->get_program())
-                             << t->get_name();
-        } else {
-          f_service_ << " || err instanceof " << js_type_namespace(t->get_program())
-                     << t->get_name();
-        }
-      }
-    }
-  }
-
-  if (has_exception) {
-    f_service_ << ") {" << endl;
-    indent_up();
-    f_service_ << indent() << "var result = new " << resultname << "(err);" << endl << indent()
-               << "output.writeMessageBegin(\"" << tfunction->get_name()
-               << "\", Thrift.MessageType.REPLY, seqid);" << endl;
-
-    indent_down();
-    indent(f_service_) << "} else {" << endl;
-    indent_up();
-  }
-
-  f_service_ << indent() << "var result = new "
-                            "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN,"
-                            " err.message);" << endl << indent() << "output.writeMessageBegin(\""
-             << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << endl;
-
-  if (has_exception) {
-    indent_down();
-    indent(f_service_) << "}" << endl;
-  }
-
-  f_service_ << indent() << "result.write(output);" << endl << indent()
-             << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl;
-  indent_down();
-  indent(f_service_) << "});" << endl;
-  indent_down();
-  indent_down();
-  indent(f_service_) << "} else {" << endl;
-  indent_up();
-  indent(f_service_) << "this._handler." << tfunction->get_name() << "(";
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    f_service_ << "args." << (*f_iter)->get_name() << ", ";
-  }
-
-  f_service_ << "function (err, result) {" << endl;
-  indent_up();
-
-  indent(f_service_) << "if (err == null";
-  if (has_exception) {
-    const vector<t_field*>& members = exceptions->get_members();
-    for (vector<t_field*>::const_iterator it = members.begin(); it != members.end(); ++it) {
-      t_type* t = get_true_type((*it)->get_type());
-      if (t->is_xception()) {
-        f_service_ << " || err instanceof " << js_type_namespace(t->get_program()) << t->get_name();
-      }
-    }
-  }
-  f_service_ << ") {" << endl;
-  indent_up();
-  f_service_ << indent() << "var result = new " << resultname
-             << "((err != null ? err : {success: result}));" << endl << indent()
-             << "output.writeMessageBegin(\"" << tfunction->get_name()
-             << "\", Thrift.MessageType.REPLY, seqid);" << endl;
-  indent_down();
-  indent(f_service_) << "} else {" << endl;
-  indent_up();
-  f_service_ << indent() << "var result = new "
-                            "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN,"
-                            " err.message);" << endl << indent() << "output.writeMessageBegin(\""
-             << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << endl;
-  indent_down();
-  f_service_ << indent() << "}" << endl << indent() << "result.write(output);" << endl << indent()
-             << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl;
-
-  indent_down();
-  indent(f_service_) << "});" << endl;
-  indent_down();
-  indent(f_service_) << "}" << endl;
-  scope_down(f_service_);
-  f_service_ << endl;
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_js_generator::generate_service_helpers(t_service* tservice) {
-  // Do not generate TS definitions for helper functions
-  bool gen_ts_tmp = gen_ts_;
-  gen_ts_ = false;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  f_service_ << "//HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    string name = ts->get_name();
-    ts->set_name(service_name_ + "_" + name);
-    generate_js_struct_definition(f_service_, ts, false, false);
-    generate_js_function_helpers(*f_iter);
-    ts->set_name(name);
-  }
-
-  gen_ts_ = gen_ts_tmp;
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_js_generator::generate_js_function_helpers(t_function* tfunction) {
-  t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_js_struct_definition(f_service_, &result, false, false);
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_js_generator::generate_service_interface(t_service* tservice) {
-  (void)tservice;
-}
-
-/**
- * Generates a REST interface
- */
-void t_js_generator::generate_service_rest(t_service* tservice) {
-  (void)tservice;
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_js_generator::generate_service_client(t_service* tservice) {
-  if (gen_node_) {
-    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : "var ";
-    f_service_ << prefix << service_name_ << "Client = "
-               << "exports.Client = function(output, pClass) {" << endl;
-  } else {
-    f_service_ << js_namespace(tservice->get_program()) << service_name_
-               << "Client = function(input, output) {" << endl;
-    if (gen_ts_) {
-      f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class "
-                    << service_name_ << "Client ";
-      if (tservice->get_extends() != NULL) {
-        f_service_ts_ << "extends " << tservice->get_extends()->get_name() << "Client ";
-      }
-      f_service_ts_ << "{" << endl;
-    }
-  }
-
-  indent_up();
-
-  if (gen_node_) {
-    f_service_ << indent() << "  this.output = output;" << endl << indent()
-               << "  this.pClass = pClass;" << endl << indent() << "  this._seqid = 0;" << endl
-               << indent() << "  this._reqs = {};" << endl;
-  } else {
-    f_service_ << indent() << "  this.input = input;" << endl << indent()
-               << "  this.output = (!output) ? input : output;" << endl << indent()
-               << "  this.seqid = 0;" << endl;
-    if (gen_ts_) {
-      f_service_ts_ << ts_indent() << "input: Thrift.TJSONProtocol;" << endl << ts_indent()
-                    << "output: Thrift.TJSONProtocol;" << endl << ts_indent() << "seqid: number;"
-                    << endl << endl << ts_indent()
-                    << "constructor(input: Thrift.TJSONProtocol, output?: Thrift.TJSONProtocol);"
-                    << endl;
-    }
-  }
-
-  indent_down();
-
-  f_service_ << indent() << "};" << endl;
-
-  if (tservice->get_extends() != NULL) {
-    indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
-                       << service_name_ << "Client, "
-                       << js_namespace(tservice->get_extends()->get_program())
-                       << tservice->get_extends()->get_name() << "Client);" << endl;
-  } else {
-    // init prototype
-    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                       << "Client.prototype = {};" << endl;
-  }
-
-  // utils for multiplexed services
-  if (gen_node_) {
-    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                       << "Client.prototype.seqid = function() { return this._seqid; }" << endl
-                       << js_namespace(tservice->get_program()) << service_name_
-                       << "Client.prototype.new_seqid = function() { return this._seqid += 1; }"
-                       << endl;
-  }
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-    string arglist = argument_list(arg_struct);
-
-    // Open function
-    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype."
-               << function_signature(*f_iter, "", true) << " {" << endl;
-
-    indent_up();
-
-    if (gen_ts_) {
-      f_service_ts_ << ts_print_doc(*f_iter) <<
-          // function definition without callback
-          ts_indent() << ts_function_signature(*f_iter, false) << endl << ts_print_doc(*f_iter) <<
-          // overload with callback
-          ts_indent() << ts_function_signature(*f_iter, true) << endl;
-    }
-
-    if (gen_node_) { // Node.js output      ./gen-nodejs
-      f_service_ << indent() << "this._seqid = this.new_seqid();" << endl << indent()
-                 << "if (callback === undefined) {" << endl;
-      indent_up();
-      f_service_ << indent() << "var _defer = Q.defer();" << endl << indent()
-                 << "this._reqs[this.seqid()] = function(error, result) {" << endl;
-      indent_up();
-      indent(f_service_) << "if (error) {" << endl;
-      indent_up();
-      indent(f_service_) << "_defer.reject(error);" << endl;
-      indent_down();
-      indent(f_service_) << "} else {" << endl;
-      indent_up();
-      indent(f_service_) << "_defer.resolve(result);" << endl;
-      indent_down();
-      indent(f_service_) << "}" << endl;
-      indent_down();
-      indent(f_service_) << "};" << endl;
-      f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");" << endl
-                 << indent() << "return _defer.promise;" << endl;
-      indent_down();
-      indent(f_service_) << "} else {" << endl;
-      indent_up();
-      f_service_ << indent() << "this._reqs[this.seqid()] = callback;" << endl << indent()
-                 << "this.send_" << funname << "(" << arglist << ");" << endl;
-      indent_down();
-      indent(f_service_) << "}" << endl;
-    } else if (gen_jquery_) { // jQuery output       ./gen-js
-      f_service_ << indent() << "if (callback === undefined) {" << endl;
-      indent_up();
-      f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");" << endl;
-      if (!(*f_iter)->is_oneway()) {
-        f_service_ << indent();
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          f_service_ << "return ";
-        }
-        f_service_ << "this.recv_" << funname << "();" << endl;
-      }
-      indent_down();
-      f_service_ << indent() << "} else {" << endl;
-      indent_up();
-      f_service_ << indent() << "var postData = this.send_" << funname << "(" << arglist
-                 << (arglist.empty() ? "" : ", ") << "true);" << endl;
-      f_service_ << indent() << "return this.output.getTransport()" << endl;
-      indent_up();
-      f_service_ << indent() << ".jqRequest(this, postData, arguments, this.recv_" << funname
-                 << ");" << endl;
-      indent_down();
-      indent_down();
-      f_service_ << indent() << "}" << endl;
-    } else { // Standard JavaScript ./gen-js
-      f_service_ << indent() << "this.send_" << funname << "(" << arglist
-                 << (arglist.empty() ? "" : ", ") << "callback); " << endl;
-      if (!(*f_iter)->is_oneway()) {
-        f_service_ << indent() << "if (!callback) {" << endl;
-        f_service_ << indent();
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          f_service_ << "  return ";
-        }
-        f_service_ << "this.recv_" << funname << "();" << endl;
-        f_service_ << indent() << "}" << endl;
-      }
-    }
-
-    indent_down();
-
-    f_service_ << "};" << endl << endl;
-
-    // Send function
-    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.send_"
-               << function_signature(*f_iter, "", !gen_node_) << " {" << endl;
-
-    indent_up();
-
-    std::string outputVar;
-    if (gen_node_) {
-      f_service_ << indent() << "var output = new this.pClass(this.output);" << endl;
-      outputVar = "output";
-    } else {
-      outputVar = "this.output";
-    }
-
-    std::string argsname = js_namespace(program_) + service_name_ + "_" + (*f_iter)->get_name()
-                           + "_args";
-
-    std::string messageType = (*f_iter)->is_oneway() ? "Thrift.MessageType.ONEWAY"
-                                                     : "Thrift.MessageType.CALL";
-
-    // Serialize the request header
-    if (gen_node_) {
-      f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name()
-                 << "', " << messageType << ", this.seqid());" << endl;
-    } else {
-      f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name()
-                 << "', " << messageType << ", this.seqid);" << endl;
-    }
-
-    f_service_ << indent() << "var args = new " << argsname << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
-                 << (*fld_iter)->get_name() << ";" << endl;
-    }
-
-    // Write to the stream
-    f_service_ << indent() << "args.write(" << outputVar << ");" << endl << indent() << outputVar
-               << ".writeMessageEnd();" << endl;
-
-    if (gen_node_) {
-      f_service_ << indent() << "return this.output.flush();" << endl;
-    } else {
-      if (gen_jquery_) {
-        f_service_ << indent() << "return this.output.getTransport().flush(callback);" << endl;
-      } else {
-        f_service_ << indent() << "if (callback) {" << endl;
-        f_service_ << indent() << "  var self = this;" << endl;
-        f_service_ << indent() << "  this.output.getTransport().flush(true, function() {" << endl;
-        f_service_ << indent() << "    var result = null;" << endl;
-        f_service_ << indent() << "    try {" << endl;
-        f_service_ << indent() << "      result = self.recv_" << funname << "();" << endl;
-        f_service_ << indent() << "    } catch (e) {" << endl;
-        f_service_ << indent() << "      result = e;" << endl;
-        f_service_ << indent() << "    }" << endl;
-        f_service_ << indent() << "    callback(result);" << endl;
-        f_service_ << indent() << "  });" << endl;
-        f_service_ << indent() << "} else {" << endl;
-        f_service_ << indent() << "  return this.output.getTransport().flush();" << endl;
-        f_service_ << indent() << "}" << endl;
-      }
-    }
-
-    indent_down();
-
-    f_service_ << "};" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = js_namespace(tservice->get_program()) + service_name_ + "_"
-                               + (*f_iter)->get_name() + "_result";
-
-      if (gen_node_) {
-        // Open function
-        f_service_ << endl << js_namespace(tservice->get_program()) << service_name_
-                   << "Client.prototype.recv_" << (*f_iter)->get_name()
-                   << " = function(input,mtype,rseqid) {" << endl;
-      } else {
-        t_struct noargs(program_);
-
-        t_function recv_function((*f_iter)->get_returntype(),
-                                 string("recv_") + (*f_iter)->get_name(),
-                                 &noargs);
-        // Open function
-        f_service_ << endl << js_namespace(tservice->get_program()) << service_name_
-                   << "Client.prototype." << function_signature(&recv_function) << " {" << endl;
-      }
-
-      indent_up();
-
-      std::string inputVar;
-      if (gen_node_) {
-        inputVar = "input";
-      } else {
-        inputVar = "this.input";
-      }
-
-      if (gen_node_) {
-        f_service_ << indent() << "var callback = this._reqs[rseqid] || function() {};" << endl
-                   << indent() << "delete this._reqs[rseqid];" << endl;
-      } else {
-        f_service_ << indent() << "var ret = this.input.readMessageBegin();" << endl << indent()
-                   << "var fname = ret.fname;" << endl << indent() << "var mtype = ret.mtype;"
-                   << endl << indent() << "var rseqid = ret.rseqid;" << endl;
-      }
-
-      f_service_ << indent() << "if (mtype == Thrift.MessageType.EXCEPTION) {" << endl << indent()
-                 << "  var x = new Thrift.TApplicationException();" << endl << indent()
-                 << "  x.read(" << inputVar << ");" << endl << indent() << "  " << inputVar
-                 << ".readMessageEnd();" << endl << indent() << "  " << render_recv_throw("x")
-                 << endl << indent() << "}" << endl;
-
-      f_service_ << indent() << "var result = new " << resultname << "();" << endl << indent()
-                 << "result.read(" << inputVar << ");" << endl;
-
-      f_service_ << indent() << inputVar << ".readMessageEnd();" << endl << endl;
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "if (null !== result." << (*x_iter)->get_name() << ") {" << endl
-                   << indent() << "  " << render_recv_throw("result." + (*x_iter)->get_name())
-                   << endl << indent() << "}" << endl;
-      }
-
-      // Careful, only return result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "if (null !== result.success) {" << endl << indent() << "  "
-                   << render_recv_return("result.success") << endl << indent() << "}" << endl;
-        f_service_ << indent()
-                   << render_recv_throw("'" + (*f_iter)->get_name() + " failed: unknown result'")
-                   << endl;
-      } else {
-        if (gen_node_) {
-          indent(f_service_) << "callback(null)" << endl;
-        } else {
-          indent(f_service_) << "return;" << endl;
-        }
-      }
-
-      // Close function
-      indent_down();
-      f_service_ << "};" << endl;
-    }
-  }
-
-  if (gen_ts_) {
-    f_service_ts_ << ts_indent() << "}" << endl;
-  }
-}
-
-std::string t_js_generator::render_recv_throw(std::string var) {
-  if (gen_node_) {
-    return "return callback(" + var + ");";
-  } else {
-    return "throw " + var + ";";
-  }
-}
-
-std::string t_js_generator::render_recv_return(std::string var) {
-  if (gen_node_) {
-    return "return callback(null, " + var + ");";
-  } else {
-    return "return " + var + ";";
-  }
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_js_generator::generate_deserialize_field(ofstream& out,
-                                                t_field* tfield,
-                                                string prefix,
-                                                bool inclass) {
-  (void)inclass;
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-    indent(out) << name << " = input.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << (((t_base_type*)type)->is_binary() ? "readBinary()" : "readString()");
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool()";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte()";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16()";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32()";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64()";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble()";
-        break;
-      default:
-        throw "compiler error: no JS name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32()";
-    }
-
-    if (!gen_node_) {
-      out << ".value";
-    }
-
-    out << ";" << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a variable. This makes two key assumptions,
- * first that there is a const char* variable named data that points to the
- * buffer for deserialization, and that there is a variable protocol which
- * is a reference to a TProtocol serialization object.
- */
-void t_js_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  out << indent() << prefix << " = new " << js_type_namespace(tstruct->get_program())
-      << tstruct->get_name() << "();" << endl << indent() << prefix << ".read(input);" << endl;
-}
-
-void t_js_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
-  string rtmp3 = tmp("_rtmp3");
-
-  t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  out << indent() << "var " << size << " = 0;" << endl;
-  out << indent() << "var " << rtmp3 << ";" << endl;
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    out << indent() << prefix << " = {};" << endl << indent() << "var " << ktype << " = 0;" << endl
-        << indent() << "var " << vtype << " = 0;" << endl;
-
-    out << indent() << rtmp3 << " = input.readMapBegin();" << endl;
-    out << indent() << ktype << " = " << rtmp3 << ".ktype;" << endl;
-    out << indent() << vtype << " = " << rtmp3 << ".vtype;" << endl;
-    out << indent() << size << " = " << rtmp3 << ".size;" << endl;
-
-  } else if (ttype->is_set()) {
-
-    out << indent() << prefix << " = [];" << endl << indent() << "var " << etype << " = 0;" << endl
-        << indent() << rtmp3 << " = input.readSetBegin();" << endl << indent() << etype << " = "
-        << rtmp3 << ".etype;" << endl << indent() << size << " = " << rtmp3 << ".size;" << endl;
-
-  } else if (ttype->is_list()) {
-
-    out << indent() << prefix << " = [];" << endl << indent() << "var " << etype << " = 0;" << endl
-        << indent() << rtmp3 << " = input.readListBegin();" << endl << indent() << etype << " = "
-        << rtmp3 << ".etype;" << endl << indent() << size << " = " << rtmp3 << ".size;" << endl;
-  }
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) << "for (var " << i << " = 0; " << i << " < " << size << "; ++" << i << ")" << endl;
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    if (!gen_node_) {
-      out << indent() << "if (" << i << " > 0 ) {" << endl << indent()
-          << "  if (input.rstack.length > input.rpos[input.rpos.length -1] + 1) {" << endl
-          << indent() << "    input.rstack.pop();" << endl << indent() << "  }" << endl << indent()
-          << "}" << endl;
-    }
-
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  scope_down(out);
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "input.readMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "input.readSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "input.readListEnd();" << endl;
-  }
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_js_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("key");
-  string val = tmp("val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  indent(out) << declare_field(&fkey, false, false) << ";" << endl;
-  indent(out) << declare_field(&fval, false, false) << ";" << endl;
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
-}
-
-void t_js_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  indent(out) << "var " << elem << " = null;" << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".push(" << elem << ");" << endl;
-}
-
-void t_js_generator::generate_deserialize_list_element(ofstream& out,
-                                                       t_list* tlist,
-                                                       string prefix) {
-  string elem = tmp("elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  indent(out) << "var " << elem << " = null;" << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".push(" << elem << ");" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_js_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + tfield->get_name());
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = tfield->get_name();
-
-    // Hack for when prefix is defined (always a hash ref)
-    if (!prefix.empty())
-      name = prefix + tfield->get_name();
-
-    indent(out) << "output.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << (((t_base_type*)type)->is_binary() ? "writeBinary(" : "writeString(") << name << ")";
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ")";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ")";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ")";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ")";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ")";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ")";
-        break;
-      default:
-        throw "compiler error: no JS name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32(" << name << ")";
-    }
-    out << ";" << endl;
-
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_js_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << prefix << ".write(output);" << endl;
-}
-
-/**
- * Writes out a container
- */
-void t_js_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  if (ttype->is_map()) {
-    indent(out) << "output.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
-                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
-                << "Thrift.objectLength(" << prefix << "));" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "output.writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
-                << prefix << ".length);" << endl;
-
-  } else if (ttype->is_list()) {
-
-    indent(out) << "output.writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
-                << ", " << prefix << ".length);" << endl;
-  }
-
-  if (ttype->is_map()) {
-    string kiter = tmp("kiter");
-    string viter = tmp("viter");
-    indent(out) << "for (var " << kiter << " in " << prefix << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (" << prefix << ".hasOwnProperty(" << kiter << "))" << endl;
-    scope_up(out);
-    indent(out) << "var " << viter << " = " << prefix << "[" << kiter << "];" << endl;
-    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
-    scope_down(out);
-    scope_down(out);
-
-  } else if (ttype->is_set()) {
-    string iter = tmp("iter");
-    indent(out) << "for (var " << iter << " in " << prefix << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << "))" << endl;
-    scope_up(out);
-    indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl;
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-    scope_down(out);
-    scope_down(out);
-
-  } else if (ttype->is_list()) {
-    string iter = tmp("iter");
-    indent(out) << "for (var " << iter << " in " << prefix << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << "))" << endl;
-    scope_up(out);
-    indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl;
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-    scope_down(out);
-    scope_down(out);
-  }
-
-  if (ttype->is_map()) {
-    indent(out) << "output.writeMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "output.writeSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "output.writeListEnd();" << endl;
-  }
-}
-
-/**
- * Serializes the members of a map.
- *
- */
-void t_js_generator::generate_serialize_map_element(ofstream& out,
-                                                    t_map* tmap,
-                                                    string kiter,
-                                                    string viter) {
-  t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(out, &kfield);
-
-  t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(out, &vfield);
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_js_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield);
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_js_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield);
-}
-
-/**
- * Declares a field, which may include initialization as necessary.
- *
- * @param ttype The type
- */
-string t_js_generator::declare_field(t_field* tfield, bool init, bool obj) {
-  string result = "this." + tfield->get_name();
-
-  if (!obj) {
-    result = "var " + tfield->get_name();
-  }
-
-  if (init) {
-    t_type* type = get_true_type(tfield->get_type());
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        break;
-      case t_base_type::TYPE_STRING:
-      case t_base_type::TYPE_BOOL:
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-      case t_base_type::TYPE_DOUBLE:
-        result += " = null";
-        break;
-      default:
-        throw "compiler error: no JS initializer for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      result += " = null";
-    } else if (type->is_map()) {
-      result += " = null";
-    } else if (type->is_container()) {
-      result += " = null";
-    } else if (type->is_struct() || type->is_xception()) {
-      if (obj) {
-        result += " = new " + js_type_namespace(type->get_program()) + type->get_name() + "()";
-      } else {
-        result += " = null";
-      }
-    }
-  } else {
-    result += " = null";
-  }
-  return result;
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_js_generator::function_signature(t_function* tfunction,
-                                          string prefix,
-                                          bool include_callback) {
-
-  string str;
-
-  str = prefix + tfunction->get_name() + " = function(";
-
-  str += argument_list(tfunction->get_arglist(), include_callback);
-
-  str += ")";
-  return str;
-}
-
-/**
- * Renders a field list
- */
-string t_js_generator::argument_list(t_struct* tstruct, bool include_callback) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    result += (*f_iter)->get_name();
-  }
-
-  if (include_callback) {
-    if (!fields.empty()) {
-      result += ", ";
-    }
-    result += "callback";
-  }
-
-  return result;
-}
-
-/**
- * Converts the parse type to a C++ enum string for the given type.
- */
-string t_js_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "Thrift.Type.STRING";
-    case t_base_type::TYPE_BOOL:
-      return "Thrift.Type.BOOL";
-    case t_base_type::TYPE_I8:
-      return "Thrift.Type.BYTE";
-    case t_base_type::TYPE_I16:
-      return "Thrift.Type.I16";
-    case t_base_type::TYPE_I32:
-      return "Thrift.Type.I32";
-    case t_base_type::TYPE_I64:
-      return "Thrift.Type.I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "Thrift.Type.DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "Thrift.Type.I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "Thrift.Type.STRUCT";
-  } else if (type->is_map()) {
-    return "Thrift.Type.MAP";
-  } else if (type->is_set()) {
-    return "Thrift.Type.SET";
-  } else if (type->is_list()) {
-    return "Thrift.Type.LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-/**
- * Converts a t_type to a TypeScript type (string).
- * @param t_type Type to convert to TypeScript
- * @return String TypeScript type
- */
-string t_js_generator::ts_get_type(t_type* type) {
-  std::string ts_type;
-
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      ts_type = "string";
-      break;
-    case t_base_type::TYPE_BOOL:
-      ts_type = "boolean";
-      break;
-    case t_base_type::TYPE_I8:
-      ts_type = "any";
-      break;
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-    case t_base_type::TYPE_DOUBLE:
-      ts_type = "number";
-      break;
-    case t_base_type::TYPE_VOID:
-      ts_type = "void";
-    }
-  } else if (type->is_enum() || type->is_struct() || type->is_xception()) {
-    std::string type_name;
-    if (type->get_program()) {
-      type_name = js_namespace(type->get_program());
-    }
-    type_name.append(type->get_name());
-    ts_type = type_name;
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-
-    ts_type = ts_get_type(etype) + "[]";
-  } else if (type->is_map()) {
-    string ktype = ts_get_type(((t_map*)type)->get_key_type());
-    string vtype = ts_get_type(((t_map*)type)->get_val_type());
-
-
-    if (ktype == "number" || ktype == "string" ) {
-      ts_type = "{ [k: " + ktype + "]: " + vtype + "; }";
-    } else if ((((t_map*)type)->get_key_type())->is_enum()) {
-      // Not yet supported (enum map): https://github.com/Microsoft/TypeScript/pull/2652
-      //ts_type = "{ [k: " + ktype + "]: " + vtype + "; }";
-      ts_type = "{ [k: number /*" + ktype + "*/]: " + vtype + "; }";
-    } else {
-      ts_type = "any";
-    }
-  }
-
-  return ts_type;
-}
-
-/**
- * Renders a TypeScript function signature of the form 'name(args: types): type;'
- *
- * @param t_function Function definition
- * @param bool in-/exclude the callback argument
- * @return String of rendered function definition
- */
-std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback) {
-  string str;
-  const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  str = tfunction->get_name() + "(";
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    str += (*f_iter)->get_name() + ts_get_req(*f_iter) + ": " + ts_get_type((*f_iter)->get_type());
-
-    if (f_iter + 1 != fields.end() || (include_callback && fields.size() > 0)) {
-      str += ", ";
-    }
-  }
-
-  if (include_callback) {
-    str += "callback: Function): ";
-
-    if (gen_jquery_) {
-      str += "JQueryXHR;";
-    } else {
-      str += "void;";
-    }
-  } else {
-    str += "): " + ts_get_type(tfunction->get_returntype()) + ";";
-  }
-
-  return str;
-}
-
-/**
- * Takes a name and produces a valid NodeJS identifier from it
- *
- * @param name The name which shall become a valid NodeJS identifier
- * @return The modified name with the updated identifier
- */
-std::string t_js_generator::make_valid_nodeJs_identifier(std::string const& name) {
-  std::string str = name;
-  if (str.empty()) {
-    return str;
-  }
-
-  // tests rely on this
-  assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
-
-  // if the first letter is a number, we add an additional underscore in front of it
-  char c = str.at(0);
-  if (('0' <= c) && (c <= '9')) {
-    str = "_" + str;
-  }
-
-  // following chars: letter, number or underscore
-  for (size_t i = 0; i < str.size(); ++i) {
-    c = str.at(i);
-    if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9'))
-        && ('_' != c) && ('$' != c)) {
-      str.replace(i, 1, "_");
-    }
-  }
-
-  return str;
-}
-
-THRIFT_REGISTER_GENERATOR(js,
-                          "Javascript",
-                          "    jquery:          Generate jQuery compatible code.\n"
-                          "    node:            Generate node.js compatible code.\n"
-                          "    ts:              Generate TypeScript definition files.\n")


[51/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Deploy headers needed to build plugins

Restructure source tree to match lib and to make sure headers are
deployed to INCLUDE_DIR/thrift.

This closes #368 and closes #1039


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/052abc39
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/052abc39
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/052abc39

Branch: refs/heads/master
Commit: 052abc39c60c54f9901993e76a81036b482ed6ba
Parents: 11da87e
Author: dtmuller <dt...@web.de>
Authored: Tue Jul 26 11:58:28 2016 +0200
Committer: Nobuaki Sukegawa <ns...@apache.org>
Committed: Mon Sep 26 01:42:02 2016 +0900

----------------------------------------------------------------------
 .gitignore                                      |   24 +-
 compiler/cpp/CMakeLists.txt                     |  121 +-
 compiler/cpp/Makefile.am                        |  210 +-
 compiler/cpp/src/Makefile.am                    |   96 +-
 compiler/cpp/src/audit/t_audit.cpp              |  466 --
 compiler/cpp/src/audit/t_audit.h                |   14 -
 compiler/cpp/src/common.cc                      |   69 -
 compiler/cpp/src/common.h                       |   43 -
 compiler/cpp/src/generate/t_as3_generator.cc    | 2594 ---------
 compiler/cpp/src/generate/t_c_glib_generator.cc | 4562 ---------------
 compiler/cpp/src/generate/t_cocoa_generator.cc  | 3301 -----------
 compiler/cpp/src/generate/t_cpp_generator.cc    | 4374 --------------
 compiler/cpp/src/generate/t_csharp_generator.cc | 3202 -----------
 compiler/cpp/src/generate/t_d_generator.cc      |  728 ---
 compiler/cpp/src/generate/t_dart_generator.cc   | 2516 ---------
 compiler/cpp/src/generate/t_delphi_generator.cc | 3920 -------------
 compiler/cpp/src/generate/t_erl_generator.cc    | 1169 ----
 compiler/cpp/src/generate/t_generator.cc        |  190 -
 compiler/cpp/src/generate/t_generator.h         |  310 -
 .../cpp/src/generate/t_generator_registry.h     |  106 -
 compiler/cpp/src/generate/t_go_generator.cc     | 3685 ------------
 compiler/cpp/src/generate/t_gv_generator.cc     |  345 --
 compiler/cpp/src/generate/t_haxe_generator.cc   | 2981 ----------
 compiler/cpp/src/generate/t_hs_generator.cc     | 1734 ------
 compiler/cpp/src/generate/t_html_generator.cc   | 1088 ----
 compiler/cpp/src/generate/t_html_generator.h    |  240 -
 compiler/cpp/src/generate/t_java_generator.cc   | 5323 ------------------
 compiler/cpp/src/generate/t_javame_generator.cc | 3295 -----------
 compiler/cpp/src/generate/t_js_generator.cc     | 2231 --------
 compiler/cpp/src/generate/t_json_generator.cc   |  727 ---
 compiler/cpp/src/generate/t_lua_generator.cc    | 1138 ----
 compiler/cpp/src/generate/t_ocaml_generator.cc  | 1762 ------
 compiler/cpp/src/generate/t_oop_generator.h     |  112 -
 compiler/cpp/src/generate/t_perl_generator.cc   | 1648 ------
 compiler/cpp/src/generate/t_php_generator.cc    | 2653 ---------
 compiler/cpp/src/generate/t_py_generator.cc     | 2625 ---------
 compiler/cpp/src/generate/t_rb_generator.cc     | 1263 -----
 compiler/cpp/src/generate/t_st_generator.cc     | 1055 ----
 compiler/cpp/src/generate/t_swift_generator.cc  | 2209 --------
 compiler/cpp/src/generate/t_xml_generator.cc    |  687 ---
 compiler/cpp/src/generate/t_xsd_generator.cc    |  376 --
 compiler/cpp/src/globals.h                      |  141 -
 compiler/cpp/src/logging.cc                     |   77 -
 compiler/cpp/src/logging.h                      |   47 -
 compiler/cpp/src/main.cc                        | 1307 -----
 compiler/cpp/src/main.h                         |  119 -
 compiler/cpp/src/parse/parse.cc                 |   39 -
 compiler/cpp/src/parse/t_base_type.h            |  117 -
 compiler/cpp/src/parse/t_const.h                |   50 -
 compiler/cpp/src/parse/t_const_value.h          |  155 -
 compiler/cpp/src/parse/t_container.h            |   47 -
 compiler/cpp/src/parse/t_doc.h                  |   55 -
 compiler/cpp/src/parse/t_enum.h                 |  110 -
 compiler/cpp/src/parse/t_enum_value.h           |   50 -
 compiler/cpp/src/parse/t_field.h                |  134 -
 compiler/cpp/src/parse/t_function.h             |   84 -
 compiler/cpp/src/parse/t_list.h                 |   41 -
 compiler/cpp/src/parse/t_map.h                  |   45 -
 compiler/cpp/src/parse/t_program.h              |  395 --
 compiler/cpp/src/parse/t_scope.h                |  181 -
 compiler/cpp/src/parse/t_service.h              |   61 -
 compiler/cpp/src/parse/t_set.h                  |   41 -
 compiler/cpp/src/parse/t_struct.h               |  171 -
 compiler/cpp/src/parse/t_type.h                 |  108 -
 compiler/cpp/src/parse/t_typedef.cc             |   34 -
 compiler/cpp/src/parse/t_typedef.h              |   67 -
 compiler/cpp/src/platform.h                     |   47 -
 compiler/cpp/src/plugin/Makefile.am             |   47 -
 compiler/cpp/src/plugin/plugin.cc               |  503 --
 compiler/cpp/src/plugin/plugin.h                |   44 -
 compiler/cpp/src/plugin/plugin.thrift           |  202 -
 compiler/cpp/src/plugin/plugin_output.cc        |  410 --
 compiler/cpp/src/plugin/plugin_output.h         |   38 -
 compiler/cpp/src/plugin/type_util.h             |   94 -
 compiler/cpp/src/thrift/audit/t_audit.cpp       |  464 ++
 compiler/cpp/src/thrift/audit/t_audit.h         |   14 +
 compiler/cpp/src/thrift/common.cc               |   69 +
 compiler/cpp/src/thrift/common.h                |   43 +
 .../cpp/src/thrift/generate/t_as3_generator.cc  | 2594 +++++++++
 .../src/thrift/generate/t_c_glib_generator.cc   | 4562 +++++++++++++++
 .../src/thrift/generate/t_cocoa_generator.cc    | 3301 +++++++++++
 .../cpp/src/thrift/generate/t_cpp_generator.cc  | 4374 ++++++++++++++
 .../src/thrift/generate/t_csharp_generator.cc   | 3202 +++++++++++
 .../cpp/src/thrift/generate/t_d_generator.cc    |  728 +++
 .../cpp/src/thrift/generate/t_dart_generator.cc | 2516 +++++++++
 .../src/thrift/generate/t_delphi_generator.cc   | 3920 +++++++++++++
 .../cpp/src/thrift/generate/t_erl_generator.cc  | 1169 ++++
 compiler/cpp/src/thrift/generate/t_generator.cc |  190 +
 compiler/cpp/src/thrift/generate/t_generator.h  |  310 +
 .../src/thrift/generate/t_generator_registry.h  |  106 +
 .../cpp/src/thrift/generate/t_go_generator.cc   | 3685 ++++++++++++
 .../cpp/src/thrift/generate/t_gv_generator.cc   |  345 ++
 .../cpp/src/thrift/generate/t_haxe_generator.cc | 2981 ++++++++++
 .../cpp/src/thrift/generate/t_hs_generator.cc   | 1734 ++++++
 .../cpp/src/thrift/generate/t_html_generator.cc | 1088 ++++
 .../cpp/src/thrift/generate/t_html_generator.h  |  240 +
 .../cpp/src/thrift/generate/t_java_generator.cc | 5323 ++++++++++++++++++
 .../src/thrift/generate/t_javame_generator.cc   | 3295 +++++++++++
 .../cpp/src/thrift/generate/t_js_generator.cc   | 2231 ++++++++
 .../cpp/src/thrift/generate/t_json_generator.cc |  727 +++
 .../cpp/src/thrift/generate/t_lua_generator.cc  | 1138 ++++
 .../src/thrift/generate/t_ocaml_generator.cc    | 1762 ++++++
 .../cpp/src/thrift/generate/t_oop_generator.h   |  112 +
 .../cpp/src/thrift/generate/t_perl_generator.cc | 1648 ++++++
 .../cpp/src/thrift/generate/t_php_generator.cc  | 2653 +++++++++
 .../cpp/src/thrift/generate/t_py_generator.cc   | 2625 +++++++++
 .../cpp/src/thrift/generate/t_rb_generator.cc   | 1263 +++++
 .../cpp/src/thrift/generate/t_st_generator.cc   | 1055 ++++
 .../src/thrift/generate/t_swift_generator.cc    | 2209 ++++++++
 .../cpp/src/thrift/generate/t_xml_generator.cc  |  687 +++
 .../cpp/src/thrift/generate/t_xsd_generator.cc  |  376 ++
 compiler/cpp/src/thrift/globals.h               |  141 +
 compiler/cpp/src/thrift/logging.cc              |   77 +
 compiler/cpp/src/thrift/logging.h               |   47 +
 compiler/cpp/src/thrift/main.cc                 | 1307 +++++
 compiler/cpp/src/thrift/main.h                  |  119 +
 compiler/cpp/src/thrift/parse/parse.cc          |   39 +
 compiler/cpp/src/thrift/parse/t_base_type.h     |  117 +
 compiler/cpp/src/thrift/parse/t_const.h         |   50 +
 compiler/cpp/src/thrift/parse/t_const_value.h   |  155 +
 compiler/cpp/src/thrift/parse/t_container.h     |   47 +
 compiler/cpp/src/thrift/parse/t_doc.h           |   55 +
 compiler/cpp/src/thrift/parse/t_enum.h          |  110 +
 compiler/cpp/src/thrift/parse/t_enum_value.h    |   50 +
 compiler/cpp/src/thrift/parse/t_field.h         |  134 +
 compiler/cpp/src/thrift/parse/t_function.h      |   84 +
 compiler/cpp/src/thrift/parse/t_list.h          |   41 +
 compiler/cpp/src/thrift/parse/t_map.h           |   45 +
 compiler/cpp/src/thrift/parse/t_program.h       |  395 ++
 compiler/cpp/src/thrift/parse/t_scope.h         |  181 +
 compiler/cpp/src/thrift/parse/t_service.h       |   61 +
 compiler/cpp/src/thrift/parse/t_set.h           |   41 +
 compiler/cpp/src/thrift/parse/t_struct.h        |  171 +
 compiler/cpp/src/thrift/parse/t_type.h          |  108 +
 compiler/cpp/src/thrift/parse/t_typedef.cc      |   34 +
 compiler/cpp/src/thrift/parse/t_typedef.h       |   67 +
 compiler/cpp/src/thrift/platform.h              |   47 +
 compiler/cpp/src/thrift/plugin/Makefile.am      |   47 +
 compiler/cpp/src/thrift/plugin/plugin.cc        |  503 ++
 compiler/cpp/src/thrift/plugin/plugin.h         |   44 +
 compiler/cpp/src/thrift/plugin/plugin.thrift    |  202 +
 compiler/cpp/src/thrift/plugin/plugin_output.cc |  410 ++
 compiler/cpp/src/thrift/plugin/plugin_output.h  |   38 +
 compiler/cpp/src/thrift/plugin/type_util.h      |   94 +
 compiler/cpp/src/thrift/thriftl.ll              |  463 ++
 compiler/cpp/src/thrift/thrifty.yy              | 1193 ++++
 compiler/cpp/src/thrift/version.h.in            |    1 +
 compiler/cpp/src/thrift/windows/config.h        |   45 +
 compiler/cpp/src/thrift/windows/version.h.in    |   33 +
 compiler/cpp/src/thriftl.ll                     |  463 --
 compiler/cpp/src/thrifty.yy                     | 1193 ----
 compiler/cpp/src/version.h.in                   |    1 -
 compiler/cpp/src/windows/config.h               |   45 -
 compiler/cpp/src/windows/version.h.in           |   33 -
 compiler/cpp/test/CMakeLists.txt                |    2 +-
 compiler/cpp/test/plugin/conversion_test.cc     |    6 +-
 compiler/cpp/test/plugin/cpp_plugin.cc          |    4 +-
 configure.ac                                    |    8 +-
 158 files changed, 71822 insertions(+), 71721 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 94e8519..9a0e275 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,28 +48,28 @@ erl_crash.dump
 /autoscan.log
 /autoscan-*.log
 /compiler/cpp/test/plugin/t_cpp_generator.cc
-/compiler/cpp/src/plugin/plugin_constants.cpp
-/compiler/cpp/src/plugin/plugin_constants.h
-/compiler/cpp/src/plugin/plugin_types.cpp
-/compiler/cpp/src/plugin/plugin_types.h
+/compiler/cpp/src/thrift/plugin/plugin_constants.cpp
+/compiler/cpp/src/thrift/plugin/plugin_constants.h
+/compiler/cpp/src/thrift/plugin/plugin_types.cpp
+/compiler/cpp/src/thrift/plugin/plugin_types.h
 /compiler/cpp/test/*test
 /compiler/cpp/test/thrift-gen-*
-/compiler/cpp/src/thrift-bootstrap
-/compiler/cpp/src/plugin/gen.stamp
+/compiler/cpp/src/thrift/thrift-bootstrap
+/compiler/cpp/src/thrift/plugin/gen.stamp
 /compiler/cpp/Debug
 /compiler/cpp/Release
-/compiler/cpp/src/libparse.a
-/compiler/cpp/src/thriftl.cc
-/compiler/cpp/src/thrifty.cc
-/compiler/cpp/src/thrifty.hh
-/compiler/cpp/src/windows/version.h
+/compiler/cpp/src/thrift/libparse.a
+/compiler/cpp/src/thrift/thriftl.cc
+/compiler/cpp/src/thrift/thrifty.cc
+/compiler/cpp/src/thrift/thrifty.hh
+/compiler/cpp/src/thrift/windows/version.h
 /compiler/cpp/thrift
 /compiler/cpp/thriftl.cc
 /compiler/cpp/thrifty.cc
 /compiler/cpp/lex.yythriftl.cc
 /compiler/cpp/thrifty.h
 /compiler/cpp/thrifty.hh
-/compiler/cpp/src/version.h
+/compiler/cpp/src/thrift/version.h
 /config.*
 /configure
 /configure.lineno

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt
index 48cadbc..2d9529a 100644
--- a/compiler/cpp/CMakeLists.txt
+++ b/compiler/cpp/CMakeLists.txt
@@ -19,52 +19,52 @@
 
 # Windows has a different header
 if(MSVC)
-    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/windows/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/windows/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h)
 else()
-    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h)
 endif()
 
 find_package(FLEX REQUIRED)
 find_package(BISON REQUIRED)
 
 # Create flex and bison files and build the lib parse static library
-BISON_TARGET(thrifty ${CMAKE_CURRENT_SOURCE_DIR}/src/thrifty.yy ${CMAKE_CURRENT_BINARY_DIR}/thrifty.cc)
-FLEX_TARGET(thriftl ${CMAKE_CURRENT_SOURCE_DIR}/src/thriftl.ll ${CMAKE_CURRENT_BINARY_DIR}/thriftl.cc)
+BISON_TARGET(thrifty ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/thrifty.yy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc)
+FLEX_TARGET(thriftl ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/thriftl.ll ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc)
 ADD_FLEX_BISON_DEPENDENCY(thriftl thrifty)
 
 # HACK: Work around the fact that bison crates a .hh file but we need a .h file
-add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/thrifty.h
-                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/thrifty.hh ${CMAKE_CURRENT_BINARY_DIR}/thrifty.h
-                   DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/thrifty.hh
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.h
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.h
+                   DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh
                    )
 
 set(libparse_SOURCES
-    ${CMAKE_CURRENT_BINARY_DIR}/thrifty.cc
-    ${CMAKE_CURRENT_BINARY_DIR}/thriftl.cc
-    ${CMAKE_CURRENT_BINARY_DIR}/thrifty.h
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.h
 )
 
 add_library(libparse STATIC ${libparse_SOURCES})
 
 # Create the thrift compiler
 set(compiler_core
-    src/common.cc
-    src/generate/t_generator.cc
-    src/parse/t_typedef.cc
-    src/parse/parse.cc
-    ${CMAKE_CURRENT_BINARY_DIR}/version.h
+    src/thrift/common.cc
+    src/thrift/generate/t_generator.cc
+    src/thrift/parse/t_typedef.cc
+    src/thrift/parse/parse.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h
 )
 
 set(thrift-compiler_SOURCES
-    src/main.cc
-    src/audit/t_audit.cpp
+    src/thrift/main.cc
+    src/thrift/audit/t_audit.cpp
 )
 
 # This macro adds an option THRIFT_COMPILER_${NAME}
 # that allows enabling or disabling certain languages
 macro(THRIFT_ADD_COMPILER name description initial)
     string(TOUPPER "THRIFT_COMPILER_${name}" enabler)
-    set(src "src/generate/t_${name}_generator.cc")
+    set(src "src/thrift/generate/t_${name}_generator.cc")
     option(${enabler} ${description} ${initial})
     if(${enabler})
         list(APPEND thrift-compiler_SOURCES ${src})
@@ -112,25 +112,25 @@ add_executable(thrift-compiler ${thrift-compiler_SOURCES})
 
 if(${WITH_PLUGIN})
     add_executable(thrift-bootstrap ${compiler_core}
-        src/main.cc
-        src/audit/t_audit.cpp
-        src/generate/t_cpp_generator.cc
+        src/thrift/main.cc
+        src/thrift/audit/t_audit.cpp
+        src/thrift/generate/t_cpp_generator.cc
     )
     target_link_libraries(thrift-bootstrap libparse)
 
     set(PLUGIN_GEN_SOURCES
-        ${CMAKE_CURRENT_BINARY_DIR}/plugin/plugin_types.h
-        ${CMAKE_CURRENT_BINARY_DIR}/plugin/plugin_types.cpp
-        ${CMAKE_CURRENT_BINARY_DIR}/plugin/plugin_constants.h
-        ${CMAKE_CURRENT_BINARY_DIR}/plugin/plugin_constants.cpp
+        ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_types.h
+        ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_types.cpp
+        ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_constants.h
+        ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_constants.cpp
     )
 
-    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/plugin)
+    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin)
     add_custom_command(OUTPUT ${PLUGIN_GEN_SOURCES}
-        DEPENDS thrift-bootstrap src/plugin/plugin.thrift
+        DEPENDS thrift-bootstrap src/thrift/plugin/plugin.thrift
         COMMAND thrift-bootstrap -gen cpp
-        -out ${CMAKE_CURRENT_BINARY_DIR}/plugin
-        ${CMAKE_CURRENT_SOURCE_DIR}/src/plugin/plugin.thrift
+        -out ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/plugin/plugin.thrift
     )
 
     include_directories(../../lib/cpp/src)
@@ -139,9 +139,9 @@ if(${WITH_PLUGIN})
     ADD_LIBRARY_THRIFT(thriftc
         ${compiler_core}
         ${PLUGIN_GEN_SOURCES}
-        src/logging.cc
-        src/plugin/plugin_output.cc
-        src/plugin/plugin.cc
+        src/thrift/logging.cc
+        src/thrift/plugin/plugin_output.cc
+        src/thrift/plugin/plugin.cc
     )
     TARGET_INCLUDE_DIRECTORIES_THRIFT(thriftc PUBLIC ${Boost_INCLUDE_DIRS})
     TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftc thrift PUBLIC)
@@ -155,6 +155,63 @@ target_link_libraries(thrift-compiler libparse)
 
 install(TARGETS thrift-compiler DESTINATION "${BIN_INSTALL_DIR}")
 
+if(${WITH_PLUGIN})
+  # Install the headers
+  install(FILES
+      "src/thrift/common.h"
+      "src/thrift/globals.h"
+      "src/thrift/logging.h"
+      "src/thrift/main.h"
+      "src/thrift/platform.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift")
+  install(FILES
+      "src/thrift/audit/t_audit.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/audit")
+  install(FILES
+      "src/thrift/generate/t_generator.h"
+      "src/thrift/generate/t_generator_registry.h"
+      "src/thrift/generate/t_html_generator.h"
+      "src/thrift/generate/t_oop_generator.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/generate")
+  install(FILES
+      "src/thrift/parse/t_base_type.h"
+      "src/thrift/parse/t_const.h"
+      "src/thrift/parse/t_const_value.h"
+      "src/thrift/parse/t_container.h"
+      "src/thrift/parse/t_doc.h"
+      "src/thrift/parse/t_enum.h"
+      "src/thrift/parse/t_enum_value.h"
+      "src/thrift/parse/t_field.h"
+      "src/thrift/parse/t_function.h"
+      "src/thrift/parse/t_list.h"
+      "src/thrift/parse/t_map.h"
+      "src/thrift/parse/t_program.h"
+      "src/thrift/parse/t_scope.h"
+      "src/thrift/parse/t_service.h"
+      "src/thrift/parse/t_set.h"
+      "src/thrift/parse/t_struct.h"
+      "src/thrift/parse/t_typedef.h"
+      "src/thrift/parse/t_type.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/parse")
+  install(FILES
+      "src/thrift/plugin/plugin.h"
+      "src/thrift/plugin/plugin_output.h"
+      "src/thrift/plugin/type_util.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/plugin")
+if(MSVC)
+  install(FILES
+      "src/thrift/windows/config.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/windows")
+  install(FILES
+      "${CMAKE_BINARY_DIR}/compiler/cpp/thrift/windows/version.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/windows")
+else()
+  install(FILES
+      "${CMAKE_BINARY_DIR}/compiler/cpp/thrift/version.h"
+      DESTINATION "${INCLUDE_INSTALL_DIR}/thrift")
+endif()
+endif()
+
 if(BUILD_TESTING)
     add_subdirectory(test)
 endif()

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/Makefile.am
----------------------------------------------------------------------
diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am
index f7a7171..9d830d7 100644
--- a/compiler/cpp/Makefile.am
+++ b/compiler/cpp/Makefile.am
@@ -23,12 +23,12 @@
 
 AUTOMAKE_OPTIONS = subdir-objects
 
-# Note on why we have src and src/plugin directories:
+# Note on why we have src/thrift and src/thrift/plugin directories:
 # Since Automake supports only one set of BUILT_SOURCES per file and does not allow
 # SUBDIRS built before BUILT_SOURCES, we end up separate Makefile.am for each source
 # code generation, i.e. lex-yacc and Thrift, to achieve stable parallel make.
 
-SUBDIRS = src src/plugin .
+SUBDIRS = src src/thrift/plugin .
 if WITH_TESTS
 SUBDIRS += test
 endif
@@ -37,82 +37,82 @@ bin_PROGRAMS = thrift
 
 thrift_OBJDIR = obj
 
-plugin_gen = src/plugin/plugin_types.h \
-             src/plugin/plugin_types.cpp \
-             src/plugin/plugin_constants.h \
-             src/plugin/plugin_constants.cpp
-
-compiler_core =  src/common.h \
-                 src/common.cc \
-                 src/generate/t_generator.cc \
-                 src/generate/t_generator_registry.h \
-                 src/globals.h \
-                 src/platform.h \
-                 src/logging.h \
-                 src/parse/t_doc.h \
-                 src/parse/t_type.h \
-                 src/parse/t_base_type.h \
-                 src/parse/t_enum.h \
-                 src/parse/t_enum_value.h \
-                 src/parse/t_typedef.h \
-                 src/parse/t_typedef.cc \
-                 src/parse/t_container.h \
-                 src/parse/t_list.h \
-                 src/parse/t_set.h \
-                 src/parse/t_map.h \
-                 src/parse/t_struct.h \
-                 src/parse/t_field.h \
-                 src/parse/t_service.h \
-                 src/parse/t_function.h \
-                 src/parse/t_program.h \
-                 src/parse/t_scope.h \
-                 src/parse/t_const.h \
-                 src/parse/t_const_value.h \
-                 src/parse/parse.cc \
-                 src/generate/t_generator.h \
-                 src/generate/t_oop_generator.h \
-                 src/generate/t_html_generator.h \
-                 src/windows/config.h \
-                 src/windows/version.h
-
-thrift_SOURCES = src/main.h \
-                 src/main.cc \
-                 src/audit/t_audit.cpp \
-                 src/audit/t_audit.h
+plugin_gen = src/thrift/plugin/plugin_types.h \
+             src/thrift/plugin/plugin_types.cpp \
+             src/thrift/plugin/plugin_constants.h \
+             src/thrift/plugin/plugin_constants.cpp
+
+compiler_core =  src/thrift/common.h \
+                 src/thrift/common.cc \
+                 src/thrift/generate/t_generator.cc \
+                 src/thrift/generate/t_generator_registry.h \
+                 src/thrift/globals.h \
+                 src/thrift/platform.h \
+                 src/thrift/logging.h \
+                 src/thrift/parse/t_doc.h \
+                 src/thrift/parse/t_type.h \
+                 src/thrift/parse/t_base_type.h \
+                 src/thrift/parse/t_enum.h \
+                 src/thrift/parse/t_enum_value.h \
+                 src/thrift/parse/t_typedef.h \
+                 src/thrift/parse/t_typedef.cc \
+                 src/thrift/parse/t_container.h \
+                 src/thrift/parse/t_list.h \
+                 src/thrift/parse/t_set.h \
+                 src/thrift/parse/t_map.h \
+                 src/thrift/parse/t_struct.h \
+                 src/thrift/parse/t_field.h \
+                 src/thrift/parse/t_service.h \
+                 src/thrift/parse/t_function.h \
+                 src/thrift/parse/t_program.h \
+                 src/thrift/parse/t_scope.h \
+                 src/thrift/parse/t_const.h \
+                 src/thrift/parse/t_const_value.h \
+                 src/thrift/parse/parse.cc \
+                 src/thrift/generate/t_generator.h \
+                 src/thrift/generate/t_oop_generator.h \
+                 src/thrift/generate/t_html_generator.h \
+                 src/thrift/windows/config.h \
+                 src/thrift/windows/version.h
+
+thrift_SOURCES = src/thrift/main.h \
+                 src/thrift/main.cc \
+                 src/thrift/audit/t_audit.cpp \
+                 src/thrift/audit/t_audit.h
 
 # Specific client generator source
-thrift_SOURCES += src/generate/t_c_glib_generator.cc \
-                  src/generate/t_cpp_generator.cc \
-                  src/generate/t_java_generator.cc \
-                  src/generate/t_json_generator.cc \
-                  src/generate/t_as3_generator.cc \
-                  src/generate/t_dart_generator.cc \
-                  src/generate/t_haxe_generator.cc \
-                  src/generate/t_csharp_generator.cc \
-                  src/generate/t_py_generator.cc \
-                  src/generate/t_rb_generator.cc \
-                  src/generate/t_perl_generator.cc \
-                  src/generate/t_php_generator.cc \
-                  src/generate/t_erl_generator.cc \
-                  src/generate/t_cocoa_generator.cc \
-                  src/generate/t_swift_generator.cc \
-                  src/generate/t_st_generator.cc \
-                  src/generate/t_ocaml_generator.cc \
-                  src/generate/t_hs_generator.cc \
-                  src/generate/t_xsd_generator.cc \
-                  src/generate/t_xml_generator.cc \
-                  src/generate/t_html_generator.cc \
-                  src/generate/t_js_generator.cc \
-                  src/generate/t_javame_generator.cc \
-                  src/generate/t_delphi_generator.cc \
-                  src/generate/t_go_generator.cc \
-                  src/generate/t_gv_generator.cc \
-                  src/generate/t_d_generator.cc \
-                  src/generate/t_lua_generator.cc
+thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \
+                  src/thrift/generate/t_cpp_generator.cc \
+                  src/thrift/generate/t_java_generator.cc \
+                  src/thrift/generate/t_json_generator.cc \
+                  src/thrift/generate/t_as3_generator.cc \
+                  src/thrift/generate/t_dart_generator.cc \
+                  src/thrift/generate/t_haxe_generator.cc \
+                  src/thrift/generate/t_csharp_generator.cc \
+                  src/thrift/generate/t_py_generator.cc \
+                  src/thrift/generate/t_rb_generator.cc \
+                  src/thrift/generate/t_perl_generator.cc \
+                  src/thrift/generate/t_php_generator.cc \
+                  src/thrift/generate/t_erl_generator.cc \
+                  src/thrift/generate/t_cocoa_generator.cc \
+                  src/thrift/generate/t_swift_generator.cc \
+                  src/thrift/generate/t_st_generator.cc \
+                  src/thrift/generate/t_ocaml_generator.cc \
+                  src/thrift/generate/t_hs_generator.cc \
+                  src/thrift/generate/t_xsd_generator.cc \
+                  src/thrift/generate/t_xml_generator.cc \
+                  src/thrift/generate/t_html_generator.cc \
+                  src/thrift/generate/t_js_generator.cc \
+                  src/thrift/generate/t_javame_generator.cc \
+                  src/thrift/generate/t_delphi_generator.cc \
+                  src/thrift/generate/t_go_generator.cc \
+                  src/thrift/generate/t_gv_generator.cc \
+                  src/thrift/generate/t_d_generator.cc \
+                  src/thrift/generate/t_lua_generator.cc
 
 thrift_CPPFLAGS = -I$(srcdir)/src
 thrift_CXXFLAGS = -Wall -Wextra -pedantic
-thrift_LDADD = @LEXLIB@ src/libparse.a
+thrift_LDADD = @LEXLIB@ src/thrift/libparse.a
 
 if !WITH_PLUGIN
 thrift_SOURCES += $(compiler_core)
@@ -125,18 +125,64 @@ thrift_LDADD += libthriftc.la
 
 nodist_libthriftc_la_SOURCES = $(plugin_gen)
 libthriftc_la_SOURCES = $(compiler_core) \
-                        src/plugin/type_util.h \
-                        src/plugin/plugin.h \
-                        src/plugin/plugin.cc \
-                        src/plugin/plugin_output.h \
-                        src/plugin/plugin_output.cc \
-                        src/plugin/plugin.thrift \
-                        src/logging.cc
+                        src/thrift/plugin/type_util.h \
+                        src/thrift/plugin/plugin.h \
+                        src/thrift/plugin/plugin.cc \
+                        src/thrift/plugin/plugin_output.h \
+                        src/thrift/plugin/plugin_output.cc \
+                        src/thrift/plugin/plugin.thrift \
+                        src/thrift/logging.cc
 
 
 libthriftc_la_CPPFLAGS = -I$(srcdir)/src -Isrc -I$(top_builddir)/lib/cpp/src -DTHRIFT_ENABLE_PLUGIN=1
 libthriftc_la_CXXFLAGS = -Wall -Wextra -pedantic
 libthriftc_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
+
+include_thriftdir = $(includedir)/thrift
+include_thrift_HEADERS = src/thrift/common.h \
+                         src/thrift/globals.h \
+                         src/thrift/logging.h \
+                         src/thrift/main.h \
+                         src/thrift/platform.h \
+                         src/thrift/version.h
+
+include_auditdir = $(include_thriftdir)/windows
+include_audit_HEADERS = src/thrift/audit/t_audit.h
+
+include_generatedir = $(include_thriftdir)/generate
+include_generate_HEADERS = src/thrift/generate/t_generator.h \
+                           src/thrift/generate/t_generator_registry.h \
+                           src/thrift/generate/t_oop_generator.h \
+                           src/thrift/generate/t_html_generator.h
+
+include_parsedir = $(include_thriftdir)/parse
+include_parse_HEADERS = src/thrift/parse/t_service.h \
+                        src/thrift/parse/t_program.h \
+                        src/thrift/parse/t_field.h \
+                        src/thrift/parse/t_scope.h \
+                        src/thrift/parse/t_typedef.h \
+                        src/thrift/parse/t_set.h \
+                        src/thrift/parse/t_const_value.h \
+                        src/thrift/parse/t_enum_value.h \
+                        src/thrift/parse/t_const.h \
+                        src/thrift/parse/t_list.h \
+                        src/thrift/parse/t_map.h \
+                        src/thrift/parse/t_container.h \
+                        src/thrift/parse/t_base_type.h \
+                        src/thrift/parse/t_enum.h \
+                        src/thrift/parse/t_function.h \
+                        src/thrift/parse/t_type.h \
+                        src/thrift/parse/t_doc.h \
+                        src/thrift/parse/t_struct.h
+
+include_plugindir = $(include_thriftdir)/plugin
+include_plugin_HEADERS = src/thrift/plugin/plugin.h \
+                         src/thrift/plugin/type_util.h \
+                         src/thrift/plugin/plugin_output.h
+
+include_windowsdir = $(include_thriftdir)/windows
+include_windows_HEADERS = src/thrift/windows/version.h \
+                          src/thrift/windows/config.h
 endif
 
 WINDOWS_DIST = \
@@ -153,7 +199,7 @@ EXTRA_DIST = \
 clean-local:
 	$(RM) version.h windows/version.h $(plugin_gen)
 
-src/main.cc: src/version.h
+src/thrift/main.cc: src/thrift/version.h
 
 style-local:
-	$(CPPSTYLE_CMD)
+  $(CPPSTYLE_CMD)

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/Makefile.am
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/Makefile.am b/compiler/cpp/src/Makefile.am
index e2fae70..f1863d5 100644
--- a/compiler/cpp/src/Makefile.am
+++ b/compiler/cpp/src/Makefile.am
@@ -25,63 +25,63 @@ AUTOMAKE_OPTIONS = subdir-objects
 
 AM_YFLAGS = -d
 
-BUILT_SOURCES = thrifty.cc
+BUILT_SOURCES = thrift/thrifty.cc
 
-noinst_LIBRARIES = libparse.a
+noinst_LIBRARIES = thrift/libparse.a
 
-libparse_a_CPPFLAGS = -I$(srcdir)
-libparse_a_CXXFLAGS = -Wall -Wno-sign-compare -Wno-unused
+thrift_libparse_a_CPPFLAGS = -I$(srcdir)
+thrift_libparse_a_CXXFLAGS = -Wall -Wno-sign-compare -Wno-unused
 
-libparse_a_SOURCES = thrifty.yy \
-                     thriftl.ll
+thrift_libparse_a_SOURCES = thrift/thrifty.yy \
+                     thrift/thriftl.ll
 
 clean-local:
-	$(RM) thriftl.cc thrifty.cc thrifty.h thrifty.hh
+	$(RM) thrift/thriftl.cc thrift/thrifty.cc thrift/thrifty.h thrift/thrifty.hh
 
 if WITH_PLUGIN
-noinst_PROGRAMS = thrift-bootstrap
+noinst_PROGRAMS = thrift/thrift-bootstrap
 
-thrift_bootstrap_SOURCES = \
-                 common.h \
-                 common.cc \
-                 audit/t_audit.h \
-                 audit/t_audit.cpp \
-                 generate/t_generator.cc \
-                 generate/t_generator_registry.h \
-                 globals.h \
-                 platform.h \
-                 logging.h \
-                 parse/t_doc.h \
-                 parse/t_type.h \
-                 parse/t_base_type.h \
-                 parse/t_enum.h \
-                 parse/t_enum_value.h \
-                 parse/t_typedef.h \
-                 parse/t_typedef.cc \
-                 parse/t_container.h \
-                 parse/t_list.h \
-                 parse/t_set.h \
-                 parse/t_map.h \
-                 parse/t_struct.h \
-                 parse/t_field.h \
-                 parse/t_service.h \
-                 parse/t_function.h \
-                 parse/t_program.h \
-                 parse/t_scope.h \
-                 parse/t_const.h \
-                 parse/t_const_value.h \
-                 parse/parse.cc \
-                 generate/t_generator.h \
-                 generate/t_oop_generator.h \
-                 generate/t_html_generator.h \
-                 windows/config.h \
-                 windows/version.h \
-                 generate/t_cpp_generator.cc \
-                 main.h \
-                 main.cc
+thrift_thrift_bootstrap_SOURCES = \
+                 thrift/common.h \
+                 thrift/common.cc \
+                 thrift/audit/t_audit.h \
+                 thrift/audit/t_audit.cpp \
+                 thrift/generate/t_generator.cc \
+                 thrift/generate/t_generator_registry.h \
+                 thrift/globals.h \
+                 thrift/platform.h \
+                 thrift/logging.h \
+                 thrift/parse/t_doc.h \
+                 thrift/parse/t_type.h \
+                 thrift/parse/t_base_type.h \
+                 thrift/parse/t_enum.h \
+                 thrift/parse/t_enum_value.h \
+                 thrift/parse/t_typedef.h \
+                 thrift/parse/t_typedef.cc \
+                 thrift/parse/t_container.h \
+                 thrift/parse/t_list.h \
+                 thrift/parse/t_set.h \
+                 thrift/parse/t_map.h \
+                 thrift/parse/t_struct.h \
+                 thrift/parse/t_field.h \
+                 thrift/parse/t_service.h \
+                 thrift/parse/t_function.h \
+                 thrift/parse/t_program.h \
+                 thrift/parse/t_scope.h \
+                 thrift/parse/t_const.h \
+                 thrift/parse/t_const_value.h \
+                 thrift/parse/parse.cc \
+                 thrift/generate/t_generator.h \
+                 thrift/generate/t_oop_generator.h \
+                 thrift/generate/t_html_generator.h \
+                 thrift/windows/config.h \
+                 thrift/windows/version.h \
+                 thrift/generate/t_cpp_generator.cc \
+                 thrift/main.h \
+                 thrift/main.cc
 
 main.cc: version.h
 
-thrift_bootstrap_CXXFLAGS = -Wall -Wextra -pedantic
-thrift_bootstrap_LDADD = @LEXLIB@ libparse.a
+thrift_thrift_bootstrap_CXXFLAGS = -Wall -Wextra -pedantic
+thrift_thrift_bootstrap_LDADD = @LEXLIB@ thrift/libparse.a
 endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/audit/t_audit.cpp
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/audit/t_audit.cpp b/compiler/cpp/src/audit/t_audit.cpp
deleted file mode 100644
index afcbd5e..0000000
--- a/compiler/cpp/src/audit/t_audit.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-
-#include <cassert>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-#include <string>
-#include <algorithm>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <limits.h>
-
-// Careful: must include globals first for extern definitions
-#include "globals.h"
-
-#include "parse/t_program.h"
-#include "parse/t_scope.h"
-#include "parse/t_const.h"
-#include "parse/t_field.h"
-
-#include "version.h"
-
-#include "t_audit.h"
-
-extern int g_warn;
-extern std::string g_curpath;
-extern bool g_return_failure;
-
-void thrift_audit_warning(int level, const char* fmt, ...) {
-   if (g_warn < level) {
-      return;
-   }
-   va_list args;
-   printf("[Thrift Audit Warning:%s] ", g_curpath.c_str());
-   va_start(args, fmt);
-   vprintf(fmt, args);
-   va_end(args);
-   printf("\n");
-}
-
-void thrift_audit_failure(const char* fmt, ...) {
-  va_list args;
-  fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str());
-  va_start(args, fmt);
-  vfprintf(stderr, fmt, args);
-  va_end(args);
-  fprintf(stderr, "\n");
-  g_return_failure = true;
-}
-
-void compare_namespace(t_program* newProgram, t_program* oldProgram)
-{
-   const std::map<std::string, std::string>& newNamespaceMap = newProgram->get_all_namespaces();
-   const std::map<std::string, std::string>& oldNamespaceMap = oldProgram->get_all_namespaces();
-
-   for(std::map<std::string, std::string>::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin();
-         oldNamespaceMapIt != oldNamespaceMap.end();
-         oldNamespaceMapIt++)
-   {
-      std::map<std::string, std::string>::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first);
-      if(newNamespaceMapIt == newNamespaceMap.end())
-      {
-         thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str());
-      }
-      else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second)
-      {
-         thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str());
-      }
-   }
-}
-
-void compare_enum_values(t_enum* newEnum,t_enum* oldEnum)
-{
-   const std::vector<t_enum_value*>& oldEnumValues = oldEnum->get_constants();
-   for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt = oldEnumValues.begin();
-         oldEnumValuesIt != oldEnumValues.end();
-         oldEnumValuesIt++)
-   {
-      int enumValue = (*oldEnumValuesIt)->get_value();
-      t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue);
-      if(newEnumValue != NULL)
-      {
-         std::string enumName = (*oldEnumValuesIt)->get_name();
-         if(enumName != newEnumValue->get_name())
-         {
-            thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str());
-         }      
-      }
-      else
-      {
-         thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str());
-      }
-
-   }
-}
-
-void compare_enums(const std::vector<t_enum*>& newEnumList, const std::vector<t_enum*>& oldEnumList)
-{
-   std::map<std::string,t_enum*> newEnumMap;
-   std::vector<t_enum*>::const_iterator newEnumIt;
-   for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++)
-   {
-      newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt;
-   }
-   std::vector<t_enum*>::const_iterator oldEnumIt;
-   for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++)
-   {
-      std::map<std::string,t_enum*>::iterator newEnumMapIt;
-      newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name());
-
-      if(newEnumMapIt == newEnumMap.end())
-      {
-         thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str());
-      }
-      else
-      {
-         compare_enum_values(newEnumMapIt->second, *oldEnumIt);
-      }
-   }
-}
-
-//This function returns 'true' if the two arguements are of same types.
-//Returns false if they are of different type
-bool compare_type(t_type* newType, t_type* oldType)
-{
-   //Comparing names of two types will work when the newType and oldType are basic types or structs or enums.
-   //However, when they are containers, get_name() returns empty for which we have to compare the type of 
-   //their elements as well.
-   if((newType->get_name()).empty() && (oldType->get_name()).empty())
-   {
-
-      if(newType->is_list() && oldType->is_list())
-      {
-         t_type* newElementType = ((t_list*)newType)->get_elem_type();
-         t_type* oldElementType = ((t_list*)oldType)->get_elem_type();
-         return compare_type(newElementType, oldElementType);
-      }
-      else if(newType->is_map() && oldType->is_map())
-      {
-         t_type* newKeyType = ((t_map*)newType)->get_key_type();
-         t_type* oldKeyType = ((t_map*)oldType)->get_key_type();
-
-         t_type* newValType = ((t_map*)newType)->get_val_type();
-         t_type* oldValType = ((t_map*)oldType)->get_val_type();
-
-         return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType));
-      }
-      else if(newType->is_set() && oldType->is_set())
-      {
-         t_type* newElementType = ((t_set*)newType)->get_elem_type();
-         t_type* oldElementType = ((t_set*)oldType)->get_elem_type();
-         return compare_type(newElementType, oldElementType); 
-      }
-      else
-      {
-         return false;
-      }
-   }
-   else if(newType->get_name() == oldType->get_name())
-   {
-      return true;
-   }
-   else
-   {
-      return false;
-   }
-}
-
-bool compare_pair(std::pair<t_const_value*, t_const_value*> newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair)
-{
-   return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second);
-}   
-
-// This function returns 'true' if the default values are same. Returns false if they are different.
-bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault)
-{
-   if(newStructDefault == NULL && oldStructDefault == NULL) return true;
-   else if(newStructDefault == NULL && oldStructDefault != NULL) return false;
-   else if (newStructDefault != NULL && oldStructDefault == NULL) return false;
-
-   if(newStructDefault->get_type() != oldStructDefault->get_type())
-   {
-      return false;
-   }
-
-   switch(newStructDefault->get_type())
-   {
-      case t_const_value::CV_INTEGER:
-         return (newStructDefault->get_integer() == oldStructDefault->get_integer());
-      case t_const_value::CV_DOUBLE:
-         return (newStructDefault->get_double() == oldStructDefault->get_double());
-      case t_const_value::CV_STRING:
-         return (newStructDefault->get_string() == oldStructDefault->get_string());
-      case t_const_value::CV_LIST:
-         {
-            const std::vector<t_const_value*>& oldDefaultList = oldStructDefault->get_list();
-            const std::vector<t_const_value*>& newDefaultList = newStructDefault->get_list();
-            bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size());
-
-            return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults);
-         }
-      case t_const_value::CV_MAP:
-         {
-            const std::map<t_const_value*, t_const_value*> newMap = newStructDefault->get_map();
-            const std::map<t_const_value*, t_const_value*> oldMap = oldStructDefault->get_map();
-
-            bool defaultValuesCompare = (oldMap.size() == newMap.size());
-
-            return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair);
-         }
-      case t_const_value::CV_IDENTIFIER:
-         return (newStructDefault->get_identifier() == oldStructDefault->get_identifier());
-      default:
-         return false;
-   }
-
-}
-
-void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName)
-{
-   t_type* newFieldType = newField->get_type();
-   t_type* oldFieldType = oldField->get_type();
-   if(!compare_type(newFieldType, oldFieldType))
-   {
-      thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
-   }
-
-   // A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values.
-   bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED);
-   bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED);
-
-   if(newStructFieldOptional != oldStructFieldOptional)
-   {
-      thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
-   }
-   if(newStructFieldOptional || oldStructFieldOptional)
-   {
-      if(!compare_defaults(newField->get_value(), oldField->get_value()))
-      {
-         thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
-      }
-   }
-
-   std::string fieldName = newField->get_name();
-   if(fieldName != oldField->get_name())
-   {
-      thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str());
-   }
-
-}
-
-void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string())
-{
-   std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName;
-   const std::vector<t_field*>& oldStructMembersInIdOrder = oldStruct->get_sorted_members();
-   const std::vector<t_field*>& newStructMembersInIdOrder = newStruct->get_sorted_members();
-   std::vector<t_field*>::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin();
-   std::vector<t_field*>::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin();
-
-   // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member
-   // lists together.  
-   while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end()))
-   {
-      if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end())
-      {
-         // A field ID has been removed from the end.
-         thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
-         oldStructMemberIt++;
-      }
-      else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end())
-      {
-         //New field ID has been added to the end.
-         if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED)
-         {
-            thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str());
-         }
-         newStructMemberIt++;
-      }
-      else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key())
-      {
-         //Field ID found in both structs. Compare field types, default values.
-         compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName);
-
-         newStructMemberIt++;
-         oldStructMemberIt++;
-      }
-      else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key())
-      {
-         //New Field Id is inserted in between
-         //Adding fields to struct is fine, but adding them in the middle is suspicious. Error!!
-         thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n",  (*newStructMemberIt)->get_key(),  structName.c_str());
-         newStructMemberIt++;
-      }
-      else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key())
-      {
-         //A field is deleted in newStruct.
-         thrift_audit_failure("Struct Field removed for Id = %d in %s \n",  (*oldStructMemberIt)->get_key(), structName.c_str());
-         oldStructMemberIt++;
-      }
-
-   }
-}
-
-void compare_structs(const std::vector<t_struct*>& newStructList, const std::vector<t_struct*>& oldStructList)
-{
-   std::map<std::string,t_struct*> newStructMap;
-   std::vector<t_struct*>::const_iterator newStructListIt;
-   for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++)
-   {
-      newStructMap[(*newStructListIt)->get_name()] = *newStructListIt;
-   }
-
-   std::vector<t_struct*>::const_iterator oldStructListIt;
-   for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++)
-   {
-      std::map<std::string, t_struct*>::iterator newStructMapIt;
-      newStructMapIt = newStructMap.find((*oldStructListIt)->get_name());
-      if(newStructMapIt == newStructMap.end())
-      {
-         thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str());
-      }
-      else
-      {
-         compare_single_struct(newStructMapIt->second, *oldStructListIt);
-      }
-   }
-
-}
-
-void compare_single_function(t_function* newFunction, t_function* oldFunction)
-{
-   t_type* newFunctionReturnType = newFunction->get_returntype();
-
-   if(newFunction->is_oneway() != oldFunction->is_oneway())
-   {
-      thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str());
-   }
-   if(!compare_type(newFunctionReturnType, oldFunction->get_returntype()))
-   {
-      thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str());
-   }
-
-   //Compare function arguments.
-   compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist());
-   std::string exceptionName = oldFunction->get_name();
-   exceptionName += "_exception";
-   compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName);
-}
-
-void compare_functions(const std::vector<t_function*>& newFunctionList, const std::vector<t_function*>& oldFunctionList)
-{
-   std::map<std::string, t_function*> newFunctionMap;
-   std::map<std::string, t_function*>::iterator newFunctionMapIt;
-   for(std::vector<t_function*>::const_iterator newFunctionIt = newFunctionList.begin();
-         newFunctionIt != newFunctionList.end();
-         newFunctionIt++)
-   {
-      newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt;
-   }
-
-   for(std::vector<t_function*>::const_iterator oldFunctionIt = oldFunctionList.begin();
-         oldFunctionIt != oldFunctionList.end();
-         oldFunctionIt++)
-   {
-      newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name());
-      if(newFunctionMapIt == newFunctionMap.end())
-      {
-         thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str());
-         continue;
-      }
-      else
-      {
-         //Function is found in both thrift files. Compare return type and argument list
-         compare_single_function(newFunctionMapIt->second, *oldFunctionIt);
-      }
-   }
-
-}
-
-void compare_services(const std::vector<t_service*>& newServices, const std::vector<t_service*>& oldServices)
-{
-   std::vector<t_service*>::const_iterator oldServiceIt;
-
-   std::map<std::string, t_service*> newServiceMap;
-   for(std::vector<t_service*>::const_iterator newServiceIt = newServices.begin();
-         newServiceIt != newServices.end();
-         newServiceIt++)
-   {
-      newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt;
-   }
-
-
-   for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++)
-   {
-      const std::string oldServiceName = (*oldServiceIt)->get_name();
-      std::map<std::string, t_service*>::iterator newServiceMapIt = newServiceMap.find(oldServiceName);
-
-      if(newServiceMapIt == newServiceMap.end())
-      {
-         thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str());
-      }
-      else
-      {
-         t_service* oldServiceExtends = (*oldServiceIt)->get_extends();
-         t_service* newServiceExtends = (newServiceMapIt->second)->get_extends();
-
-         if(oldServiceExtends == NULL)
-         {
-            // It is fine to add extends. So if service in older thrift did not have any extends, we are fine.
-            // DO Nothing
-         }
-         else if(oldServiceExtends != NULL && newServiceExtends == NULL)
-         {
-            thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
-         }
-         else
-         {
-            std::string oldExtendsName = oldServiceExtends->get_name();
-            std::string newExtendsName = newServiceExtends->get_name();
-
-            if( newExtendsName != oldExtendsName)
-            {
-               thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
-            }
-         }
-
-         compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions());
-      }
-
-   }
-
-}
-
-void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst)
-{
-   std::vector<t_const*>::const_iterator newConstIt;
-   std::vector<t_const*>::const_iterator oldConstIt;
-
-   std::map<std::string, t_const*> newConstMap;
-
-   for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++)
-   {
-      newConstMap[(*newConstIt)->get_name()] = *newConstIt;
-   }
-
-   std::map<std::string, t_const*>::const_iterator newConstMapIt;
-   for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++)
-   {
-      newConstMapIt = newConstMap.find((*oldConstIt)->get_name());
-      if(newConstMapIt == newConstMap.end())
-      {
-         thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str());
-      }
-      else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type()))
-      {
-         thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str());
-      }
-      else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value()))
-      {
-         thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str());
-      }
-   }
-}
-
-

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/audit/t_audit.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/audit/t_audit.h b/compiler/cpp/src/audit/t_audit.h
deleted file mode 100644
index be79e31..0000000
--- a/compiler/cpp/src/audit/t_audit.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef T_AUDIT_H
-#define T_AUDIT_H
-
-void compare_namespace(t_program* newProgram, t_program* oldProgram);
-void compare_enums(const std::vector<t_enum*>& newEnumList,
-                   const std::vector<t_enum*>& oldEnumList);
-bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault);
-void compare_structs(const std::vector<t_struct*>& newStructList,
-                     const std::vector<t_struct*>& oldStructList);
-void compare_services(const std::vector<t_service*>& newServices,
-                      const std::vector<t_service*>& oldServices);
-void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst);
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/common.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/common.cc b/compiler/cpp/src/common.cc
deleted file mode 100644
index 6e11bb2..0000000
--- a/compiler/cpp/src/common.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include "common.h"
-#include "parse/t_base_type.h"
-
-t_type* g_type_void;
-t_type* g_type_string;
-t_type* g_type_binary;
-t_type* g_type_slist;
-t_type* g_type_bool;
-t_type* g_type_i8;
-t_type* g_type_i16;
-t_type* g_type_i32;
-t_type* g_type_i64;
-t_type* g_type_double;
-
-void initGlobals() {
-  g_type_void = new t_base_type("void", t_base_type::TYPE_VOID);
-  g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
-  g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING);
-  ((t_base_type*)g_type_binary)->set_binary(true);
-  g_type_slist = new t_base_type("string", t_base_type::TYPE_STRING);
-  ((t_base_type*)g_type_slist)->set_string_list(true);
-  g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL);
-  g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8);
-  g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16);
-  g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32);
-  g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64);
-  g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
-}
-
-void clearGlobals() {
-  delete g_type_void;
-  delete g_type_string;
-  delete g_type_bool;
-  delete g_type_i8;
-  delete g_type_i16;
-  delete g_type_i32;
-  delete g_type_i64;
-  delete g_type_double;
-}
-
-/**
- * Those are not really needed for plugins but causes link errors without
- */
-
-/**
- * The location of the last parsed doctext comment.
- */
-int g_doctext_lineno;
-int g_program_doctext_lineno = 0;
-PROGDOCTEXT_STATUS g_program_doctext_status = INVALID;

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/common.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/common.h b/compiler/cpp/src/common.h
deleted file mode 100644
index ab7c423..0000000
--- a/compiler/cpp/src/common.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_COMMON_H
-#define T_COMMON_H
-
-#include "parse/t_type.h"
-
-/**
- * Global types for the parser to be able to reference
- */
-
-extern t_type* g_type_void;
-extern t_type* g_type_string;
-extern t_type* g_type_binary;
-extern t_type* g_type_slist;
-extern t_type* g_type_bool;
-extern t_type* g_type_i8;
-extern t_type* g_type_i16;
-extern t_type* g_type_i32;
-extern t_type* g_type_i64;
-extern t_type* g_type_double;
-
-void initGlobals();
-void clearGlobals();
-
-#endif


[13/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_gv_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_gv_generator.cc b/compiler/cpp/src/thrift/generate/t_gv_generator.cc
new file mode 100644
index 0000000..72b7c82
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_gv_generator.cc
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <map>
+#include <list>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/generate/t_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::pair;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Graphviz code generator
+ */
+class t_gv_generator : public t_generator {
+public:
+  t_gv_generator(t_program* program,
+                 const std::map<std::string, std::string>& parsed_options,
+                 const std::string& option_string)
+    : t_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    exception_arrows = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("exceptions") == 0) {
+        exception_arrows = true;
+      } else {
+        throw "unknown option gv:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-gv";
+  }
+
+  /**
+   * Init and end of generator
+   */
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_service(t_service* tservice);
+
+protected:
+  /**
+   * Helpers
+   */
+  void print_type(t_type* ttype, string struct_field_ref);
+  void print_const_value(t_type* type, t_const_value* tvalue);
+
+private:
+  std::ofstream f_out_;
+  std::list<string> edges;
+  bool exception_arrows;
+};
+
+/**
+ * Init generator:
+ * - Adds some escaping for the Graphviz domain.
+ * - Create output directory and open file for writting.
+ * - Write the file header.
+ */
+void t_gv_generator::init_generator() {
+  escape_['{'] = "\\{";
+  escape_['}'] = "\\}";
+
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  string fname = get_out_dir() + program_->get_name() + ".gv";
+  f_out_.open(fname.c_str());
+  f_out_ << "digraph \"" << escape_string(program_name_) << "\" {" << endl;
+  f_out_ << "node [style=filled, shape=record];" << endl;
+  f_out_ << "edge [arrowsize=0.5];" << endl;
+  f_out_ << "rankdir=LR" << endl;
+}
+
+/**
+ * Closes generator:
+ * - Print accumulated nodes connections.
+ * - Print footnote.
+ * - Closes file.
+ */
+void t_gv_generator::close_generator() {
+  // Print edges
+  std::list<string>::iterator iter = edges.begin();
+  for (; iter != edges.end(); iter++) {
+    f_out_ << (*iter) << endl;
+  }
+
+  // Print graph end } and close file
+  f_out_ << "}" << endl;
+  f_out_.close();
+}
+
+void t_gv_generator::generate_typedef(t_typedef* ttypedef) {
+  string name = ttypedef->get_name();
+  f_out_ << "node [fillcolor=azure];" << endl;
+  f_out_ << name << " [label=\"";
+
+  f_out_ << escape_string(name);
+  f_out_ << " :: ";
+  print_type(ttypedef->get_type(), name);
+
+  f_out_ << "\"];" << endl;
+}
+
+void t_gv_generator::generate_enum(t_enum* tenum) {
+  string name = tenum->get_name();
+  f_out_ << "node [fillcolor=white];" << endl;
+  f_out_ << name << " [label=\"enum " << escape_string(name);
+
+  vector<t_enum_value*> values = tenum->get_constants();
+  vector<t_enum_value*>::iterator val_iter;
+  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
+    f_out_ << '|' << (*val_iter)->get_name();
+    f_out_ << " = ";
+    f_out_ << (*val_iter)->get_value();
+  }
+
+  f_out_ << "\"];" << endl;
+}
+
+void t_gv_generator::generate_const(t_const* tconst) {
+  string name = tconst->get_name();
+
+  f_out_ << "node [fillcolor=aliceblue];" << endl;
+  f_out_ << "const_" << name << " [label=\"";
+
+  f_out_ << escape_string(name);
+  f_out_ << " = ";
+  print_const_value(tconst->get_type(), tconst->get_value());
+  f_out_ << " :: ";
+  print_type(tconst->get_type(), "const_" + name);
+
+  f_out_ << "\"];" << endl;
+}
+
+void t_gv_generator::generate_struct(t_struct* tstruct) {
+  string name = tstruct->get_name();
+
+  if (tstruct->is_xception()) {
+    f_out_ << "node [fillcolor=lightpink];" << endl;
+    f_out_ << name << " [label=\"";
+    f_out_ << "exception " << escape_string(name);
+  } else if (tstruct->is_union()) {
+    f_out_ << "node [fillcolor=lightcyan];" << endl;
+    f_out_ << name << " [label=\"";
+    f_out_ << "union " << escape_string(name);
+  } else {
+    f_out_ << "node [fillcolor=beige];" << endl;
+    f_out_ << name << " [label=\"";
+    f_out_ << "struct " << escape_string(name);
+  }
+
+  vector<t_field*> members = tstruct->get_members();
+  vector<t_field*>::iterator mem_iter = members.begin();
+  for (; mem_iter != members.end(); mem_iter++) {
+    string field_name = (*mem_iter)->get_name();
+
+    // print port (anchor reference)
+    f_out_ << "|<field_" << field_name << '>';
+
+    // field name :: field type
+    f_out_ << (*mem_iter)->get_name();
+    f_out_ << " :: ";
+    print_type((*mem_iter)->get_type(), name + ":field_" + field_name);
+  }
+
+  f_out_ << "\"];" << endl;
+}
+
+void t_gv_generator::print_type(t_type* ttype, string struct_field_ref) {
+  if (ttype->is_container()) {
+    if (ttype->is_list()) {
+      f_out_ << "list\\<";
+      print_type(((t_list*)ttype)->get_elem_type(), struct_field_ref);
+      f_out_ << "\\>";
+    } else if (ttype->is_set()) {
+      f_out_ << "set\\<";
+      print_type(((t_set*)ttype)->get_elem_type(), struct_field_ref);
+      f_out_ << "\\>";
+    } else if (ttype->is_map()) {
+      f_out_ << "map\\<";
+      print_type(((t_map*)ttype)->get_key_type(), struct_field_ref);
+      f_out_ << ", ";
+      print_type(((t_map*)ttype)->get_val_type(), struct_field_ref);
+      f_out_ << "\\>";
+    }
+  } else if (ttype->is_base_type()) {
+    f_out_ << (((t_base_type*)ttype)->is_binary() ? "binary" : ttype->get_name());
+  } else {
+    f_out_ << ttype->get_name();
+    edges.push_back(struct_field_ref + " -> " + ttype->get_name());
+  }
+}
+
+/**
+ * Prints out an string representation of the provided constant value
+ */
+void t_gv_generator::print_const_value(t_type* type, t_const_value* tvalue) {
+  bool first = true;
+  switch (tvalue->get_type()) {
+  case t_const_value::CV_INTEGER:
+    f_out_ << tvalue->get_integer();
+    break;
+  case t_const_value::CV_DOUBLE:
+    f_out_ << tvalue->get_double();
+    break;
+  case t_const_value::CV_STRING:
+    f_out_ << "\\\"" << get_escaped_string(tvalue) << "\\\"";
+    break;
+  case t_const_value::CV_MAP: {
+    f_out_ << "\\{ ";
+    map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
+    map<t_const_value*, t_const_value*>::iterator map_iter;
+    for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
+      if (!first) {
+        f_out_ << ", ";
+      }
+      first = false;
+      print_const_value(((t_map*)type)->get_key_type(), map_iter->first);
+      f_out_ << " = ";
+      print_const_value(((t_map*)type)->get_val_type(), map_iter->second);
+    }
+    f_out_ << " \\}";
+  } break;
+  case t_const_value::CV_LIST: {
+    f_out_ << "\\{ ";
+    vector<t_const_value*> list_elems = tvalue->get_list();
+    ;
+    vector<t_const_value*>::iterator list_iter;
+    for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
+      if (!first) {
+        f_out_ << ", ";
+      }
+      first = false;
+      if (type->is_list()) {
+        print_const_value(((t_list*)type)->get_elem_type(), *list_iter);
+      } else {
+        print_const_value(((t_set*)type)->get_elem_type(), *list_iter);
+      }
+    }
+    f_out_ << " \\}";
+  } break;
+  case t_const_value::CV_IDENTIFIER:
+    f_out_ << escape_string(type->get_name()) << "."
+           << escape_string(tvalue->get_identifier_name());
+    break;
+  default:
+    f_out_ << "UNKNOWN";
+    break;
+  }
+}
+
+void t_gv_generator::generate_service(t_service* tservice) {
+  string service_name = get_service_name(tservice);
+  f_out_ << "subgraph cluster_" << service_name << " {" << endl;
+  f_out_ << "node [fillcolor=bisque];" << endl;
+  f_out_ << "style=dashed;" << endl;
+  f_out_ << "label = \"" << escape_string(service_name) << " service\";" << endl;
+
+  // TODO: service extends
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator fn_iter = functions.begin();
+  for (; fn_iter != functions.end(); fn_iter++) {
+    string fn_name = (*fn_iter)->get_name();
+
+    f_out_ << "function_" << service_name << fn_name;
+    f_out_ << "[label=\"<return_type>function " << escape_string(fn_name);
+    f_out_ << " :: ";
+    print_type((*fn_iter)->get_returntype(), "function_" + service_name + fn_name + ":return_type");
+
+    vector<t_field*> args = (*fn_iter)->get_arglist()->get_members();
+    vector<t_field*>::iterator arg_iter = args.begin();
+    for (; arg_iter != args.end(); arg_iter++) {
+      f_out_ << "|<param_" << (*arg_iter)->get_name() << ">";
+      f_out_ << (*arg_iter)->get_name();
+      if ((*arg_iter)->get_value() != NULL) {
+        f_out_ << " = ";
+        print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value());
+      }
+      f_out_ << " :: ";
+      print_type((*arg_iter)->get_type(),
+                 "function_" + service_name + fn_name + ":param_" + (*arg_iter)->get_name());
+    }
+    // end of node
+    f_out_ << "\"];" << endl;
+
+    // Exception edges
+    if (exception_arrows) {
+      vector<t_field*> excepts = (*fn_iter)->get_xceptions()->get_members();
+      vector<t_field*>::iterator ex_iter = excepts.begin();
+      for (; ex_iter != excepts.end(); ex_iter++) {
+        edges.push_back("function_" + service_name + fn_name + " -> "
+                        + (*ex_iter)->get_type()->get_name() + " [color=red]");
+      }
+    }
+  }
+
+  f_out_ << " }" << endl;
+}
+
+THRIFT_REGISTER_GENERATOR(
+    gv,
+    "Graphviz",
+    "    exceptions:      Whether to draw arrows from functions to exception.\n")


[38/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_hs_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_hs_generator.cc b/compiler/cpp/src/generate/t_hs_generator.cc
deleted file mode 100644
index cef8cd0..0000000
--- a/compiler/cpp/src/generate/t_hs_generator.cc
+++ /dev/null
@@ -1,1734 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-
-#include "t_oop_generator.h"
-
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Haskell code generator.
- *
- */
-class t_hs_generator : public t_oop_generator {
-public:
-  t_hs_generator(t_program* program,
-                 const map<string, string>& parsed_options,
-                 const string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option hs:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-hs";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  string render_const_value(t_type* type, t_const_value* value);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_hs_struct(t_struct* tstruct, bool is_exception);
-
-  void generate_hs_struct_definition(ofstream& out,
-                                     t_struct* tstruct,
-                                     bool is_xception = false,
-                                     bool helper = false);
-
-  void generate_hs_struct_reader(ofstream& out, t_struct* tstruct);
-
-  void generate_hs_struct_writer(ofstream& out, t_struct* tstruct);
-
-  void generate_hs_struct_arbitrary(ofstream& out, t_struct* tstruct);
-
-  void generate_hs_function_helpers(t_function* tfunction);
-
-  void generate_hs_typemap(ofstream& out, t_struct* tstruct);
-
-  void generate_hs_default(ofstream& out, t_struct* tstruct);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(ofstream& out, t_field* tfield, string prefix);
-
-  void generate_deserialize_struct(ofstream& out, t_struct* tstruct, string name = "");
-
-  void generate_deserialize_container(ofstream& out, t_type* ttype, string arg = "");
-
-  void generate_deserialize_set_element(ofstream& out, t_set* tset);
-
-  void generate_deserialize_list_element(ofstream& out, t_list* tlist, string prefix = "");
-
-  void generate_deserialize_type(ofstream& out, t_type* type, string arg = "");
-
-  void generate_serialize_type(ofstream& out, t_type* type, string name = "");
-
-  void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix = "");
-
-  void generate_serialize_container(ofstream& out, t_type* ttype, string prefix = "");
-
-  void generate_serialize_map_element(ofstream& out, t_map* tmap, string kiter, string viter);
-
-  void generate_serialize_set_element(ofstream& out, t_set* tmap, string iter);
-
-  void generate_serialize_list_element(ofstream& out, t_list* tlist, string iter);
-
-  /**
-   * Helper rendering functions
-   */
-
-  string hs_autogen_comment();
-  string hs_language_pragma();
-  string hs_imports();
-
-  string type_name(t_type* ttype, string function_prefix = "");
-
-  string field_name(string tname, string fname);
-
-  string function_type(t_function* tfunc,
-                       bool options = false,
-                       bool io = false,
-                       bool method = false);
-
-  string type_to_enum(t_type* ttype);
-
-  string type_to_default(t_type* ttype);
-
-  string render_hs_type(t_type* type, bool needs_parens);
-
-  string type_to_constructor(t_type* ttype);
-
-  string render_hs_type_for_function_name(t_type* type);
-
-private:
-  ofstream f_types_;
-  ofstream f_consts_;
-  ofstream f_service_;
-  ofstream f_iface_;
-  ofstream f_client_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_hs_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  // Make output file
-  string pname = capitalize(program_name_);
-  string f_types_name = get_out_dir() + pname + "_Types.hs";
-  f_types_.open(f_types_name.c_str());
-
-  string f_consts_name = get_out_dir() + pname + "_Consts.hs";
-  f_consts_.open(f_consts_name.c_str());
-
-  // Print header
-  f_types_ << hs_language_pragma() << endl;
-  f_types_ << hs_autogen_comment() << endl;
-  f_types_ << "module " << pname << "_Types where" << endl;
-  f_types_ << hs_imports() << endl;
-
-  f_consts_ << hs_language_pragma() << endl;
-  f_consts_ << hs_autogen_comment() << endl;
-  f_consts_ << "module " << pname << "_Consts where" << endl;
-  f_consts_ << hs_imports() << endl;
-  f_consts_ << "import " << pname << "_Types" << endl;
-}
-
-string t_hs_generator::hs_language_pragma() {
-  return string(
-      "{-# LANGUAGE DeriveDataTypeable #-}\n"
-      "{-# LANGUAGE DeriveGeneric #-}\n"
-      "{-# LANGUAGE OverloadedStrings #-}\n"
-      "{-# OPTIONS_GHC -fno-warn-missing-fields #-}\n"
-      "{-# OPTIONS_GHC -fno-warn-missing-signatures #-}\n"
-      "{-# OPTIONS_GHC -fno-warn-name-shadowing #-}\n"
-      "{-# OPTIONS_GHC -fno-warn-unused-imports #-}\n"
-      "{-# OPTIONS_GHC -fno-warn-unused-matches #-}\n");
-}
-
-/**
- * Autogen'd comment
- */
-string t_hs_generator::hs_autogen_comment() {
-  return string("-----------------------------------------------------------------\n")
-         + "-- Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")                      --\n"
-         + "--                                                             --\n"
-         + "-- DO NOT EDIT UNLESS YOU ARE SURE YOU KNOW WHAT YOU ARE DOING --\n"
-         + "-----------------------------------------------------------------\n";
-}
-
-/**
- * Prints standard thrift imports
- */
-string t_hs_generator::hs_imports() {
-  const vector<t_program*>& includes = program_->get_includes();
-  string result = string(
-      "import Prelude (($), (.), (>>=), (==), (++))\n"
-      "import qualified Prelude as P\n"
-      "import qualified Control.Exception as X\n"
-      "import qualified Control.Monad as M ( liftM, ap, when )\n"
-      "import Data.Functor ( (<$>) )\n"
-      "import qualified Data.ByteString.Lazy as LBS\n"
-      "import qualified Data.Hashable as H\n"
-      "import qualified Data.Int as I\n"
-      "import qualified Data.Maybe as M (catMaybes)\n"
-      "import qualified Data.Text.Lazy.Encoding as E ( decodeUtf8, encodeUtf8 )\n"
-      "import qualified Data.Text.Lazy as LT\n"
-      "import qualified GHC.Generics as G (Generic)\n"
-      "import qualified Data.Typeable as TY ( Typeable )\n"
-      "import qualified Data.HashMap.Strict as Map\n"
-      "import qualified Data.HashSet as Set\n"
-      "import qualified Data.Vector as Vector\n"
-      "import qualified Test.QuickCheck.Arbitrary as QC ( Arbitrary(..) )\n"
-      "import qualified Test.QuickCheck as QC ( elements )\n"
-      "\n"
-      "import qualified Thrift as T\n"
-      "import qualified Thrift.Types as T\n"
-      "import qualified Thrift.Arbitraries as T\n"
-      "\n");
-
-  for (size_t i = 0; i < includes.size(); ++i)
-    result += "import qualified " + capitalize(includes[i]->get_name()) + "_Types\n";
-
-  if (includes.size() > 0)
-    result += "\n";
-
-  return result;
-}
-
-/**
- * Closes the type files
- */
-void t_hs_generator::close_generator() {
-  // Close types file
-  f_types_.close();
-  f_consts_.close();
-}
-
-/**
- * Generates a typedef. Ez.
- *
- * @param ttypedef The type definition
- */
-void t_hs_generator::generate_typedef(t_typedef* ttypedef) {
-  string tname = capitalize(ttypedef->get_symbolic());
-  string tdef = render_hs_type(ttypedef->get_type(), false);
-  indent(f_types_) << "type " << tname << " = " << tdef << endl;
-  f_types_ << endl;
-}
-
-/**
- * Generates code for an enumerated type.
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_hs_generator::generate_enum(t_enum* tenum) {
-  indent(f_types_) << "data " << capitalize(tenum->get_name()) << " = ";
-  indent_up();
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-
-  bool first = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    string name = capitalize((*c_iter)->get_name());
-    f_types_ << (first ? "" : "|");
-    f_types_ << name;
-    first = false;
-  }
-  indent(f_types_) << "deriving (P.Show, P.Eq, G.Generic, TY.Typeable, P.Ord, P.Bounded)" << endl;
-  indent_down();
-
-  string ename = capitalize(tenum->get_name());
-
-  indent(f_types_) << "instance P.Enum " << ename << " where" << endl;
-  indent_up();
-  indent(f_types_) << "fromEnum t = case t of" << endl;
-  indent_up();
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    string name = capitalize((*c_iter)->get_name());
-    indent(f_types_) << name << " -> " << value << endl;
-  }
-  indent_down();
-  indent(f_types_) << "toEnum t = case t of" << endl;
-  indent_up();
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    string name = capitalize((*c_iter)->get_name());
-    indent(f_types_) << value << " -> " << name << endl;
-  }
-  indent(f_types_) << "_ -> X.throw T.ThriftException" << endl;
-  indent_down();
-  indent_down();
-
-  indent(f_types_) << "instance H.Hashable " << ename << " where" << endl;
-  indent_up();
-  indent(f_types_) << "hashWithSalt salt = H.hashWithSalt salt P.. P.fromEnum" << endl;
-  indent_down();
-
-  indent(f_types_) << "instance QC.Arbitrary " << ename << " where" << endl;
-  indent_up();
-  indent(f_types_) << "arbitrary = QC.elements (P.enumFromTo P.minBound P.maxBound)" << endl;
-  indent_down();
-}
-
-/**
- * Generate a constant value
- */
-void t_hs_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = decapitalize(tconst->get_name());
-
-  t_const_value* value = tconst->get_value();
-
-  indent(f_consts_) << name << " :: " << render_hs_type(type, false) << endl;
-  indent(f_consts_) << name << " = " << render_const_value(type, value) << endl;
-  f_consts_ << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_hs_generator::render_const_value(t_type* type, t_const_value* value) {
-  if (value == NULL)
-    return type_to_default(type);
-
-  type = get_true_type(type);
-  ostringstream out;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "P.True" : "P.False");
-      break;
-
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << "(" << value->get_integer() << ")";
-      break;
-
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << "(" << value->get_integer() << ")";
-      } else {
-        out << "(" << value->get_double() << ")";
-      }
-      break;
-
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-
-  } else if (type->is_enum()) {
-    t_enum* tenum = (t_enum*)type;
-    vector<t_enum_value*> constants = tenum->get_constants();
-    for (vector<t_enum_value*>::iterator c_iter = constants.begin(); c_iter != constants.end();
-         ++c_iter) {
-      int val = (*c_iter)->get_value();
-      if (val == value->get_integer()) {
-        t_program* prog = type->get_program();
-        if (prog != NULL && prog != program_)
-          out << capitalize(prog->get_name()) << "_Types.";
-        out << capitalize((*c_iter)->get_name());
-        break;
-      }
-    }
-
-  } else if (type->is_struct() || type->is_xception()) {
-    string cname = type_name(type);
-    out << "default_" << cname << "{";
-
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-
-    bool first = true;
-    for (map<t_const_value*, t_const_value*>::const_iterator v_iter = val.begin();
-         v_iter != val.end();
-         ++v_iter) {
-      t_field* field = NULL;
-
-      for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end();
-           ++f_iter)
-        if ((*f_iter)->get_name() == v_iter->first->get_string())
-          field = (*f_iter);
-
-      if (field == NULL)
-        throw "type error: " + cname + " has no field " + v_iter->first->get_string();
-
-      string fname = v_iter->first->get_string();
-      string const_value = render_const_value(field->get_type(), v_iter->second);
-
-      out << (first ? "" : ", ");
-      out << field_name(cname, fname) << " = ";
-      if (field->get_req() == t_field::T_OPTIONAL || ((t_type*)field->get_type())->is_xception()) {
-        out << "P.Just ";
-      }
-      out << const_value;
-      first = false;
-    }
-
-    out << "}";
-
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    out << "(Map.fromList [";
-
-    bool first = true;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(ktype, v_iter->first);
-      string val = render_const_value(vtype, v_iter->second);
-      out << (first ? "" : ",");
-      out << "(" << key << "," << val << ")";
-      first = false;
-    }
-    out << "])";
-
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype = type->is_list() ? ((t_list*)type)->get_elem_type()
-                                    : ((t_set*)type)->get_elem_type();
-
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-
-    if (type->is_set())
-      out << "(Set.fromList [";
-    else
-      out << "(Vector.fromList [";
-
-    bool first = true;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << (first ? "" : ",");
-      out << render_const_value(etype, *v_iter);
-      first = false;
-    }
-
-    out << "])";
-
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-
-  return out.str();
-}
-
-/**
- * Generates a "struct"
- */
-void t_hs_generator::generate_struct(t_struct* tstruct) {
-  generate_hs_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct, but also has an exception declaration.
- *
- * @param txception The struct definition
- */
-void t_hs_generator::generate_xception(t_struct* txception) {
-  generate_hs_struct(txception, true);
-}
-
-/**
- * Generates a Haskell struct
- */
-void t_hs_generator::generate_hs_struct(t_struct* tstruct, bool is_exception) {
-  generate_hs_struct_definition(f_types_, tstruct, is_exception, false);
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_hs_generator::generate_hs_struct_definition(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   bool is_exception,
-                                                   bool helper) {
-  (void)helper;
-  string tname = type_name(tstruct);
-  string name = tstruct->get_name();
-  const vector<t_field*>& members = tstruct->get_members();
-
-  indent(out) << "data " << tname << " = " << tname;
-  if (members.size() > 0) {
-    indent_up();
-    bool first = true;
-    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
-         ++m_iter) {
-      if (first) {
-        indent(out) << "{ ";
-        first = false;
-      } else {
-        indent(out) << ", ";
-      }
-      string mname = (*m_iter)->get_name();
-      out << field_name(tname, mname) << " :: ";
-      if ((*m_iter)->get_req() == t_field::T_OPTIONAL
-          || ((t_type*)(*m_iter)->get_type())->is_xception()) {
-        out << "P.Maybe ";
-      }
-      out << render_hs_type((*m_iter)->get_type(), true) << endl;
-    }
-    indent(out) << "}";
-    indent_down();
-  }
-
-  out << " deriving (P.Show,P.Eq,G.Generic,TY.Typeable)" << endl;
-
-  if (is_exception)
-    out << "instance X.Exception " << tname << endl;
-
-  indent(out) << "instance H.Hashable " << tname << " where" << endl;
-  indent_up();
-  indent(out) << "hashWithSalt salt record = salt";
-  for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
-       ++m_iter) {
-    string mname = (*m_iter)->get_name();
-    indent(out) << " `H.hashWithSalt` " << field_name(tname, mname) << " record";
-  }
-  indent(out) << endl;
-  indent_down();
-
-  generate_hs_struct_arbitrary(out, tstruct);
-  generate_hs_struct_writer(out, tstruct);
-  generate_hs_struct_reader(out, tstruct);
-  generate_hs_typemap(out, tstruct);
-  generate_hs_default(out, tstruct);
-}
-
-void t_hs_generator::generate_hs_struct_arbitrary(ofstream& out, t_struct* tstruct) {
-  string tname = type_name(tstruct);
-  string name = tstruct->get_name();
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  indent(out) << "instance QC.Arbitrary " << tname << " where " << endl;
-  indent_up();
-  if (members.size() > 0) {
-    indent(out) << "arbitrary = M.liftM " << tname;
-    indent_up();
-    indent_up();
-    indent_up();
-    indent_up();
-    bool first = true;
-    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
-         ++m_iter) {
-      if (first) {
-        first = false;
-        out << " ";
-      } else {
-        indent(out) << "`M.ap`";
-      }
-      out << "(";
-      if ((*m_iter)->get_req() == t_field::T_OPTIONAL
-          || ((t_type*)(*m_iter)->get_type())->is_xception()) {
-        out << "M.liftM P.Just ";
-      }
-      out << "QC.arbitrary)" << endl;
-    }
-    indent_down();
-    indent_down();
-    indent_down();
-    indent_down();
-
-    // Shrink
-    indent(out) << "shrink obj | obj == default_" << tname << " = []" << endl;
-    indent(out) << "           | P.otherwise = M.catMaybes" << endl;
-    indent_up();
-    first = true;
-    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
-         ++m_iter) {
-      if (first) {
-        first = false;
-        indent(out) << "[ ";
-      } else {
-        indent(out) << ", ";
-      }
-      string fname = field_name(tname, (*m_iter)->get_name());
-      out << "if obj == default_" << tname;
-      out << "{" << fname << " = " << fname << " obj} ";
-      out << "then P.Nothing ";
-      out << "else P.Just $ default_" << tname;
-      out << "{" << fname << " = " << fname << " obj}" << endl;
-    }
-    indent(out) << "]" << endl;
-    indent_down();
-  } else { /* 0 == members.size() */
-    indent(out) << "arbitrary = QC.elements [" << tname << "]" << endl;
-  }
-  indent_down();
-}
-
-/**
- * Generates the read method for a struct
- */
-void t_hs_generator::generate_hs_struct_reader(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  string sname = type_name(tstruct);
-  string id = tmp("_id");
-  string val = tmp("_val");
-
-  indent(out) << "to_" << sname << " :: T.ThriftVal -> " << sname << endl;
-  indent(out) << "to_" << sname << " (T.TStruct fields) = " << sname << "{" << endl;
-  indent_up();
-
-  bool first = true;
-
-  // Generate deserialization code for known cases
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    int32_t key = (*f_iter)->get_key();
-    string etype = type_to_enum((*f_iter)->get_type());
-    string fname = (*f_iter)->get_name();
-
-    if (first) {
-      first = false;
-    } else {
-      out << "," << endl;
-    }
-
-    // Fill in Field
-    indent(out) << field_name(sname, fname) << " = ";
-
-    out << "P.maybe (";
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      out << "P.error \"Missing required field: " << fname << "\"";
-    } else {
-      if (((*f_iter)->get_req() == t_field::T_OPTIONAL
-           || ((t_type*)(*f_iter)->get_type())->is_xception()) && (*f_iter)->get_value() == NULL) {
-        out << "P.Nothing";
-      } else {
-        out << field_name(sname, fname) << " default_" << sname;
-      }
-    }
-    out << ") ";
-
-    out << "(\\(_," << val << ") -> ";
-    if ((*f_iter)->get_req() == t_field::T_OPTIONAL
-        || ((t_type*)(*f_iter)->get_type())->is_xception())
-      out << "P.Just ";
-    generate_deserialize_field(out, *f_iter, val);
-    out << ")";
-    out << " (Map.lookup (" << key << ") fields)";
-  }
-
-  out << endl;
-  indent(out) << "}" << endl;
-  indent_down();
-
-  // read
-  string tmap = type_name(tstruct, "typemap_");
-  indent(out) << "to_" << sname << " _ = P.error \"not a struct\"" << endl;
-
-  indent(out) << "read_" << sname << " :: (T.Transport t, T.Protocol p) => p t -> P.IO " << sname
-              << endl;
-  indent(out) << "read_" << sname << " iprot = to_" << sname;
-  out << " <$> T.readVal iprot (T.T_STRUCT " << tmap << ")" << endl;
-
-  indent(out) << "decode_" << sname
-              << " :: (T.Protocol p, T.Transport t) => p t -> LBS.ByteString -> " << sname << endl;
-  indent(out) << "decode_" << sname << " iprot bs = to_" << sname << " $ ";
-  out << "T.deserializeVal iprot (T.T_STRUCT " << tmap << ") bs" << endl;
-}
-
-void t_hs_generator::generate_hs_struct_writer(ofstream& out, t_struct* tstruct) {
-  string name = type_name(tstruct);
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-  string str = tmp("_str");
-  string f = tmp("_f");
-  string v = tmp("_v");
-
-  indent(out) << "from_" << name << " :: " << name << " -> T.ThriftVal" << endl;
-  indent(out) << "from_" << name << " record = T.TStruct $ Map.fromList ";
-  indent_up();
-
-  // Get Exceptions
-  bool hasExn = false;
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (((t_type*)(*f_iter)->get_type())->is_xception()) {
-      hasExn = true;
-      break;
-    }
-  }
-
-  bool isfirst = true;
-  if (hasExn) {
-    out << endl;
-    indent(out) << "(let exns = M.catMaybes ";
-    indent_up();
-    for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end();
-         ++f_iter) {
-      if (((t_type*)(*f_iter)->get_type())->is_xception()) {
-        if (isfirst) {
-          out << "[ ";
-          isfirst = false;
-        } else {
-          out << ", ";
-        }
-        string mname = (*f_iter)->get_name();
-        int32_t key = (*f_iter)->get_key();
-        out << "(\\" << v << " -> (" << key << ", (\"" << mname << "\",";
-        generate_serialize_type(out, (*f_iter)->get_type(), v);
-        out << "))) <$> " << field_name(name, mname) << " record";
-      }
-    }
-    if (!isfirst) {
-      out << "]" << endl;
-    }
-    indent_down();
-    indent(out) << "in if P.not (P.null exns) then exns else ";
-    indent_up();
-  } else {
-    out << "$ ";
-  }
-
-  out << "M.catMaybes" << endl;
-  // Get the Rest
-  isfirst = true;
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    // Write field header
-    if (isfirst) {
-      indent(out) << "[ ";
-      isfirst = false;
-    } else {
-      indent(out) << ", ";
-    }
-    string mname = (*f_iter)->get_name();
-    int32_t key = (*f_iter)->get_key();
-    out << "(\\";
-    out << v << " -> ";
-    if ((*f_iter)->get_req() != t_field::T_OPTIONAL
-        && !((t_type*)(*f_iter)->get_type())->is_xception()) {
-      out << "P.Just ";
-    }
-    out << "(" << key << ", (\"" << mname << "\",";
-    generate_serialize_type(out, (*f_iter)->get_type(), v);
-    out << "))) ";
-    if ((*f_iter)->get_req() != t_field::T_OPTIONAL
-        && !((t_type*)(*f_iter)->get_type())->is_xception()) {
-      out << "$";
-    } else {
-      out << "<$>";
-    }
-    out << " " << field_name(name, mname) << " record" << endl;
-  }
-
-  // Write the struct map
-  if (isfirst) {
-    indent(out) << "[]" << endl;
-  } else {
-    indent(out) << "]" << endl;
-  }
-  if (hasExn) {
-    indent(out) << ")" << endl;
-    indent_down();
-  }
-  indent_down();
-
-  // write
-  indent(out) << "write_" << name << " :: (T.Protocol p, T.Transport t) => p t -> " << name
-              << " -> P.IO ()" << endl;
-  indent(out) << "write_" << name << " oprot record = T.writeVal oprot $ from_";
-  out << name << " record" << endl;
-
-  // encode
-  indent(out) << "encode_" << name << " :: (T.Protocol p, T.Transport t) => p t -> " << name
-              << " -> LBS.ByteString" << endl;
-  indent(out) << "encode_" << name << " oprot record = T.serializeVal oprot $ ";
-  out << "from_" << name << " record" << endl;
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_hs_generator::generate_service(t_service* tservice) {
-  string f_service_name = get_out_dir() + capitalize(service_name_) + ".hs";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << hs_language_pragma() << endl;
-  f_service_ << hs_autogen_comment() << endl;
-  f_service_ << "module " << capitalize(service_name_) << " where" << endl;
-  f_service_ << hs_imports() << endl;
-
-  if (tservice->get_extends()) {
-    f_service_ << "import qualified " << capitalize(tservice->get_extends()->get_name()) << endl;
-  }
-
-  f_service_ << "import " << capitalize(program_name_) << "_Types" << endl;
-  f_service_ << "import qualified " << capitalize(service_name_) << "_Iface as Iface" << endl;
-
-  // Generate the three main parts of the service
-  generate_service_helpers(tservice);
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-
-  // Close service file
-  f_service_.close();
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_hs_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  indent(f_service_) << "-- HELPER FUNCTIONS AND STRUCTURES --" << endl;
-  indent(f_service_) << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_hs_struct_definition(f_service_, ts, false);
-    generate_hs_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_hs_generator::generate_hs_function_helpers(t_function* tfunction) {
-  t_struct result(program_, field_name(tfunction->get_name(), "result"));
-  t_field success(tfunction->get_returntype(), "success", 0);
-
-  if (!tfunction->get_returntype()->is_void())
-    result.append(&success);
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
-    result.append(*f_iter);
-
-  generate_hs_struct_definition(f_service_, &result, false);
-}
-
-/**
- * Generate the map from field names to (type, id)
- * @param tstruct the Struct
- */
-void t_hs_generator::generate_hs_typemap(ofstream& out, t_struct* tstruct) {
-  string name = type_name(tstruct);
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "typemap_" << name << " :: T.TypeMap" << endl;
-  indent(out) << "typemap_" << name << " = Map.fromList [";
-  bool first = true;
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    string mname = (*f_iter)->get_name();
-    if (!first) {
-      out << ",";
-    }
-
-    t_type* type = get_true_type((*f_iter)->get_type());
-    int32_t key = (*f_iter)->get_key();
-    out << "(" << key << ",(\"" << mname << "\"," << type_to_enum(type) << "))";
-    first = false;
-  }
-  out << "]" << endl;
-}
-
-/**
- * generate the struct with default values filled in
- * @param tstruct the Struct
- */
-void t_hs_generator::generate_hs_default(ofstream& out, t_struct* tstruct) {
-  string name = type_name(tstruct);
-  string fname = type_name(tstruct, "default_");
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-
-  indent(out) << fname << " :: " << name << endl;
-  indent(out) << fname << " = " << name << "{" << endl;
-  indent_up();
-  bool first = true;
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    string mname = (*f_iter)->get_name();
-    if (first) {
-      first = false;
-    } else {
-      out << "," << endl;
-    }
-
-    t_type* type = get_true_type((*f_iter)->get_type());
-    t_const_value* value = (*f_iter)->get_value();
-    indent(out) << field_name(name, mname) << " = ";
-    if ((*f_iter)->get_req() == t_field::T_OPTIONAL
-        || ((t_type*)(*f_iter)->get_type())->is_xception()) {
-      if (value == NULL) {
-        out << "P.Nothing";
-      } else {
-        out << "P.Just " << render_const_value(type, value);
-      }
-    } else {
-      out << render_const_value(type, value);
-    }
-  }
-  out << "}" << endl;
-  indent_down();
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_hs_generator::generate_service_interface(t_service* tservice) {
-  string f_iface_name = get_out_dir() + capitalize(service_name_) + "_Iface.hs";
-  f_iface_.open(f_iface_name.c_str());
-
-  f_iface_ << hs_language_pragma() << endl;
-  f_iface_ << hs_autogen_comment() << endl;
-
-  f_iface_ << "module " << capitalize(service_name_) << "_Iface where" << endl;
-
-  f_iface_ << hs_imports() << endl;
-  f_iface_ << "import " << capitalize(program_name_) << "_Types" << endl;
-  f_iface_ << endl;
-
-  string sname = capitalize(service_name_);
-  if (tservice->get_extends() != NULL) {
-    string extends = type_name(tservice->get_extends());
-
-    indent(f_iface_) << "import " << extends << "_Iface" << endl;
-    indent(f_iface_) << "class " << extends << "_Iface a => " << sname << "_Iface a where" << endl;
-
-  } else {
-    indent(f_iface_) << "class " << sname << "_Iface a where" << endl;
-  }
-
-  indent_up();
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string ft = function_type(*f_iter, true, true, true);
-    indent(f_iface_) << decapitalize((*f_iter)->get_name()) << " :: a -> " << ft << endl;
-  }
-
-  indent_down();
-  f_iface_.close();
-}
-
-/**
- * Generates a service client definition. Note that in Haskell, the client doesn't implement iface.
- *This is because
- * The client does not (and should not have to) deal with arguments being Nothing.
- *
- * @param tservice The service to generate a server for.
- */
-void t_hs_generator::generate_service_client(t_service* tservice) {
-  string f_client_name = get_out_dir() + capitalize(service_name_) + "_Client.hs";
-  f_client_.open(f_client_name.c_str());
-  f_client_ << hs_language_pragma() << endl;
-  f_client_ << hs_autogen_comment() << endl;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-
-  string extends = "";
-  string exports = "";
-
-  bool first = true;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    exports += (first ? "" : ",");
-    string funname = (*f_iter)->get_name();
-    exports += decapitalize(funname);
-    first = false;
-  }
-
-  string sname = capitalize(service_name_);
-  indent(f_client_) << "module " << sname << "_Client(" << exports << ") where" << endl;
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    indent(f_client_) << "import " << extends << "_Client" << endl;
-  }
-
-  indent(f_client_) << "import qualified Data.IORef as R" << endl;
-  indent(f_client_) << hs_imports() << endl;
-  indent(f_client_) << "import " << capitalize(program_name_) << "_Types" << endl;
-  indent(f_client_) << "import " << capitalize(service_name_) << endl;
-
-  // DATS RITE A GLOBAL VAR
-  indent(f_client_) << "seqid = R.newIORef 0" << endl;
-
-  // Generate client method implementations
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-
-    string fargs = "";
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter)
-      fargs += " arg_" + (*fld_iter)->get_name();
-
-    // Open function
-    indent(f_client_) << decapitalize(funname) << " (ip,op)" << fargs << " = do" << endl;
-    indent_up();
-    indent(f_client_) << "send_" << funname << " op" << fargs;
-
-    f_client_ << endl;
-
-    if (!(*f_iter)->is_oneway())
-      indent(f_client_) << "recv_" << funname << " ip" << endl;
-
-    indent_down();
-
-    indent(f_client_) << "send_" << funname << " op" << fargs << " = do" << endl;
-    indent_up();
-
-    indent(f_client_) << "seq <- seqid" << endl;
-    indent(f_client_) << "seqn <- R.readIORef seq" << endl;
-    string argsname = capitalize((*f_iter)->get_name() + "_args");
-
-    // Serialize the request header
-    string fname = (*f_iter)->get_name();
-    string msgType = (*f_iter)->is_oneway() ? "T.M_ONEWAY" : "T.M_CALL";
-    indent(f_client_) << "T.writeMessageBegin op (\"" << fname << "\", " << msgType << ", seqn)"
-                      << endl;
-    indent(f_client_) << "write_" << argsname << " op (" << argsname << "{";
-
-    bool first = true;
-    for (vector<t_field*>::const_iterator fld_iter = fields.begin(); fld_iter != fields.end();
-         ++fld_iter) {
-      string fieldname = (*fld_iter)->get_name();
-      f_client_ << (first ? "" : ",");
-      f_client_ << field_name(argsname, fieldname) << "=";
-      if ((*fld_iter)->get_req() == t_field::T_OPTIONAL
-          || ((t_type*)(*fld_iter)->get_type())->is_xception())
-        f_client_ << "P.Just ";
-      f_client_ << "arg_" << fieldname;
-      first = false;
-    }
-    f_client_ << "})" << endl;
-    indent(f_client_) << "T.writeMessageEnd op" << endl;
-
-    // Write to the stream
-    indent(f_client_) << "T.tFlush (T.getTransport op)" << endl;
-    indent_down();
-
-    if (!(*f_iter)->is_oneway()) {
-      string resultname = capitalize((*f_iter)->get_name() + "_result");
-      t_struct noargs(program_);
-
-      string funname = string("recv_") + (*f_iter)->get_name();
-      t_function recv_function((*f_iter)->get_returntype(), funname, &noargs);
-
-      // Open function
-      indent(f_client_) << funname << " ip = do" << endl;
-      indent_up();
-
-      indent(f_client_) << "(fname, mtype, rseqid) <- T.readMessageBegin ip" << endl;
-      indent(f_client_) << "M.when (mtype == T.M_EXCEPTION) $ do { exn <- T.readAppExn ip ; "
-                           "T.readMessageEnd ip ; X.throw exn }" << endl;
-
-      indent(f_client_) << "res <- read_" << resultname << " ip" << endl;
-      indent(f_client_) << "T.readMessageEnd ip" << endl;
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const vector<t_field*>& xceptions = xs->get_members();
-
-      for (vector<t_field*>::const_iterator x_iter = xceptions.begin(); x_iter != xceptions.end();
-           ++x_iter) {
-        indent(f_client_) << "P.maybe (P.return ()) X.throw ("
-                          << field_name(resultname, (*x_iter)->get_name()) << " res)" << endl;
-      }
-
-      if (!(*f_iter)->get_returntype()->is_void())
-        indent(f_client_) << "P.return $ " << field_name(resultname, "success") << " res" << endl;
-      else
-        indent(f_client_) << "P.return ()" << endl;
-
-      // Close function
-      indent_down();
-    }
-  }
-
-  f_client_.close();
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_hs_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter)
-    generate_process_function(tservice, *f_iter);
-
-  indent(f_service_) << "proc_ handler (iprot,oprot) (name,typ,seqid) = case name of" << endl;
-  indent_up();
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string fname = (*f_iter)->get_name();
-    indent(f_service_) << "\"" << fname << "\" -> process_" << decapitalize(fname)
-                       << " (seqid,iprot,oprot,handler)" << endl;
-  }
-
-  indent(f_service_) << "_ -> ";
-  if (tservice->get_extends() != NULL) {
-    f_service_ << type_name(tservice->get_extends())
-               << ".proc_ handler (iprot,oprot) (name,typ,seqid)" << endl;
-
-  } else {
-    f_service_ << "do" << endl;
-    indent_up();
-    indent(f_service_) << "_ <- T.readVal iprot (T.T_STRUCT Map.empty)" << endl;
-    indent(f_service_) << "T.writeMessageBegin oprot (name,T.M_EXCEPTION,seqid)" << endl;
-    indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN_METHOD (\"Unknown function "
-                          "\" ++ LT.unpack name))" << endl;
-    indent(f_service_) << "T.writeMessageEnd oprot" << endl;
-    indent(f_service_) << "T.tFlush (T.getTransport oprot)" << endl;
-    indent_down();
-  }
-
-  indent_down();
-
-  // Generate the server implementation
-  indent(f_service_) << "process handler (iprot, oprot) = do" << endl;
-  indent_up();
-
-  indent(f_service_) << "(name, typ, seqid) <- T.readMessageBegin iprot" << endl;
-  indent(f_service_) << "proc_ handler (iprot,oprot) (name,typ,seqid)" << endl;
-  indent(f_service_) << "T.readMessageEnd iprot" << endl;
-  indent(f_service_) << "P.return P.True" << endl;
-  indent_down();
-}
-
-bool hasNoArguments(t_function* func) {
-  return (func->get_arglist()->get_members().empty());
-}
-
-string t_hs_generator::render_hs_type_for_function_name(t_type* type) {
-  string type_str = render_hs_type(type, false);
-  std::string::size_type found = -1;
-
-  while (true) {
-    found = type_str.find_first_of("[]. ", found + 1);
-    if (string::npos == size_t(found)) {
-      break;
-    }
-
-    if (type_str[found] == '.')
-      type_str[found] = '_';
-    else
-      type_str[found] = 'Z';
-  }
-  return type_str;
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_hs_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open function
-  string funname = decapitalize(tfunction->get_name());
-  indent(f_service_) << "process_" << funname << " (seqid, iprot, oprot, handler) = do" << endl;
-  indent_up();
-
-  string argsname = capitalize(tfunction->get_name()) + "_args";
-  string resultname = capitalize(tfunction->get_name()) + "_result";
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(f_service_) << "args <- read_" << argsname << " iprot" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  size_t n = xceptions.size() + 1;
-  // Try block for a function with exceptions
-  if (n > 0) {
-    for (size_t i = 0; i < n; i++) {
-      indent(f_service_) << "(X.catch" << endl;
-      indent_up();
-    }
-  }
-
-  if (n > 0) {
-    indent(f_service_) << "(do" << endl;
-    indent_up();
-  }
-  indent(f_service_);
-
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void())
-    f_service_ << "val <- ";
-
-  f_service_ << "Iface." << decapitalize(tfunction->get_name()) << " handler";
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
-    f_service_ << " (" << field_name(argsname, (*f_iter)->get_name()) << " args)";
-
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << endl;
-    indent(f_service_) << "let res = default_" << resultname << "{"
-                       << field_name(resultname, "success") << " = val}";
-
-  } else if (!tfunction->is_oneway()) {
-    f_service_ << endl;
-    indent(f_service_) << "let res = default_" << resultname;
-  }
-  f_service_ << endl;
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    indent(f_service_) << "P.return ()";
-  } else {
-    indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name()
-                       << "\", T.M_REPLY, seqid)" << endl;
-    indent(f_service_) << "write_" << resultname << " oprot res" << endl;
-    indent(f_service_) << "T.writeMessageEnd oprot" << endl;
-    indent(f_service_) << "T.tFlush (T.getTransport oprot)";
-  }
-  if (n > 0) {
-    f_service_ << ")";
-    indent_down();
-  }
-  f_service_ << endl;
-
-  if (n > 0) {
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      indent(f_service_) << "(\\e  -> do" << endl;
-      indent_up();
-
-      if (!tfunction->is_oneway()) {
-        indent(f_service_) << "let res = default_" << resultname << "{"
-                           << field_name(resultname, (*x_iter)->get_name()) << " = P.Just e}"
-                           << endl;
-        indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name()
-                           << "\", T.M_REPLY, seqid)" << endl;
-        indent(f_service_) << "write_" << resultname << " oprot res" << endl;
-        indent(f_service_) << "T.writeMessageEnd oprot" << endl;
-        indent(f_service_) << "T.tFlush (T.getTransport oprot)";
-      } else {
-        indent(f_service_) << "P.return ()";
-      }
-
-      f_service_ << "))" << endl;
-      indent_down();
-      indent_down();
-    }
-    indent(f_service_) << "((\\_ -> do" << endl;
-    indent_up();
-
-    if (!tfunction->is_oneway()) {
-      indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name()
-                         << "\", T.M_EXCEPTION, seqid)" << endl;
-      indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN \"\")" << endl;
-      indent(f_service_) << "T.writeMessageEnd oprot" << endl;
-      indent(f_service_) << "T.tFlush (T.getTransport oprot)";
-    } else {
-      indent(f_service_) << "P.return ()";
-    }
-
-    f_service_ << ") :: X.SomeException -> P.IO ()))" << endl;
-    indent_down();
-    indent_down();
-  }
-  // Close function
-  indent_down();
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_hs_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
-  (void)prefix;
-  t_type* type = tfield->get_type();
-  generate_deserialize_type(out, type, prefix);
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_hs_generator::generate_deserialize_type(ofstream& out, t_type* type, string arg) {
-  type = get_true_type(type);
-  string val = tmp("_val");
-  out << "(case " << arg << " of {" << type_to_constructor(type) << " " << val << " -> ";
-
-  if (type->is_void())
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE";
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, val);
-
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, val);
-
-  } else if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    if (tbase == t_base_type::TYPE_STRING && !((t_base_type*)type)->is_binary()) {
-      out << "E.decodeUtf8 ";
-    }
-    out << val;
-    if (((t_base_type*)type)->is_binary()) {
-      // Since wire type of binary is the same as string, we actually receive T.TString not
-      // T.TBinary
-      out << "; T.TString " << val << " -> " << val;
-    }
-  } else if (type->is_enum()) {
-    out << "P.toEnum $ P.fromIntegral " << val;
-
-  } else {
-    throw "DO NOT KNOW HOW TO DESERIALIZE TYPE " + type->get_name();
-  }
-  out << "; _ -> P.error \"wrong type\"})";
-}
-
-/**
- * Generates an unserializer for a struct, calling read()
- */
-void t_hs_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string name) {
-
-  out << "(" << type_name(tstruct, "to_") << " (T.TStruct " << name << "))";
-}
-
-/**
- * Serialize a container by writing out the header followed by
- * data and then a footer.
- */
-void t_hs_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string arg) {
-
-  string val = tmp("_v");
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    string key = tmp("_k");
-    out << "(Map.fromList $ P.map (\\(" << key << "," << val << ") -> (";
-    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type(), key);
-
-    out << ",";
-    generate_deserialize_type(out, ((t_map*)ttype)->get_val_type(), val);
-
-    out << ")) " << arg << ")";
-
-  } else if (ttype->is_set()) {
-    out << "(Set.fromList $ P.map (\\" << val << " -> ";
-    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type(), val);
-    out << ") " << arg << ")";
-
-  } else if (ttype->is_list()) {
-    out << "(Vector.fromList $ P.map (\\" << val << " -> ";
-    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type(), val);
-    out << ") " << arg << ")";
-  }
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_hs_generator::generate_serialize_type(ofstream& out, t_type* type, string name) {
-
-  type = get_true_type(type);
-  // Do nothing for void types
-  if (type->is_void())
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE";
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, name);
-
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, name);
-
-  } else if (type->is_base_type() || type->is_enum()) {
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      out << type_to_constructor(type) << " ";
-      if (tbase == t_base_type::TYPE_STRING && !((t_base_type*)type)->is_binary()) {
-        out << "$ E.encodeUtf8 ";
-      }
-      out << name;
-
-    } else if (type->is_enum()) {
-      string ename = capitalize(type->get_name());
-      out << "T.TI32 $ P.fromIntegral $ P.fromEnum " << name;
-    }
-
-  } else {
-    throw "DO NOT KNOW HOW TO SERIALIZE FIELD OF TYPE " + type->get_name();
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_hs_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  out << type_name(tstruct, "from_") << " " << prefix;
-}
-
-void t_hs_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  string k = tmp("_k");
-  string v = tmp("_v");
-
-  if (ttype->is_map()) {
-    t_type* ktype = ((t_map*)ttype)->get_key_type();
-    t_type* vtype = ((t_map*)ttype)->get_val_type();
-    out << "T.TMap " << type_to_enum(ktype) << " " << type_to_enum(vtype);
-    out << " $ P.map (\\(" << k << "," << v << ") -> (";
-    generate_serialize_type(out, ktype, k);
-    out << ", ";
-    generate_serialize_type(out, vtype, v);
-    out << ")) $ Map.toList " << prefix;
-
-  } else if (ttype->is_set()) {
-    out << "T.TSet " << type_to_enum(((t_list*)ttype)->get_elem_type());
-    out << " $ P.map (\\" << v << " -> ";
-    generate_serialize_type(out, ((t_list*)ttype)->get_elem_type(), v);
-    out << ") $ Set.toList " << prefix;
-
-  } else if (ttype->is_list()) {
-    out << "T.TList " << type_to_enum(((t_list*)ttype)->get_elem_type());
-    out << " $ P.map (\\" << v << " -> ";
-    generate_serialize_type(out, ((t_list*)ttype)->get_elem_type(), v);
-    out << ") $ Vector.toList " << prefix;
-  }
-}
-
-string t_hs_generator::function_type(t_function* tfunc, bool options, bool io, bool method) {
-  string result = "";
-
-  const vector<t_field*>& fields = tfunc->get_arglist()->get_members();
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_OPTIONAL
-        || ((t_type*)(*f_iter)->get_type())->is_xception())
-      result += "P.Maybe ";
-    result += render_hs_type((*f_iter)->get_type(), options);
-    result += " -> ";
-  }
-
-  if (fields.empty() && !method)
-    result += "() -> ";
-
-  if (io)
-    result += "P.IO ";
-
-  result += render_hs_type(tfunc->get_returntype(), io);
-  return result;
-}
-
-string t_hs_generator::type_name(t_type* ttype, string function_prefix) {
-  string prefix = "";
-  t_program* program = ttype->get_program();
-
-  if (program != NULL && program != program_)
-    if (!ttype->is_service())
-      prefix = capitalize(program->get_name()) + "_Types.";
-
-  return prefix + function_prefix + capitalize(ttype->get_name());
-}
-
-string t_hs_generator::field_name(string tname, string fname) {
-  return decapitalize(tname) + "_" + fname;
-}
-
-/**
- * Converts the parse type to a Protocol.t_type enum
- */
-string t_hs_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      return "T.T_VOID";
-    case t_base_type::TYPE_STRING:
-      return ((t_base_type*)type)->is_binary() ? "T.T_BINARY" : "T.T_STRING";
-    case t_base_type::TYPE_BOOL:
-      return "T.T_BOOL";
-    case t_base_type::TYPE_I8:
-      return "T.T_BYTE";
-    case t_base_type::TYPE_I16:
-      return "T.T_I16";
-    case t_base_type::TYPE_I32:
-      return "T.T_I32";
-    case t_base_type::TYPE_I64:
-      return "T.T_I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "T.T_DOUBLE";
-    }
-
-  } else if (type->is_enum()) {
-    return "T.T_I32";
-
-  } else if (type->is_struct() || type->is_xception()) {
-    return "(T.T_STRUCT " + type_name((t_struct*)type, "typemap_") + ")";
-
-  } else if (type->is_map()) {
-    string ktype = type_to_enum(((t_map*)type)->get_key_type());
-    string vtype = type_to_enum(((t_map*)type)->get_val_type());
-    return "(T.T_MAP " + ktype + " " + vtype + ")";
-
-  } else if (type->is_set()) {
-    return "(T.T_SET " + type_to_enum(((t_list*)type)->get_elem_type()) + ")";
-
-  } else if (type->is_list()) {
-    return "(T.T_LIST " + type_to_enum(((t_list*)type)->get_elem_type()) + ")";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-/**
- * Converts the parse type to a default value
- */
-string t_hs_generator::type_to_default(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      return "P.error \"No default value for type T_VOID\"";
-    case t_base_type::TYPE_STRING:
-      return "\"\"";
-    case t_base_type::TYPE_BOOL:
-      return "P.False";
-    case t_base_type::TYPE_I8:
-      return "0";
-    case t_base_type::TYPE_I16:
-      return "0";
-    case t_base_type::TYPE_I32:
-      return "0";
-    case t_base_type::TYPE_I64:
-      return "0";
-    case t_base_type::TYPE_DOUBLE:
-      return "0";
-    }
-
-  } else if (type->is_enum()) {
-    return "(P.toEnum 0)";
-
-  } else if (type->is_struct() || type->is_xception()) {
-    return type_name((t_struct*)type, "default_");
-
-  } else if (type->is_map()) {
-    return "Map.empty";
-
-  } else if (type->is_set()) {
-    return "Set.empty";
-
-  } else if (type->is_list()) {
-    return "Vector.empty";
-  }
-
-  throw "INVALID TYPE IN type_to_default: " + type->get_name();
-}
-
-/**
- * Converts the parse type to an haskell type
- */
-string t_hs_generator::render_hs_type(t_type* type, bool needs_parens) {
-  type = get_true_type(type);
-  string type_repr;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      return "()";
-    case t_base_type::TYPE_STRING:
-      return (((t_base_type*)type)->is_binary() ? "LBS.ByteString" : "LT.Text");
-    case t_base_type::TYPE_BOOL:
-      return "P.Bool";
-    case t_base_type::TYPE_I8:
-      return "I.Int8";
-    case t_base_type::TYPE_I16:
-      return "I.Int16";
-    case t_base_type::TYPE_I32:
-      return "I.Int32";
-    case t_base_type::TYPE_I64:
-      return "I.Int64";
-    case t_base_type::TYPE_DOUBLE:
-      return "P.Double";
-    }
-
-  } else if (type->is_enum()) {
-    return type_name((t_enum*)type);
-
-  } else if (type->is_struct() || type->is_xception()) {
-    return type_name((t_struct*)type);
-
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    type_repr = "Map.HashMap " + render_hs_type(ktype, true) + " " + render_hs_type(vtype, true);
-
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    type_repr = "Set.HashSet " + render_hs_type(etype, true);
-
-  } else if (type->is_list()) {
-    t_type* etype = ((t_list*)type)->get_elem_type();
-    type_repr = "Vector.Vector " + render_hs_type(etype, true);
-
-  } else {
-    throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-  }
-
-  return needs_parens ? "(" + type_repr + ")" : type_repr;
-}
-
-/**
- * Converts the parse type to a haskell constructor
- */
-string t_hs_generator::type_to_constructor(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "invalid type: T_VOID";
-    case t_base_type::TYPE_STRING:
-      return ((t_base_type*)type)->is_binary() ? "T.TBinary" : "T.TString";
-    case t_base_type::TYPE_BOOL:
-      return "T.TBool";
-    case t_base_type::TYPE_I8:
-      return "T.TByte";
-    case t_base_type::TYPE_I16:
-      return "T.TI16";
-    case t_base_type::TYPE_I32:
-      return "T.TI32";
-    case t_base_type::TYPE_I64:
-      return "T.TI64";
-    case t_base_type::TYPE_DOUBLE:
-      return "T.TDouble";
-    }
-
-  } else if (type->is_enum()) {
-    return "T.TI32";
-
-  } else if (type->is_struct() || type->is_xception()) {
-    return "T.TStruct";
-
-  } else if (type->is_map()) {
-    return "T.TMap _ _";
-
-  } else if (type->is_set()) {
-    return "T.TSet _";
-
-  } else if (type->is_list()) {
-    return "T.TList _";
-  }
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-THRIFT_REGISTER_GENERATOR(hs, "Haskell", "")


[40/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_gv_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_gv_generator.cc b/compiler/cpp/src/generate/t_gv_generator.cc
deleted file mode 100644
index 61be8e6..0000000
--- a/compiler/cpp/src/generate/t_gv_generator.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <map>
-#include <list>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::pair;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Graphviz code generator
- */
-class t_gv_generator : public t_generator {
-public:
-  t_gv_generator(t_program* program,
-                 const std::map<std::string, std::string>& parsed_options,
-                 const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    exception_arrows = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("exceptions") == 0) {
-        exception_arrows = true;
-      } else {
-        throw "unknown option gv:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-gv";
-  }
-
-  /**
-   * Init and end of generator
-   */
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_service(t_service* tservice);
-
-protected:
-  /**
-   * Helpers
-   */
-  void print_type(t_type* ttype, string struct_field_ref);
-  void print_const_value(t_type* type, t_const_value* tvalue);
-
-private:
-  std::ofstream f_out_;
-  std::list<string> edges;
-  bool exception_arrows;
-};
-
-/**
- * Init generator:
- * - Adds some escaping for the Graphviz domain.
- * - Create output directory and open file for writting.
- * - Write the file header.
- */
-void t_gv_generator::init_generator() {
-  escape_['{'] = "\\{";
-  escape_['}'] = "\\}";
-
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  string fname = get_out_dir() + program_->get_name() + ".gv";
-  f_out_.open(fname.c_str());
-  f_out_ << "digraph \"" << escape_string(program_name_) << "\" {" << endl;
-  f_out_ << "node [style=filled, shape=record];" << endl;
-  f_out_ << "edge [arrowsize=0.5];" << endl;
-  f_out_ << "rankdir=LR" << endl;
-}
-
-/**
- * Closes generator:
- * - Print accumulated nodes connections.
- * - Print footnote.
- * - Closes file.
- */
-void t_gv_generator::close_generator() {
-  // Print edges
-  std::list<string>::iterator iter = edges.begin();
-  for (; iter != edges.end(); iter++) {
-    f_out_ << (*iter) << endl;
-  }
-
-  // Print graph end } and close file
-  f_out_ << "}" << endl;
-  f_out_.close();
-}
-
-void t_gv_generator::generate_typedef(t_typedef* ttypedef) {
-  string name = ttypedef->get_name();
-  f_out_ << "node [fillcolor=azure];" << endl;
-  f_out_ << name << " [label=\"";
-
-  f_out_ << escape_string(name);
-  f_out_ << " :: ";
-  print_type(ttypedef->get_type(), name);
-
-  f_out_ << "\"];" << endl;
-}
-
-void t_gv_generator::generate_enum(t_enum* tenum) {
-  string name = tenum->get_name();
-  f_out_ << "node [fillcolor=white];" << endl;
-  f_out_ << name << " [label=\"enum " << escape_string(name);
-
-  vector<t_enum_value*> values = tenum->get_constants();
-  vector<t_enum_value*>::iterator val_iter;
-  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
-    f_out_ << '|' << (*val_iter)->get_name();
-    f_out_ << " = ";
-    f_out_ << (*val_iter)->get_value();
-  }
-
-  f_out_ << "\"];" << endl;
-}
-
-void t_gv_generator::generate_const(t_const* tconst) {
-  string name = tconst->get_name();
-
-  f_out_ << "node [fillcolor=aliceblue];" << endl;
-  f_out_ << "const_" << name << " [label=\"";
-
-  f_out_ << escape_string(name);
-  f_out_ << " = ";
-  print_const_value(tconst->get_type(), tconst->get_value());
-  f_out_ << " :: ";
-  print_type(tconst->get_type(), "const_" + name);
-
-  f_out_ << "\"];" << endl;
-}
-
-void t_gv_generator::generate_struct(t_struct* tstruct) {
-  string name = tstruct->get_name();
-
-  if (tstruct->is_xception()) {
-    f_out_ << "node [fillcolor=lightpink];" << endl;
-    f_out_ << name << " [label=\"";
-    f_out_ << "exception " << escape_string(name);
-  } else if (tstruct->is_union()) {
-    f_out_ << "node [fillcolor=lightcyan];" << endl;
-    f_out_ << name << " [label=\"";
-    f_out_ << "union " << escape_string(name);
-  } else {
-    f_out_ << "node [fillcolor=beige];" << endl;
-    f_out_ << name << " [label=\"";
-    f_out_ << "struct " << escape_string(name);
-  }
-
-  vector<t_field*> members = tstruct->get_members();
-  vector<t_field*>::iterator mem_iter = members.begin();
-  for (; mem_iter != members.end(); mem_iter++) {
-    string field_name = (*mem_iter)->get_name();
-
-    // print port (anchor reference)
-    f_out_ << "|<field_" << field_name << '>';
-
-    // field name :: field type
-    f_out_ << (*mem_iter)->get_name();
-    f_out_ << " :: ";
-    print_type((*mem_iter)->get_type(), name + ":field_" + field_name);
-  }
-
-  f_out_ << "\"];" << endl;
-}
-
-void t_gv_generator::print_type(t_type* ttype, string struct_field_ref) {
-  if (ttype->is_container()) {
-    if (ttype->is_list()) {
-      f_out_ << "list\\<";
-      print_type(((t_list*)ttype)->get_elem_type(), struct_field_ref);
-      f_out_ << "\\>";
-    } else if (ttype->is_set()) {
-      f_out_ << "set\\<";
-      print_type(((t_set*)ttype)->get_elem_type(), struct_field_ref);
-      f_out_ << "\\>";
-    } else if (ttype->is_map()) {
-      f_out_ << "map\\<";
-      print_type(((t_map*)ttype)->get_key_type(), struct_field_ref);
-      f_out_ << ", ";
-      print_type(((t_map*)ttype)->get_val_type(), struct_field_ref);
-      f_out_ << "\\>";
-    }
-  } else if (ttype->is_base_type()) {
-    f_out_ << (((t_base_type*)ttype)->is_binary() ? "binary" : ttype->get_name());
-  } else {
-    f_out_ << ttype->get_name();
-    edges.push_back(struct_field_ref + " -> " + ttype->get_name());
-  }
-}
-
-/**
- * Prints out an string representation of the provided constant value
- */
-void t_gv_generator::print_const_value(t_type* type, t_const_value* tvalue) {
-  bool first = true;
-  switch (tvalue->get_type()) {
-  case t_const_value::CV_INTEGER:
-    f_out_ << tvalue->get_integer();
-    break;
-  case t_const_value::CV_DOUBLE:
-    f_out_ << tvalue->get_double();
-    break;
-  case t_const_value::CV_STRING:
-    f_out_ << "\\\"" << get_escaped_string(tvalue) << "\\\"";
-    break;
-  case t_const_value::CV_MAP: {
-    f_out_ << "\\{ ";
-    map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
-    map<t_const_value*, t_const_value*>::iterator map_iter;
-    for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
-      if (!first) {
-        f_out_ << ", ";
-      }
-      first = false;
-      print_const_value(((t_map*)type)->get_key_type(), map_iter->first);
-      f_out_ << " = ";
-      print_const_value(((t_map*)type)->get_val_type(), map_iter->second);
-    }
-    f_out_ << " \\}";
-  } break;
-  case t_const_value::CV_LIST: {
-    f_out_ << "\\{ ";
-    vector<t_const_value*> list_elems = tvalue->get_list();
-    ;
-    vector<t_const_value*>::iterator list_iter;
-    for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
-      if (!first) {
-        f_out_ << ", ";
-      }
-      first = false;
-      if (type->is_list()) {
-        print_const_value(((t_list*)type)->get_elem_type(), *list_iter);
-      } else {
-        print_const_value(((t_set*)type)->get_elem_type(), *list_iter);
-      }
-    }
-    f_out_ << " \\}";
-  } break;
-  case t_const_value::CV_IDENTIFIER:
-    f_out_ << escape_string(type->get_name()) << "."
-           << escape_string(tvalue->get_identifier_name());
-    break;
-  default:
-    f_out_ << "UNKNOWN";
-    break;
-  }
-}
-
-void t_gv_generator::generate_service(t_service* tservice) {
-  string service_name = get_service_name(tservice);
-  f_out_ << "subgraph cluster_" << service_name << " {" << endl;
-  f_out_ << "node [fillcolor=bisque];" << endl;
-  f_out_ << "style=dashed;" << endl;
-  f_out_ << "label = \"" << escape_string(service_name) << " service\";" << endl;
-
-  // TODO: service extends
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator fn_iter = functions.begin();
-  for (; fn_iter != functions.end(); fn_iter++) {
-    string fn_name = (*fn_iter)->get_name();
-
-    f_out_ << "function_" << service_name << fn_name;
-    f_out_ << "[label=\"<return_type>function " << escape_string(fn_name);
-    f_out_ << " :: ";
-    print_type((*fn_iter)->get_returntype(), "function_" + service_name + fn_name + ":return_type");
-
-    vector<t_field*> args = (*fn_iter)->get_arglist()->get_members();
-    vector<t_field*>::iterator arg_iter = args.begin();
-    for (; arg_iter != args.end(); arg_iter++) {
-      f_out_ << "|<param_" << (*arg_iter)->get_name() << ">";
-      f_out_ << (*arg_iter)->get_name();
-      if ((*arg_iter)->get_value() != NULL) {
-        f_out_ << " = ";
-        print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value());
-      }
-      f_out_ << " :: ";
-      print_type((*arg_iter)->get_type(),
-                 "function_" + service_name + fn_name + ":param_" + (*arg_iter)->get_name());
-    }
-    // end of node
-    f_out_ << "\"];" << endl;
-
-    // Exception edges
-    if (exception_arrows) {
-      vector<t_field*> excepts = (*fn_iter)->get_xceptions()->get_members();
-      vector<t_field*>::iterator ex_iter = excepts.begin();
-      for (; ex_iter != excepts.end(); ex_iter++) {
-        edges.push_back("function_" + service_name + fn_name + " -> "
-                        + (*ex_iter)->get_type()->get_name() + " [color=red]");
-      }
-    }
-  }
-
-  f_out_ << " }" << endl;
-}
-
-THRIFT_REGISTER_GENERATOR(
-    gv,
-    "Graphviz",
-    "    exceptions:      Whether to draw arrows from functions to exception.\n")


[52/55] [abbrv] thrift git commit: THRIFT-3839 Performance issue with big message deserialization using php extension

Posted by ns...@apache.org.
THRIFT-3839 Performance issue with big message deserialization using php extension

This closes #1014


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/dd9885e3
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/dd9885e3
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/dd9885e3

Branch: refs/heads/master
Commit: dd9885e3225180cc12cdfb7bfddc4b3cdbd405fe
Parents: eacbd65
Author: myroslav.kosinskyi <my...@skelia.com.ua>
Authored: Mon May 23 11:16:12 2016 +0300
Committer: Nobuaki Sukegawa <ns...@apache.org>
Committed: Mon Sep 26 01:42:02 2016 +0900

----------------------------------------------------------------------
 lib/php/lib/Thrift/Serializer/TBinarySerializer.php  |  5 +++--
 lib/php/lib/Thrift/Transport/TMemoryBuffer.php       |  5 +++++
 .../src/ext/thrift_protocol/php_thrift_protocol.cpp  | 15 +++++++++++++--
 .../src/ext/thrift_protocol/php_thrift_protocol7.cpp |  7 ++++---
 4 files changed, 25 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/dd9885e3/lib/php/lib/Thrift/Serializer/TBinarySerializer.php
----------------------------------------------------------------------
diff --git a/lib/php/lib/Thrift/Serializer/TBinarySerializer.php b/lib/php/lib/Thrift/Serializer/TBinarySerializer.php
index 7e0cf8b..aa2f71b 100644
--- a/lib/php/lib/Thrift/Serializer/TBinarySerializer.php
+++ b/lib/php/lib/Thrift/Serializer/TBinarySerializer.php
@@ -57,7 +57,7 @@ class TBinarySerializer
     return $transport->getBuffer();
   }
 
-  public static function deserialize($string_object, $class_name)
+  public static function deserialize($string_object, $class_name, $buffer_size  = 8192)
   {
      $transport = new TMemoryBuffer();
      $protocol = new TBinaryProtocolAccelerated($transport);
@@ -72,7 +72,8 @@ class TBinarySerializer
        $protocolTransport->flush();
 
        return thrift_protocol_read_binary($protocol, $class_name,
-                                          $protocol->isStrictRead());
+                                          $protocol->isStrictRead(),
+                                          $buffer_size);
      } else {
        $transport->write($string_object);
        $object = new $class_name();

http://git-wip-us.apache.org/repos/asf/thrift/blob/dd9885e3/lib/php/lib/Thrift/Transport/TMemoryBuffer.php
----------------------------------------------------------------------
diff --git a/lib/php/lib/Thrift/Transport/TMemoryBuffer.php b/lib/php/lib/Thrift/Transport/TMemoryBuffer.php
index 5fc26bf..ca31c57 100644
--- a/lib/php/lib/Thrift/Transport/TMemoryBuffer.php
+++ b/lib/php/lib/Thrift/Transport/TMemoryBuffer.php
@@ -92,4 +92,9 @@ class TMemoryBuffer extends TTransport
   {
     return TStringFuncFactory::create()->strlen($this->buf_);
   }
+
+  public function putBack($data)
+  {
+    $this->buf_ = $data.$this->buf_;
+  }
 }

http://git-wip-us.apache.org/repos/asf/thrift/blob/dd9885e3/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
----------------------------------------------------------------------
diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
index 65cfb16..a0de645 100644
--- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
+++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
@@ -994,7 +994,7 @@ PHP_FUNCTION(thrift_protocol_write_binary) {
   }
 }
 
-// 3 params: $transport $response_Typename $strict_read
+// 4 params: $transport $response_Typename $strict_read $buffer_size
 PHP_FUNCTION(thrift_protocol_read_binary) {
   int argc = ZEND_NUM_ARGS();
 
@@ -1017,8 +1017,19 @@ PHP_FUNCTION(thrift_protocol_read_binary) {
     RETURN_NULL();
   }
 
+  if (argc == 4 && Z_TYPE_PP(args[3]) != IS_LONG) {
+    php_error_docref(NULL TSRMLS_CC, E_ERROR, "4nd parameter is not an integer (typename of expected buffer size)");
+    efree(args);
+    RETURN_NULL();
+  }
+
   try {
-    PHPInputTransport transport(*args[0]);
+    size_t buffer_size = 8192;
+    if (argc == 4) {
+      buffer_size = Z_LVAL_PP(args[3]);
+    }
+
+    PHPInputTransport transport(*args[0], buffer_size);
     char* obj_typename = Z_STRVAL_PP(args[1]);
     convert_to_boolean(*args[2]);
     bool strict_read = Z_BVAL_PP(args[2]);

http://git-wip-us.apache.org/repos/asf/thrift/blob/dd9885e3/lib/php/src/ext/thrift_protocol/php_thrift_protocol7.cpp
----------------------------------------------------------------------
diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol7.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol7.cpp
index e482762..c4c76cf 100644
--- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol7.cpp
+++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol7.cpp
@@ -959,18 +959,19 @@ PHP_FUNCTION(thrift_protocol_write_binary) {
 }
 
 
-// 3 params: $transport $response_typename $strict_read
+// 4 params: $transport $response_Typename $strict_read $buffer_size
 PHP_FUNCTION(thrift_protocol_read_binary) {
   zval *protocol;
   zend_string *obj_typename;
   zend_bool strict_read;
+  size_t buffer_size = 8192;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "oSb", &protocol, &obj_typename, &strict_read) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "oSb|l", &protocol, &obj_typename, &strict_read, &buffer_size) == FAILURE) {
     return;
   }
 
   try {
-    PHPInputTransport transport(protocol);
+    PHPInputTransport transport(protocol, buffer_size);
     int8_t messageType = 0;
     int32_t sz = transport.readI32();
 


[11/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_hs_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc
new file mode 100644
index 0000000..a3ccd8d
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc
@@ -0,0 +1,1734 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+
+#include "thrift/platform.h"
+#include "thrift/version.h"
+
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Haskell code generator.
+ *
+ */
+class t_hs_generator : public t_oop_generator {
+public:
+  t_hs_generator(t_program* program,
+                 const map<string, string>& parsed_options,
+                 const string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option hs:" + iter->first;
+    }
+
+    out_dir_base_ = "gen-hs";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  string render_const_value(t_type* type, t_const_value* value);
+
+  /**
+   * Struct generation code
+   */
+
+  void generate_hs_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_hs_struct_definition(ofstream& out,
+                                     t_struct* tstruct,
+                                     bool is_xception = false,
+                                     bool helper = false);
+
+  void generate_hs_struct_reader(ofstream& out, t_struct* tstruct);
+
+  void generate_hs_struct_writer(ofstream& out, t_struct* tstruct);
+
+  void generate_hs_struct_arbitrary(ofstream& out, t_struct* tstruct);
+
+  void generate_hs_function_helpers(t_function* tfunction);
+
+  void generate_hs_typemap(ofstream& out, t_struct* tstruct);
+
+  void generate_hs_default(ofstream& out, t_struct* tstruct);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(ofstream& out, t_field* tfield, string prefix);
+
+  void generate_deserialize_struct(ofstream& out, t_struct* tstruct, string name = "");
+
+  void generate_deserialize_container(ofstream& out, t_type* ttype, string arg = "");
+
+  void generate_deserialize_set_element(ofstream& out, t_set* tset);
+
+  void generate_deserialize_list_element(ofstream& out, t_list* tlist, string prefix = "");
+
+  void generate_deserialize_type(ofstream& out, t_type* type, string arg = "");
+
+  void generate_serialize_type(ofstream& out, t_type* type, string name = "");
+
+  void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix = "");
+
+  void generate_serialize_container(ofstream& out, t_type* ttype, string prefix = "");
+
+  void generate_serialize_map_element(ofstream& out, t_map* tmap, string kiter, string viter);
+
+  void generate_serialize_set_element(ofstream& out, t_set* tmap, string iter);
+
+  void generate_serialize_list_element(ofstream& out, t_list* tlist, string iter);
+
+  /**
+   * Helper rendering functions
+   */
+
+  string hs_autogen_comment();
+  string hs_language_pragma();
+  string hs_imports();
+
+  string type_name(t_type* ttype, string function_prefix = "");
+
+  string field_name(string tname, string fname);
+
+  string function_type(t_function* tfunc,
+                       bool options = false,
+                       bool io = false,
+                       bool method = false);
+
+  string type_to_enum(t_type* ttype);
+
+  string type_to_default(t_type* ttype);
+
+  string render_hs_type(t_type* type, bool needs_parens);
+
+  string type_to_constructor(t_type* ttype);
+
+  string render_hs_type_for_function_name(t_type* type);
+
+private:
+  ofstream f_types_;
+  ofstream f_consts_;
+  ofstream f_service_;
+  ofstream f_iface_;
+  ofstream f_client_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_hs_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  // Make output file
+  string pname = capitalize(program_name_);
+  string f_types_name = get_out_dir() + pname + "_Types.hs";
+  f_types_.open(f_types_name.c_str());
+
+  string f_consts_name = get_out_dir() + pname + "_Consts.hs";
+  f_consts_.open(f_consts_name.c_str());
+
+  // Print header
+  f_types_ << hs_language_pragma() << endl;
+  f_types_ << hs_autogen_comment() << endl;
+  f_types_ << "module " << pname << "_Types where" << endl;
+  f_types_ << hs_imports() << endl;
+
+  f_consts_ << hs_language_pragma() << endl;
+  f_consts_ << hs_autogen_comment() << endl;
+  f_consts_ << "module " << pname << "_Consts where" << endl;
+  f_consts_ << hs_imports() << endl;
+  f_consts_ << "import " << pname << "_Types" << endl;
+}
+
+string t_hs_generator::hs_language_pragma() {
+  return string(
+      "{-# LANGUAGE DeriveDataTypeable #-}\n"
+      "{-# LANGUAGE DeriveGeneric #-}\n"
+      "{-# LANGUAGE OverloadedStrings #-}\n"
+      "{-# OPTIONS_GHC -fno-warn-missing-fields #-}\n"
+      "{-# OPTIONS_GHC -fno-warn-missing-signatures #-}\n"
+      "{-# OPTIONS_GHC -fno-warn-name-shadowing #-}\n"
+      "{-# OPTIONS_GHC -fno-warn-unused-imports #-}\n"
+      "{-# OPTIONS_GHC -fno-warn-unused-matches #-}\n");
+}
+
+/**
+ * Autogen'd comment
+ */
+string t_hs_generator::hs_autogen_comment() {
+  return string("-----------------------------------------------------------------\n")
+         + "-- Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")                      --\n"
+         + "--                                                             --\n"
+         + "-- DO NOT EDIT UNLESS YOU ARE SURE YOU KNOW WHAT YOU ARE DOING --\n"
+         + "-----------------------------------------------------------------\n";
+}
+
+/**
+ * Prints standard thrift imports
+ */
+string t_hs_generator::hs_imports() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = string(
+      "import Prelude (($), (.), (>>=), (==), (++))\n"
+      "import qualified Prelude as P\n"
+      "import qualified Control.Exception as X\n"
+      "import qualified Control.Monad as M ( liftM, ap, when )\n"
+      "import Data.Functor ( (<$>) )\n"
+      "import qualified Data.ByteString.Lazy as LBS\n"
+      "import qualified Data.Hashable as H\n"
+      "import qualified Data.Int as I\n"
+      "import qualified Data.Maybe as M (catMaybes)\n"
+      "import qualified Data.Text.Lazy.Encoding as E ( decodeUtf8, encodeUtf8 )\n"
+      "import qualified Data.Text.Lazy as LT\n"
+      "import qualified GHC.Generics as G (Generic)\n"
+      "import qualified Data.Typeable as TY ( Typeable )\n"
+      "import qualified Data.HashMap.Strict as Map\n"
+      "import qualified Data.HashSet as Set\n"
+      "import qualified Data.Vector as Vector\n"
+      "import qualified Test.QuickCheck.Arbitrary as QC ( Arbitrary(..) )\n"
+      "import qualified Test.QuickCheck as QC ( elements )\n"
+      "\n"
+      "import qualified Thrift as T\n"
+      "import qualified Thrift.Types as T\n"
+      "import qualified Thrift.Arbitraries as T\n"
+      "\n");
+
+  for (size_t i = 0; i < includes.size(); ++i)
+    result += "import qualified " + capitalize(includes[i]->get_name()) + "_Types\n";
+
+  if (includes.size() > 0)
+    result += "\n";
+
+  return result;
+}
+
+/**
+ * Closes the type files
+ */
+void t_hs_generator::close_generator() {
+  // Close types file
+  f_types_.close();
+  f_consts_.close();
+}
+
+/**
+ * Generates a typedef. Ez.
+ *
+ * @param ttypedef The type definition
+ */
+void t_hs_generator::generate_typedef(t_typedef* ttypedef) {
+  string tname = capitalize(ttypedef->get_symbolic());
+  string tdef = render_hs_type(ttypedef->get_type(), false);
+  indent(f_types_) << "type " << tname << " = " << tdef << endl;
+  f_types_ << endl;
+}
+
+/**
+ * Generates code for an enumerated type.
+ * the values.
+ *
+ * @param tenum The enumeration
+ */
+void t_hs_generator::generate_enum(t_enum* tenum) {
+  indent(f_types_) << "data " << capitalize(tenum->get_name()) << " = ";
+  indent_up();
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+
+  bool first = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    string name = capitalize((*c_iter)->get_name());
+    f_types_ << (first ? "" : "|");
+    f_types_ << name;
+    first = false;
+  }
+  indent(f_types_) << "deriving (P.Show, P.Eq, G.Generic, TY.Typeable, P.Ord, P.Bounded)" << endl;
+  indent_down();
+
+  string ename = capitalize(tenum->get_name());
+
+  indent(f_types_) << "instance P.Enum " << ename << " where" << endl;
+  indent_up();
+  indent(f_types_) << "fromEnum t = case t of" << endl;
+  indent_up();
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    string name = capitalize((*c_iter)->get_name());
+    indent(f_types_) << name << " -> " << value << endl;
+  }
+  indent_down();
+  indent(f_types_) << "toEnum t = case t of" << endl;
+  indent_up();
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    string name = capitalize((*c_iter)->get_name());
+    indent(f_types_) << value << " -> " << name << endl;
+  }
+  indent(f_types_) << "_ -> X.throw T.ThriftException" << endl;
+  indent_down();
+  indent_down();
+
+  indent(f_types_) << "instance H.Hashable " << ename << " where" << endl;
+  indent_up();
+  indent(f_types_) << "hashWithSalt salt = H.hashWithSalt salt P.. P.fromEnum" << endl;
+  indent_down();
+
+  indent(f_types_) << "instance QC.Arbitrary " << ename << " where" << endl;
+  indent_up();
+  indent(f_types_) << "arbitrary = QC.elements (P.enumFromTo P.minBound P.maxBound)" << endl;
+  indent_down();
+}
+
+/**
+ * Generate a constant value
+ */
+void t_hs_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = decapitalize(tconst->get_name());
+
+  t_const_value* value = tconst->get_value();
+
+  indent(f_consts_) << name << " :: " << render_hs_type(type, false) << endl;
+  indent(f_consts_) << name << " = " << render_const_value(type, value) << endl;
+  f_consts_ << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_hs_generator::render_const_value(t_type* type, t_const_value* value) {
+  if (value == NULL)
+    return type_to_default(type);
+
+  type = get_true_type(type);
+  ostringstream out;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+
+    case t_base_type::TYPE_STRING:
+      out << '"' << get_escaped_string(value) << '"';
+      break;
+
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "P.True" : "P.False");
+      break;
+
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << "(" << value->get_integer() << ")";
+      break;
+
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << "(" << value->get_integer() << ")";
+      } else {
+        out << "(" << value->get_double() << ")";
+      }
+      break;
+
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+
+  } else if (type->is_enum()) {
+    t_enum* tenum = (t_enum*)type;
+    vector<t_enum_value*> constants = tenum->get_constants();
+    for (vector<t_enum_value*>::iterator c_iter = constants.begin(); c_iter != constants.end();
+         ++c_iter) {
+      int val = (*c_iter)->get_value();
+      if (val == value->get_integer()) {
+        t_program* prog = type->get_program();
+        if (prog != NULL && prog != program_)
+          out << capitalize(prog->get_name()) << "_Types.";
+        out << capitalize((*c_iter)->get_name());
+        break;
+      }
+    }
+
+  } else if (type->is_struct() || type->is_xception()) {
+    string cname = type_name(type);
+    out << "default_" << cname << "{";
+
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+
+    bool first = true;
+    for (map<t_const_value*, t_const_value*>::const_iterator v_iter = val.begin();
+         v_iter != val.end();
+         ++v_iter) {
+      t_field* field = NULL;
+
+      for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end();
+           ++f_iter)
+        if ((*f_iter)->get_name() == v_iter->first->get_string())
+          field = (*f_iter);
+
+      if (field == NULL)
+        throw "type error: " + cname + " has no field " + v_iter->first->get_string();
+
+      string fname = v_iter->first->get_string();
+      string const_value = render_const_value(field->get_type(), v_iter->second);
+
+      out << (first ? "" : ", ");
+      out << field_name(cname, fname) << " = ";
+      if (field->get_req() == t_field::T_OPTIONAL || ((t_type*)field->get_type())->is_xception()) {
+        out << "P.Just ";
+      }
+      out << const_value;
+      first = false;
+    }
+
+    out << "}";
+
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+
+    out << "(Map.fromList [";
+
+    bool first = true;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(ktype, v_iter->first);
+      string val = render_const_value(vtype, v_iter->second);
+      out << (first ? "" : ",");
+      out << "(" << key << "," << val << ")";
+      first = false;
+    }
+    out << "])";
+
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype = type->is_list() ? ((t_list*)type)->get_elem_type()
+                                    : ((t_set*)type)->get_elem_type();
+
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+
+    if (type->is_set())
+      out << "(Set.fromList [";
+    else
+      out << "(Vector.fromList [";
+
+    bool first = true;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << (first ? "" : ",");
+      out << render_const_value(etype, *v_iter);
+      first = false;
+    }
+
+    out << "])";
+
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+
+  return out.str();
+}
+
+/**
+ * Generates a "struct"
+ */
+void t_hs_generator::generate_struct(t_struct* tstruct) {
+  generate_hs_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct, but also has an exception declaration.
+ *
+ * @param txception The struct definition
+ */
+void t_hs_generator::generate_xception(t_struct* txception) {
+  generate_hs_struct(txception, true);
+}
+
+/**
+ * Generates a Haskell struct
+ */
+void t_hs_generator::generate_hs_struct(t_struct* tstruct, bool is_exception) {
+  generate_hs_struct_definition(f_types_, tstruct, is_exception, false);
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_hs_generator::generate_hs_struct_definition(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   bool is_exception,
+                                                   bool helper) {
+  (void)helper;
+  string tname = type_name(tstruct);
+  string name = tstruct->get_name();
+  const vector<t_field*>& members = tstruct->get_members();
+
+  indent(out) << "data " << tname << " = " << tname;
+  if (members.size() > 0) {
+    indent_up();
+    bool first = true;
+    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
+         ++m_iter) {
+      if (first) {
+        indent(out) << "{ ";
+        first = false;
+      } else {
+        indent(out) << ", ";
+      }
+      string mname = (*m_iter)->get_name();
+      out << field_name(tname, mname) << " :: ";
+      if ((*m_iter)->get_req() == t_field::T_OPTIONAL
+          || ((t_type*)(*m_iter)->get_type())->is_xception()) {
+        out << "P.Maybe ";
+      }
+      out << render_hs_type((*m_iter)->get_type(), true) << endl;
+    }
+    indent(out) << "}";
+    indent_down();
+  }
+
+  out << " deriving (P.Show,P.Eq,G.Generic,TY.Typeable)" << endl;
+
+  if (is_exception)
+    out << "instance X.Exception " << tname << endl;
+
+  indent(out) << "instance H.Hashable " << tname << " where" << endl;
+  indent_up();
+  indent(out) << "hashWithSalt salt record = salt";
+  for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
+       ++m_iter) {
+    string mname = (*m_iter)->get_name();
+    indent(out) << " `H.hashWithSalt` " << field_name(tname, mname) << " record";
+  }
+  indent(out) << endl;
+  indent_down();
+
+  generate_hs_struct_arbitrary(out, tstruct);
+  generate_hs_struct_writer(out, tstruct);
+  generate_hs_struct_reader(out, tstruct);
+  generate_hs_typemap(out, tstruct);
+  generate_hs_default(out, tstruct);
+}
+
+void t_hs_generator::generate_hs_struct_arbitrary(ofstream& out, t_struct* tstruct) {
+  string tname = type_name(tstruct);
+  string name = tstruct->get_name();
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  indent(out) << "instance QC.Arbitrary " << tname << " where " << endl;
+  indent_up();
+  if (members.size() > 0) {
+    indent(out) << "arbitrary = M.liftM " << tname;
+    indent_up();
+    indent_up();
+    indent_up();
+    indent_up();
+    bool first = true;
+    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
+         ++m_iter) {
+      if (first) {
+        first = false;
+        out << " ";
+      } else {
+        indent(out) << "`M.ap`";
+      }
+      out << "(";
+      if ((*m_iter)->get_req() == t_field::T_OPTIONAL
+          || ((t_type*)(*m_iter)->get_type())->is_xception()) {
+        out << "M.liftM P.Just ";
+      }
+      out << "QC.arbitrary)" << endl;
+    }
+    indent_down();
+    indent_down();
+    indent_down();
+    indent_down();
+
+    // Shrink
+    indent(out) << "shrink obj | obj == default_" << tname << " = []" << endl;
+    indent(out) << "           | P.otherwise = M.catMaybes" << endl;
+    indent_up();
+    first = true;
+    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
+         ++m_iter) {
+      if (first) {
+        first = false;
+        indent(out) << "[ ";
+      } else {
+        indent(out) << ", ";
+      }
+      string fname = field_name(tname, (*m_iter)->get_name());
+      out << "if obj == default_" << tname;
+      out << "{" << fname << " = " << fname << " obj} ";
+      out << "then P.Nothing ";
+      out << "else P.Just $ default_" << tname;
+      out << "{" << fname << " = " << fname << " obj}" << endl;
+    }
+    indent(out) << "]" << endl;
+    indent_down();
+  } else { /* 0 == members.size() */
+    indent(out) << "arbitrary = QC.elements [" << tname << "]" << endl;
+  }
+  indent_down();
+}
+
+/**
+ * Generates the read method for a struct
+ */
+void t_hs_generator::generate_hs_struct_reader(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  string sname = type_name(tstruct);
+  string id = tmp("_id");
+  string val = tmp("_val");
+
+  indent(out) << "to_" << sname << " :: T.ThriftVal -> " << sname << endl;
+  indent(out) << "to_" << sname << " (T.TStruct fields) = " << sname << "{" << endl;
+  indent_up();
+
+  bool first = true;
+
+  // Generate deserialization code for known cases
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    int32_t key = (*f_iter)->get_key();
+    string etype = type_to_enum((*f_iter)->get_type());
+    string fname = (*f_iter)->get_name();
+
+    if (first) {
+      first = false;
+    } else {
+      out << "," << endl;
+    }
+
+    // Fill in Field
+    indent(out) << field_name(sname, fname) << " = ";
+
+    out << "P.maybe (";
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      out << "P.error \"Missing required field: " << fname << "\"";
+    } else {
+      if (((*f_iter)->get_req() == t_field::T_OPTIONAL
+           || ((t_type*)(*f_iter)->get_type())->is_xception()) && (*f_iter)->get_value() == NULL) {
+        out << "P.Nothing";
+      } else {
+        out << field_name(sname, fname) << " default_" << sname;
+      }
+    }
+    out << ") ";
+
+    out << "(\\(_," << val << ") -> ";
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL
+        || ((t_type*)(*f_iter)->get_type())->is_xception())
+      out << "P.Just ";
+    generate_deserialize_field(out, *f_iter, val);
+    out << ")";
+    out << " (Map.lookup (" << key << ") fields)";
+  }
+
+  out << endl;
+  indent(out) << "}" << endl;
+  indent_down();
+
+  // read
+  string tmap = type_name(tstruct, "typemap_");
+  indent(out) << "to_" << sname << " _ = P.error \"not a struct\"" << endl;
+
+  indent(out) << "read_" << sname << " :: (T.Transport t, T.Protocol p) => p t -> P.IO " << sname
+              << endl;
+  indent(out) << "read_" << sname << " iprot = to_" << sname;
+  out << " <$> T.readVal iprot (T.T_STRUCT " << tmap << ")" << endl;
+
+  indent(out) << "decode_" << sname
+              << " :: (T.Protocol p, T.Transport t) => p t -> LBS.ByteString -> " << sname << endl;
+  indent(out) << "decode_" << sname << " iprot bs = to_" << sname << " $ ";
+  out << "T.deserializeVal iprot (T.T_STRUCT " << tmap << ") bs" << endl;
+}
+
+void t_hs_generator::generate_hs_struct_writer(ofstream& out, t_struct* tstruct) {
+  string name = type_name(tstruct);
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+  string str = tmp("_str");
+  string f = tmp("_f");
+  string v = tmp("_v");
+
+  indent(out) << "from_" << name << " :: " << name << " -> T.ThriftVal" << endl;
+  indent(out) << "from_" << name << " record = T.TStruct $ Map.fromList ";
+  indent_up();
+
+  // Get Exceptions
+  bool hasExn = false;
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (((t_type*)(*f_iter)->get_type())->is_xception()) {
+      hasExn = true;
+      break;
+    }
+  }
+
+  bool isfirst = true;
+  if (hasExn) {
+    out << endl;
+    indent(out) << "(let exns = M.catMaybes ";
+    indent_up();
+    for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end();
+         ++f_iter) {
+      if (((t_type*)(*f_iter)->get_type())->is_xception()) {
+        if (isfirst) {
+          out << "[ ";
+          isfirst = false;
+        } else {
+          out << ", ";
+        }
+        string mname = (*f_iter)->get_name();
+        int32_t key = (*f_iter)->get_key();
+        out << "(\\" << v << " -> (" << key << ", (\"" << mname << "\",";
+        generate_serialize_type(out, (*f_iter)->get_type(), v);
+        out << "))) <$> " << field_name(name, mname) << " record";
+      }
+    }
+    if (!isfirst) {
+      out << "]" << endl;
+    }
+    indent_down();
+    indent(out) << "in if P.not (P.null exns) then exns else ";
+    indent_up();
+  } else {
+    out << "$ ";
+  }
+
+  out << "M.catMaybes" << endl;
+  // Get the Rest
+  isfirst = true;
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    // Write field header
+    if (isfirst) {
+      indent(out) << "[ ";
+      isfirst = false;
+    } else {
+      indent(out) << ", ";
+    }
+    string mname = (*f_iter)->get_name();
+    int32_t key = (*f_iter)->get_key();
+    out << "(\\";
+    out << v << " -> ";
+    if ((*f_iter)->get_req() != t_field::T_OPTIONAL
+        && !((t_type*)(*f_iter)->get_type())->is_xception()) {
+      out << "P.Just ";
+    }
+    out << "(" << key << ", (\"" << mname << "\",";
+    generate_serialize_type(out, (*f_iter)->get_type(), v);
+    out << "))) ";
+    if ((*f_iter)->get_req() != t_field::T_OPTIONAL
+        && !((t_type*)(*f_iter)->get_type())->is_xception()) {
+      out << "$";
+    } else {
+      out << "<$>";
+    }
+    out << " " << field_name(name, mname) << " record" << endl;
+  }
+
+  // Write the struct map
+  if (isfirst) {
+    indent(out) << "[]" << endl;
+  } else {
+    indent(out) << "]" << endl;
+  }
+  if (hasExn) {
+    indent(out) << ")" << endl;
+    indent_down();
+  }
+  indent_down();
+
+  // write
+  indent(out) << "write_" << name << " :: (T.Protocol p, T.Transport t) => p t -> " << name
+              << " -> P.IO ()" << endl;
+  indent(out) << "write_" << name << " oprot record = T.writeVal oprot $ from_";
+  out << name << " record" << endl;
+
+  // encode
+  indent(out) << "encode_" << name << " :: (T.Protocol p, T.Transport t) => p t -> " << name
+              << " -> LBS.ByteString" << endl;
+  indent(out) << "encode_" << name << " oprot record = T.serializeVal oprot $ ";
+  out << "from_" << name << " record" << endl;
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_hs_generator::generate_service(t_service* tservice) {
+  string f_service_name = get_out_dir() + capitalize(service_name_) + ".hs";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << hs_language_pragma() << endl;
+  f_service_ << hs_autogen_comment() << endl;
+  f_service_ << "module " << capitalize(service_name_) << " where" << endl;
+  f_service_ << hs_imports() << endl;
+
+  if (tservice->get_extends()) {
+    f_service_ << "import qualified " << capitalize(tservice->get_extends()->get_name()) << endl;
+  }
+
+  f_service_ << "import " << capitalize(program_name_) << "_Types" << endl;
+  f_service_ << "import qualified " << capitalize(service_name_) << "_Iface as Iface" << endl;
+
+  // Generate the three main parts of the service
+  generate_service_helpers(tservice);
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+
+  // Close service file
+  f_service_.close();
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_hs_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  indent(f_service_) << "-- HELPER FUNCTIONS AND STRUCTURES --" << endl;
+  indent(f_service_) << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_hs_struct_definition(f_service_, ts, false);
+    generate_hs_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_hs_generator::generate_hs_function_helpers(t_function* tfunction) {
+  t_struct result(program_, field_name(tfunction->get_name(), "result"));
+  t_field success(tfunction->get_returntype(), "success", 0);
+
+  if (!tfunction->get_returntype()->is_void())
+    result.append(&success);
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
+    result.append(*f_iter);
+
+  generate_hs_struct_definition(f_service_, &result, false);
+}
+
+/**
+ * Generate the map from field names to (type, id)
+ * @param tstruct the Struct
+ */
+void t_hs_generator::generate_hs_typemap(ofstream& out, t_struct* tstruct) {
+  string name = type_name(tstruct);
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "typemap_" << name << " :: T.TypeMap" << endl;
+  indent(out) << "typemap_" << name << " = Map.fromList [";
+  bool first = true;
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string mname = (*f_iter)->get_name();
+    if (!first) {
+      out << ",";
+    }
+
+    t_type* type = get_true_type((*f_iter)->get_type());
+    int32_t key = (*f_iter)->get_key();
+    out << "(" << key << ",(\"" << mname << "\"," << type_to_enum(type) << "))";
+    first = false;
+  }
+  out << "]" << endl;
+}
+
+/**
+ * generate the struct with default values filled in
+ * @param tstruct the Struct
+ */
+void t_hs_generator::generate_hs_default(ofstream& out, t_struct* tstruct) {
+  string name = type_name(tstruct);
+  string fname = type_name(tstruct, "default_");
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+
+  indent(out) << fname << " :: " << name << endl;
+  indent(out) << fname << " = " << name << "{" << endl;
+  indent_up();
+  bool first = true;
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string mname = (*f_iter)->get_name();
+    if (first) {
+      first = false;
+    } else {
+      out << "," << endl;
+    }
+
+    t_type* type = get_true_type((*f_iter)->get_type());
+    t_const_value* value = (*f_iter)->get_value();
+    indent(out) << field_name(name, mname) << " = ";
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL
+        || ((t_type*)(*f_iter)->get_type())->is_xception()) {
+      if (value == NULL) {
+        out << "P.Nothing";
+      } else {
+        out << "P.Just " << render_const_value(type, value);
+      }
+    } else {
+      out << render_const_value(type, value);
+    }
+  }
+  out << "}" << endl;
+  indent_down();
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_hs_generator::generate_service_interface(t_service* tservice) {
+  string f_iface_name = get_out_dir() + capitalize(service_name_) + "_Iface.hs";
+  f_iface_.open(f_iface_name.c_str());
+
+  f_iface_ << hs_language_pragma() << endl;
+  f_iface_ << hs_autogen_comment() << endl;
+
+  f_iface_ << "module " << capitalize(service_name_) << "_Iface where" << endl;
+
+  f_iface_ << hs_imports() << endl;
+  f_iface_ << "import " << capitalize(program_name_) << "_Types" << endl;
+  f_iface_ << endl;
+
+  string sname = capitalize(service_name_);
+  if (tservice->get_extends() != NULL) {
+    string extends = type_name(tservice->get_extends());
+
+    indent(f_iface_) << "import " << extends << "_Iface" << endl;
+    indent(f_iface_) << "class " << extends << "_Iface a => " << sname << "_Iface a where" << endl;
+
+  } else {
+    indent(f_iface_) << "class " << sname << "_Iface a where" << endl;
+  }
+
+  indent_up();
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string ft = function_type(*f_iter, true, true, true);
+    indent(f_iface_) << decapitalize((*f_iter)->get_name()) << " :: a -> " << ft << endl;
+  }
+
+  indent_down();
+  f_iface_.close();
+}
+
+/**
+ * Generates a service client definition. Note that in Haskell, the client doesn't implement iface.
+ *This is because
+ * The client does not (and should not have to) deal with arguments being Nothing.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_hs_generator::generate_service_client(t_service* tservice) {
+  string f_client_name = get_out_dir() + capitalize(service_name_) + "_Client.hs";
+  f_client_.open(f_client_name.c_str());
+  f_client_ << hs_language_pragma() << endl;
+  f_client_ << hs_autogen_comment() << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+
+  string extends = "";
+  string exports = "";
+
+  bool first = true;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    exports += (first ? "" : ",");
+    string funname = (*f_iter)->get_name();
+    exports += decapitalize(funname);
+    first = false;
+  }
+
+  string sname = capitalize(service_name_);
+  indent(f_client_) << "module " << sname << "_Client(" << exports << ") where" << endl;
+
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    indent(f_client_) << "import " << extends << "_Client" << endl;
+  }
+
+  indent(f_client_) << "import qualified Data.IORef as R" << endl;
+  indent(f_client_) << hs_imports() << endl;
+  indent(f_client_) << "import " << capitalize(program_name_) << "_Types" << endl;
+  indent(f_client_) << "import " << capitalize(service_name_) << endl;
+
+  // DATS RITE A GLOBAL VAR
+  indent(f_client_) << "seqid = R.newIORef 0" << endl;
+
+  // Generate client method implementations
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+
+    string fargs = "";
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter)
+      fargs += " arg_" + (*fld_iter)->get_name();
+
+    // Open function
+    indent(f_client_) << decapitalize(funname) << " (ip,op)" << fargs << " = do" << endl;
+    indent_up();
+    indent(f_client_) << "send_" << funname << " op" << fargs;
+
+    f_client_ << endl;
+
+    if (!(*f_iter)->is_oneway())
+      indent(f_client_) << "recv_" << funname << " ip" << endl;
+
+    indent_down();
+
+    indent(f_client_) << "send_" << funname << " op" << fargs << " = do" << endl;
+    indent_up();
+
+    indent(f_client_) << "seq <- seqid" << endl;
+    indent(f_client_) << "seqn <- R.readIORef seq" << endl;
+    string argsname = capitalize((*f_iter)->get_name() + "_args");
+
+    // Serialize the request header
+    string fname = (*f_iter)->get_name();
+    string msgType = (*f_iter)->is_oneway() ? "T.M_ONEWAY" : "T.M_CALL";
+    indent(f_client_) << "T.writeMessageBegin op (\"" << fname << "\", " << msgType << ", seqn)"
+                      << endl;
+    indent(f_client_) << "write_" << argsname << " op (" << argsname << "{";
+
+    bool first = true;
+    for (vector<t_field*>::const_iterator fld_iter = fields.begin(); fld_iter != fields.end();
+         ++fld_iter) {
+      string fieldname = (*fld_iter)->get_name();
+      f_client_ << (first ? "" : ",");
+      f_client_ << field_name(argsname, fieldname) << "=";
+      if ((*fld_iter)->get_req() == t_field::T_OPTIONAL
+          || ((t_type*)(*fld_iter)->get_type())->is_xception())
+        f_client_ << "P.Just ";
+      f_client_ << "arg_" << fieldname;
+      first = false;
+    }
+    f_client_ << "})" << endl;
+    indent(f_client_) << "T.writeMessageEnd op" << endl;
+
+    // Write to the stream
+    indent(f_client_) << "T.tFlush (T.getTransport op)" << endl;
+    indent_down();
+
+    if (!(*f_iter)->is_oneway()) {
+      string resultname = capitalize((*f_iter)->get_name() + "_result");
+      t_struct noargs(program_);
+
+      string funname = string("recv_") + (*f_iter)->get_name();
+      t_function recv_function((*f_iter)->get_returntype(), funname, &noargs);
+
+      // Open function
+      indent(f_client_) << funname << " ip = do" << endl;
+      indent_up();
+
+      indent(f_client_) << "(fname, mtype, rseqid) <- T.readMessageBegin ip" << endl;
+      indent(f_client_) << "M.when (mtype == T.M_EXCEPTION) $ do { exn <- T.readAppExn ip ; "
+                           "T.readMessageEnd ip ; X.throw exn }" << endl;
+
+      indent(f_client_) << "res <- read_" << resultname << " ip" << endl;
+      indent(f_client_) << "T.readMessageEnd ip" << endl;
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const vector<t_field*>& xceptions = xs->get_members();
+
+      for (vector<t_field*>::const_iterator x_iter = xceptions.begin(); x_iter != xceptions.end();
+           ++x_iter) {
+        indent(f_client_) << "P.maybe (P.return ()) X.throw ("
+                          << field_name(resultname, (*x_iter)->get_name()) << " res)" << endl;
+      }
+
+      if (!(*f_iter)->get_returntype()->is_void())
+        indent(f_client_) << "P.return $ " << field_name(resultname, "success") << " res" << endl;
+      else
+        indent(f_client_) << "P.return ()" << endl;
+
+      // Close function
+      indent_down();
+    }
+  }
+
+  f_client_.close();
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_hs_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter)
+    generate_process_function(tservice, *f_iter);
+
+  indent(f_service_) << "proc_ handler (iprot,oprot) (name,typ,seqid) = case name of" << endl;
+  indent_up();
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string fname = (*f_iter)->get_name();
+    indent(f_service_) << "\"" << fname << "\" -> process_" << decapitalize(fname)
+                       << " (seqid,iprot,oprot,handler)" << endl;
+  }
+
+  indent(f_service_) << "_ -> ";
+  if (tservice->get_extends() != NULL) {
+    f_service_ << type_name(tservice->get_extends())
+               << ".proc_ handler (iprot,oprot) (name,typ,seqid)" << endl;
+
+  } else {
+    f_service_ << "do" << endl;
+    indent_up();
+    indent(f_service_) << "_ <- T.readVal iprot (T.T_STRUCT Map.empty)" << endl;
+    indent(f_service_) << "T.writeMessageBegin oprot (name,T.M_EXCEPTION,seqid)" << endl;
+    indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN_METHOD (\"Unknown function "
+                          "\" ++ LT.unpack name))" << endl;
+    indent(f_service_) << "T.writeMessageEnd oprot" << endl;
+    indent(f_service_) << "T.tFlush (T.getTransport oprot)" << endl;
+    indent_down();
+  }
+
+  indent_down();
+
+  // Generate the server implementation
+  indent(f_service_) << "process handler (iprot, oprot) = do" << endl;
+  indent_up();
+
+  indent(f_service_) << "(name, typ, seqid) <- T.readMessageBegin iprot" << endl;
+  indent(f_service_) << "proc_ handler (iprot,oprot) (name,typ,seqid)" << endl;
+  indent(f_service_) << "T.readMessageEnd iprot" << endl;
+  indent(f_service_) << "P.return P.True" << endl;
+  indent_down();
+}
+
+bool hasNoArguments(t_function* func) {
+  return (func->get_arglist()->get_members().empty());
+}
+
+string t_hs_generator::render_hs_type_for_function_name(t_type* type) {
+  string type_str = render_hs_type(type, false);
+  std::string::size_type found = -1;
+
+  while (true) {
+    found = type_str.find_first_of("[]. ", found + 1);
+    if (string::npos == size_t(found)) {
+      break;
+    }
+
+    if (type_str[found] == '.')
+      type_str[found] = '_';
+    else
+      type_str[found] = 'Z';
+  }
+  return type_str;
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_hs_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open function
+  string funname = decapitalize(tfunction->get_name());
+  indent(f_service_) << "process_" << funname << " (seqid, iprot, oprot, handler) = do" << endl;
+  indent_up();
+
+  string argsname = capitalize(tfunction->get_name()) + "_args";
+  string resultname = capitalize(tfunction->get_name()) + "_result";
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(f_service_) << "args <- read_" << argsname << " iprot" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  size_t n = xceptions.size() + 1;
+  // Try block for a function with exceptions
+  if (n > 0) {
+    for (size_t i = 0; i < n; i++) {
+      indent(f_service_) << "(X.catch" << endl;
+      indent_up();
+    }
+  }
+
+  if (n > 0) {
+    indent(f_service_) << "(do" << endl;
+    indent_up();
+  }
+  indent(f_service_);
+
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void())
+    f_service_ << "val <- ";
+
+  f_service_ << "Iface." << decapitalize(tfunction->get_name()) << " handler";
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
+    f_service_ << " (" << field_name(argsname, (*f_iter)->get_name()) << " args)";
+
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << endl;
+    indent(f_service_) << "let res = default_" << resultname << "{"
+                       << field_name(resultname, "success") << " = val}";
+
+  } else if (!tfunction->is_oneway()) {
+    f_service_ << endl;
+    indent(f_service_) << "let res = default_" << resultname;
+  }
+  f_service_ << endl;
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    indent(f_service_) << "P.return ()";
+  } else {
+    indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name()
+                       << "\", T.M_REPLY, seqid)" << endl;
+    indent(f_service_) << "write_" << resultname << " oprot res" << endl;
+    indent(f_service_) << "T.writeMessageEnd oprot" << endl;
+    indent(f_service_) << "T.tFlush (T.getTransport oprot)";
+  }
+  if (n > 0) {
+    f_service_ << ")";
+    indent_down();
+  }
+  f_service_ << endl;
+
+  if (n > 0) {
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      indent(f_service_) << "(\\e  -> do" << endl;
+      indent_up();
+
+      if (!tfunction->is_oneway()) {
+        indent(f_service_) << "let res = default_" << resultname << "{"
+                           << field_name(resultname, (*x_iter)->get_name()) << " = P.Just e}"
+                           << endl;
+        indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name()
+                           << "\", T.M_REPLY, seqid)" << endl;
+        indent(f_service_) << "write_" << resultname << " oprot res" << endl;
+        indent(f_service_) << "T.writeMessageEnd oprot" << endl;
+        indent(f_service_) << "T.tFlush (T.getTransport oprot)";
+      } else {
+        indent(f_service_) << "P.return ()";
+      }
+
+      f_service_ << "))" << endl;
+      indent_down();
+      indent_down();
+    }
+    indent(f_service_) << "((\\_ -> do" << endl;
+    indent_up();
+
+    if (!tfunction->is_oneway()) {
+      indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name()
+                         << "\", T.M_EXCEPTION, seqid)" << endl;
+      indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN \"\")" << endl;
+      indent(f_service_) << "T.writeMessageEnd oprot" << endl;
+      indent(f_service_) << "T.tFlush (T.getTransport oprot)";
+    } else {
+      indent(f_service_) << "P.return ()";
+    }
+
+    f_service_ << ") :: X.SomeException -> P.IO ()))" << endl;
+    indent_down();
+    indent_down();
+  }
+  // Close function
+  indent_down();
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_hs_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+  (void)prefix;
+  t_type* type = tfield->get_type();
+  generate_deserialize_type(out, type, prefix);
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_hs_generator::generate_deserialize_type(ofstream& out, t_type* type, string arg) {
+  type = get_true_type(type);
+  string val = tmp("_val");
+  out << "(case " << arg << " of {" << type_to_constructor(type) << " " << val << " -> ";
+
+  if (type->is_void())
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE";
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, val);
+
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, val);
+
+  } else if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    if (tbase == t_base_type::TYPE_STRING && !((t_base_type*)type)->is_binary()) {
+      out << "E.decodeUtf8 ";
+    }
+    out << val;
+    if (((t_base_type*)type)->is_binary()) {
+      // Since wire type of binary is the same as string, we actually receive T.TString not
+      // T.TBinary
+      out << "; T.TString " << val << " -> " << val;
+    }
+  } else if (type->is_enum()) {
+    out << "P.toEnum $ P.fromIntegral " << val;
+
+  } else {
+    throw "DO NOT KNOW HOW TO DESERIALIZE TYPE " + type->get_name();
+  }
+  out << "; _ -> P.error \"wrong type\"})";
+}
+
+/**
+ * Generates an unserializer for a struct, calling read()
+ */
+void t_hs_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string name) {
+
+  out << "(" << type_name(tstruct, "to_") << " (T.TStruct " << name << "))";
+}
+
+/**
+ * Serialize a container by writing out the header followed by
+ * data and then a footer.
+ */
+void t_hs_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string arg) {
+
+  string val = tmp("_v");
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    string key = tmp("_k");
+    out << "(Map.fromList $ P.map (\\(" << key << "," << val << ") -> (";
+    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type(), key);
+
+    out << ",";
+    generate_deserialize_type(out, ((t_map*)ttype)->get_val_type(), val);
+
+    out << ")) " << arg << ")";
+
+  } else if (ttype->is_set()) {
+    out << "(Set.fromList $ P.map (\\" << val << " -> ";
+    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type(), val);
+    out << ") " << arg << ")";
+
+  } else if (ttype->is_list()) {
+    out << "(Vector.fromList $ P.map (\\" << val << " -> ";
+    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type(), val);
+    out << ") " << arg << ")";
+  }
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_hs_generator::generate_serialize_type(ofstream& out, t_type* type, string name) {
+
+  type = get_true_type(type);
+  // Do nothing for void types
+  if (type->is_void())
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE";
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, name);
+
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, name);
+
+  } else if (type->is_base_type() || type->is_enum()) {
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      out << type_to_constructor(type) << " ";
+      if (tbase == t_base_type::TYPE_STRING && !((t_base_type*)type)->is_binary()) {
+        out << "$ E.encodeUtf8 ";
+      }
+      out << name;
+
+    } else if (type->is_enum()) {
+      string ename = capitalize(type->get_name());
+      out << "T.TI32 $ P.fromIntegral $ P.fromEnum " << name;
+    }
+
+  } else {
+    throw "DO NOT KNOW HOW TO SERIALIZE FIELD OF TYPE " + type->get_name();
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_hs_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  out << type_name(tstruct, "from_") << " " << prefix;
+}
+
+void t_hs_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  string k = tmp("_k");
+  string v = tmp("_v");
+
+  if (ttype->is_map()) {
+    t_type* ktype = ((t_map*)ttype)->get_key_type();
+    t_type* vtype = ((t_map*)ttype)->get_val_type();
+    out << "T.TMap " << type_to_enum(ktype) << " " << type_to_enum(vtype);
+    out << " $ P.map (\\(" << k << "," << v << ") -> (";
+    generate_serialize_type(out, ktype, k);
+    out << ", ";
+    generate_serialize_type(out, vtype, v);
+    out << ")) $ Map.toList " << prefix;
+
+  } else if (ttype->is_set()) {
+    out << "T.TSet " << type_to_enum(((t_list*)ttype)->get_elem_type());
+    out << " $ P.map (\\" << v << " -> ";
+    generate_serialize_type(out, ((t_list*)ttype)->get_elem_type(), v);
+    out << ") $ Set.toList " << prefix;
+
+  } else if (ttype->is_list()) {
+    out << "T.TList " << type_to_enum(((t_list*)ttype)->get_elem_type());
+    out << " $ P.map (\\" << v << " -> ";
+    generate_serialize_type(out, ((t_list*)ttype)->get_elem_type(), v);
+    out << ") $ Vector.toList " << prefix;
+  }
+}
+
+string t_hs_generator::function_type(t_function* tfunc, bool options, bool io, bool method) {
+  string result = "";
+
+  const vector<t_field*>& fields = tfunc->get_arglist()->get_members();
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL
+        || ((t_type*)(*f_iter)->get_type())->is_xception())
+      result += "P.Maybe ";
+    result += render_hs_type((*f_iter)->get_type(), options);
+    result += " -> ";
+  }
+
+  if (fields.empty() && !method)
+    result += "() -> ";
+
+  if (io)
+    result += "P.IO ";
+
+  result += render_hs_type(tfunc->get_returntype(), io);
+  return result;
+}
+
+string t_hs_generator::type_name(t_type* ttype, string function_prefix) {
+  string prefix = "";
+  t_program* program = ttype->get_program();
+
+  if (program != NULL && program != program_)
+    if (!ttype->is_service())
+      prefix = capitalize(program->get_name()) + "_Types.";
+
+  return prefix + function_prefix + capitalize(ttype->get_name());
+}
+
+string t_hs_generator::field_name(string tname, string fname) {
+  return decapitalize(tname) + "_" + fname;
+}
+
+/**
+ * Converts the parse type to a Protocol.t_type enum
+ */
+string t_hs_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      return "T.T_VOID";
+    case t_base_type::TYPE_STRING:
+      return ((t_base_type*)type)->is_binary() ? "T.T_BINARY" : "T.T_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "T.T_BOOL";
+    case t_base_type::TYPE_I8:
+      return "T.T_BYTE";
+    case t_base_type::TYPE_I16:
+      return "T.T_I16";
+    case t_base_type::TYPE_I32:
+      return "T.T_I32";
+    case t_base_type::TYPE_I64:
+      return "T.T_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "T.T_DOUBLE";
+    }
+
+  } else if (type->is_enum()) {
+    return "T.T_I32";
+
+  } else if (type->is_struct() || type->is_xception()) {
+    return "(T.T_STRUCT " + type_name((t_struct*)type, "typemap_") + ")";
+
+  } else if (type->is_map()) {
+    string ktype = type_to_enum(((t_map*)type)->get_key_type());
+    string vtype = type_to_enum(((t_map*)type)->get_val_type());
+    return "(T.T_MAP " + ktype + " " + vtype + ")";
+
+  } else if (type->is_set()) {
+    return "(T.T_SET " + type_to_enum(((t_list*)type)->get_elem_type()) + ")";
+
+  } else if (type->is_list()) {
+    return "(T.T_LIST " + type_to_enum(((t_list*)type)->get_elem_type()) + ")";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Converts the parse type to a default value
+ */
+string t_hs_generator::type_to_default(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      return "P.error \"No default value for type T_VOID\"";
+    case t_base_type::TYPE_STRING:
+      return "\"\"";
+    case t_base_type::TYPE_BOOL:
+      return "P.False";
+    case t_base_type::TYPE_I8:
+      return "0";
+    case t_base_type::TYPE_I16:
+      return "0";
+    case t_base_type::TYPE_I32:
+      return "0";
+    case t_base_type::TYPE_I64:
+      return "0";
+    case t_base_type::TYPE_DOUBLE:
+      return "0";
+    }
+
+  } else if (type->is_enum()) {
+    return "(P.toEnum 0)";
+
+  } else if (type->is_struct() || type->is_xception()) {
+    return type_name((t_struct*)type, "default_");
+
+  } else if (type->is_map()) {
+    return "Map.empty";
+
+  } else if (type->is_set()) {
+    return "Set.empty";
+
+  } else if (type->is_list()) {
+    return "Vector.empty";
+  }
+
+  throw "INVALID TYPE IN type_to_default: " + type->get_name();
+}
+
+/**
+ * Converts the parse type to an haskell type
+ */
+string t_hs_generator::render_hs_type(t_type* type, bool needs_parens) {
+  type = get_true_type(type);
+  string type_repr;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      return "()";
+    case t_base_type::TYPE_STRING:
+      return (((t_base_type*)type)->is_binary() ? "LBS.ByteString" : "LT.Text");
+    case t_base_type::TYPE_BOOL:
+      return "P.Bool";
+    case t_base_type::TYPE_I8:
+      return "I.Int8";
+    case t_base_type::TYPE_I16:
+      return "I.Int16";
+    case t_base_type::TYPE_I32:
+      return "I.Int32";
+    case t_base_type::TYPE_I64:
+      return "I.Int64";
+    case t_base_type::TYPE_DOUBLE:
+      return "P.Double";
+    }
+
+  } else if (type->is_enum()) {
+    return type_name((t_enum*)type);
+
+  } else if (type->is_struct() || type->is_xception()) {
+    return type_name((t_struct*)type);
+
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    type_repr = "Map.HashMap " + render_hs_type(ktype, true) + " " + render_hs_type(vtype, true);
+
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    type_repr = "Set.HashSet " + render_hs_type(etype, true);
+
+  } else if (type->is_list()) {
+    t_type* etype = ((t_list*)type)->get_elem_type();
+    type_repr = "Vector.Vector " + render_hs_type(etype, true);
+
+  } else {
+    throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+  }
+
+  return needs_parens ? "(" + type_repr + ")" : type_repr;
+}
+
+/**
+ * Converts the parse type to a haskell constructor
+ */
+string t_hs_generator::type_to_constructor(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "invalid type: T_VOID";
+    case t_base_type::TYPE_STRING:
+      return ((t_base_type*)type)->is_binary() ? "T.TBinary" : "T.TString";
+    case t_base_type::TYPE_BOOL:
+      return "T.TBool";
+    case t_base_type::TYPE_I8:
+      return "T.TByte";
+    case t_base_type::TYPE_I16:
+      return "T.TI16";
+    case t_base_type::TYPE_I32:
+      return "T.TI32";
+    case t_base_type::TYPE_I64:
+      return "T.TI64";
+    case t_base_type::TYPE_DOUBLE:
+      return "T.TDouble";
+    }
+
+  } else if (type->is_enum()) {
+    return "T.TI32";
+
+  } else if (type->is_struct() || type->is_xception()) {
+    return "T.TStruct";
+
+  } else if (type->is_map()) {
+    return "T.TMap _ _";
+
+  } else if (type->is_set()) {
+    return "T.TSet _";
+
+  } else if (type->is_list()) {
+    return "T.TList _";
+  }
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+THRIFT_REGISTER_GENERATOR(hs, "Haskell", "")


[42/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_erl_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc
deleted file mode 100644
index 9ac908c..0000000
--- a/compiler/cpp/src/generate/t_erl_generator.cc
+++ /dev/null
@@ -1,1169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-#include "t_generator.h"
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const std::string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Erlang code generator.
- *
- */
-class t_erl_generator : public t_generator {
-public:
-  t_erl_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    legacy_names_ = false;
-    maps_ = false;
-    otp16_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("legacynames") == 0) {
-        legacy_names_ = true;
-      } else if( iter->first.compare("maps") == 0) {
-        maps_ = true;
-      } else if( iter->first.compare("otp16") == 0) {
-        otp16_ = true;
-      } else {
-        throw "unknown option erl:" + iter->first;
-      }
-    }
-
-    if (maps_ && otp16_) {
-      throw "argument error: Cannot specify both maps and otp16; maps are not available for Erlang/OTP R16 or older";
-    }
-
-    out_dir_base_ = "gen-erl";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-  void generate_member_type(std::ostream& out, t_type* type);
-  void generate_member_value(std::ostream& out, t_type* type, t_const_value* value);
-
-  std::string render_member_type(t_field* field);
-  std::string render_member_value(t_field* field);
-  std::string render_member_requiredness(t_field* field);
-
-  //  std::string render_default_value(t_type* type);
-  std::string render_default_value(t_field* field);
-  std::string render_const_value(t_type* type, t_const_value* value);
-  std::string render_type_term(t_type* ttype, bool expand_structs, bool extended_info = false);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_erl_struct(t_struct* tstruct, bool is_exception);
-  void generate_erl_struct_definition(std::ostream& out, t_struct* tstruct);
-  void generate_erl_struct_member(std::ostream& out, t_field* tmember);
-  void generate_erl_struct_info(std::ostream& out, t_struct* tstruct);
-  void generate_erl_extended_struct_info(std::ostream& out, t_struct* tstruct);
-  void generate_erl_function_helpers(t_function* tfunction);
-  void generate_type_metadata(std::string function_name, vector<string> names);
-  void generate_enum_info(t_enum* tenum);
-  void generate_enum_metadata();
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_metadata(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_function_info(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string erl_autogen_comment();
-  std::string erl_imports();
-  std::string render_includes();
-  std::string type_name(t_type* ttype);
-
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string type_module(t_type* ttype);
-
-  std::string make_safe_for_module_name(std::string in) {
-    if (legacy_names_) {
-      return decapitalize(in);
-    } else {
-      return underscore(in);
-    }
-  }
-
-  std::string atomify(std::string in) {
-    if (legacy_names_) {
-      return "'" + decapitalize(in) + "'";
-    } else {
-      return "'" + in + "'";
-    }
-  }
-
-  std::string constify(std::string in) {
-    if (legacy_names_) {
-      return capitalize(in);
-    } else {
-      return uppercase(in);
-    }
-  }
-
-  static std::string comment(string in);
-
-private:
-  bool has_default_value(t_field*);
-
-  /* if true retain pre 0.9.2 naming scheme for functions, atoms and consts */
-  bool legacy_names_;
-
-  /* if true use maps instead of dicts in generated code */
-  bool maps_;
-
-  /* if true use non-namespaced dict and set instead of dict:dict and sets:set */
-  bool otp16_;
-
-  /**
-   * add function to export list
-   */
-
-  void export_function(t_function* tfunction, std::string prefix = "");
-  void export_string(std::string name, int num);
-
-  void export_types_function(t_function* tfunction, std::string prefix = "");
-  void export_types_string(std::string name, int num);
-
-  /**
-   * write out headers and footers for hrl files
-   */
-
-  void hrl_header(std::ostream& out, std::string name);
-  void hrl_footer(std::ostream& out, std::string name);
-
-  /**
-   * stuff to spit out at the top of generated files
-   */
-
-  bool export_lines_first_;
-  std::ostringstream export_lines_;
-
-  bool export_types_lines_first_;
-  std::ostringstream export_types_lines_;
-
-  /**
-   * File streams
-   */
-
-  std::ostringstream f_info_;
-  std::ostringstream f_info_ext_;
-
-  std::ofstream f_types_file_;
-  std::ofstream f_types_hrl_file_;
-
-  std::ofstream f_consts_;
-  std::ostringstream f_service_;
-  std::ofstream f_service_file_;
-  std::ofstream f_service_hrl_;
-
-  /**
-   * Metadata containers
-   */
-  std::vector<std::string> v_struct_names_;
-  std::vector<std::string> v_enum_names_;
-  std::vector<std::string> v_exception_names_;
-  std::vector<t_enum*> v_enums_;
-};
-
-/**
- * UI for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_erl_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  // setup export lines
-  export_lines_first_ = true;
-  export_types_lines_first_ = true;
-
-  // types files
-  string f_types_name = get_out_dir() + make_safe_for_module_name(program_name_) + "_types.erl";
-  string f_types_hrl_name = get_out_dir() + make_safe_for_module_name(program_name_) + "_types.hrl";
-
-  f_types_file_.open(f_types_name.c_str());
-  f_types_hrl_file_.open(f_types_hrl_name.c_str());
-
-  hrl_header(f_types_hrl_file_, make_safe_for_module_name(program_name_) + "_types");
-
-  f_types_file_ << erl_autogen_comment() << endl << "-module("
-                << make_safe_for_module_name(program_name_) << "_types)." << endl << erl_imports()
-                << endl;
-
-  f_types_file_ << "-include(\"" << make_safe_for_module_name(program_name_) << "_types.hrl\")."
-                << endl << endl;
-
-  f_types_hrl_file_ << render_includes() << endl;
-
-  // consts file
-  string f_consts_name = get_out_dir() + make_safe_for_module_name(program_name_)
-                         + "_constants.hrl";
-  f_consts_.open(f_consts_name.c_str());
-
-  f_consts_ << erl_autogen_comment() << endl << erl_imports() << endl << "-include(\""
-            << make_safe_for_module_name(program_name_) << "_types.hrl\")." << endl << endl;
-}
-
-/**
- * Boilerplate at beginning and end of header files
- */
-void t_erl_generator::hrl_header(ostream& out, string name) {
-  out << "-ifndef(_" << name << "_included)." << endl << "-define(_" << name << "_included, yeah)."
-      << endl;
-}
-
-void t_erl_generator::hrl_footer(ostream& out, string name) {
-  (void)name;
-  out << "-endif." << endl;
-}
-
-/**
- * Renders all the imports necessary for including another Thrift program
- */
-string t_erl_generator::render_includes() {
-  const vector<t_program*>& includes = program_->get_includes();
-  string result = "";
-  for (size_t i = 0; i < includes.size(); ++i) {
-    result += "-include(\"" + make_safe_for_module_name(includes[i]->get_name())
-              + "_types.hrl\").\n";
-  }
-  if (includes.size() > 0) {
-    result += "\n";
-  }
-  return result;
-}
-
-/**
- * Autogen'd comment
- */
-string t_erl_generator::erl_autogen_comment() {
-  return std::string("%%\n") + "%% Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-         + "%%\n" + "%% DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
-         + "%%\n";
-}
-
-/**
- * Comment out text
- */
-
-string t_erl_generator::comment(string in) {
-  size_t pos = 0;
-  in.insert(pos, "%% ");
-  while ((pos = in.find_first_of('\n', pos)) != string::npos) {
-    in.insert(++pos, "%% ");
-  }
-  return in;
-}
-
-/**
- * Prints standard thrift imports
- */
-string t_erl_generator::erl_imports() {
-  return "";
-}
-
-/**
- * Closes the type files
- */
-void t_erl_generator::close_generator() {
-
-  export_types_string("struct_info", 1);
-  export_types_string("struct_info_ext", 1);
-  export_types_string("enum_info", 1);
-  export_types_string("enum_names", 0);
-  export_types_string("struct_names", 0);
-  export_types_string("exception_names", 0);
-
-  f_types_file_ << "-export([" << export_types_lines_.str() << "])." << endl << endl;
-
-  f_types_file_ << f_info_.str();
-  f_types_file_ << "struct_info(_) -> erlang:error(function_clause)." << endl << endl;
-
-  f_types_file_ << f_info_ext_.str();
-  f_types_file_ << "struct_info_ext(_) -> erlang:error(function_clause)." << endl << endl;
-
-  generate_type_metadata("struct_names", v_struct_names_);
-  generate_enum_metadata();
-  generate_type_metadata("enum_names", v_enum_names_);
-  generate_type_metadata("exception_names", v_exception_names_);
-
-  hrl_footer(f_types_hrl_file_, string("BOGUS"));
-
-  f_types_file_.close();
-  f_types_hrl_file_.close();
-  f_consts_.close();
-}
-
-void t_erl_generator::generate_type_metadata(std::string function_name, vector<string> names) {
-  vector<string>::iterator s_iter;
-  size_t num_structs = names.size();
-
-  indent(f_types_file_) << function_name << "() ->\n";
-  indent_up();
-  indent(f_types_file_) << "[";
-
-
-  for(size_t i=0; i < num_structs; i++) {
-    f_types_file_ << names.at(i);
-
-    if (i < num_structs - 1) {
-      f_types_file_ << ", ";
-    }
-  }
-
-  f_types_file_ << "].\n\n";
-  indent_down();
-}
-
-/**
- * Generates a typedef. no op
- *
- * @param ttypedef The type definition
- */
-void t_erl_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Generates code for an enumerated type. Done using a class to scope
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_erl_generator::generate_enum(t_enum* tenum) {
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-
-  v_enums_.push_back(tenum);
-  v_enum_names_.push_back(atomify(tenum->get_name()));
-
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    string name = (*c_iter)->get_name();
-    indent(f_types_hrl_file_) << "-define(" << constify(make_safe_for_module_name(program_name_))
-                              << "_" << constify(tenum->get_name()) << "_" << constify(name) << ", "
-                              << value << ")." << endl;
-  }
-
-  f_types_hrl_file_ << endl;
-}
-
-void t_erl_generator::generate_enum_info(t_enum* tenum){
-  vector<t_enum_value*> constants = tenum->get_constants();
-  size_t num_constants = constants.size();
-
-  indent(f_types_file_) << "enum_info(" << atomify(tenum->get_name()) << ") ->\n";
-  indent_up();
-  indent(f_types_file_) << "[\n";
-
-  for(size_t i=0; i < num_constants; i++) {
-    indent_up();
-    t_enum_value* value = constants.at(i);
-    indent(f_types_file_) << "{" << atomify(value->get_name()) << ", " << value->get_value() << "}";
-
-    if (i < num_constants - 1) {
-      f_types_file_ << ",\n";
-    }
-    indent_down();
-  }
-  f_types_file_ << "\n";
-  indent(f_types_file_) << "];\n\n";
-  indent_down();
-}
-
-void t_erl_generator::generate_enum_metadata() {
-  size_t enum_count = v_enums_.size();
-
-  for(size_t i=0; i < enum_count; i++) {
-    t_enum* tenum = v_enums_.at(i);
-    generate_enum_info(tenum);
-  }
-
-  indent(f_types_file_) << "enum_info(_) -> erlang:error(function_clause).\n\n";
-}
-
-/**
- * Generate a constant value
- */
-void t_erl_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  f_consts_ << "-define(" << constify(make_safe_for_module_name(program_name_)) << "_"
-            << constify(name) << ", " << render_const_value(type, value) << ")." << endl << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_erl_generator::render_const_value(t_type* type, t_const_value* value) {
-  type = get_true_type(type);
-  std::ostringstream out;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    indent(out) << value->get_integer();
-
-  } else if (type->is_struct() || type->is_xception()) {
-    out << "#" << type_name(type) << "{";
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    bool first = true;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-
-      if (first) {
-        first = false;
-      } else {
-        out << ",";
-      }
-      out << v_iter->first->get_string();
-      out << " = ";
-      out << render_const_value(field_type, v_iter->second);
-    }
-    indent_down();
-    indent(out) << "}";
-
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-
-    if (maps_) {
-      out << "maps:from_list([";
-    } else {
-      out << "dict:from_list([";
-    }
-    map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
-    for (i = value->get_map().begin(); i != end;) {
-      out << "{" << render_const_value(ktype, i->first) << ","
-          << render_const_value(vtype, i->second) << "}";
-      if (++i != end) {
-        out << ",";
-      }
-    }
-    out << "])";
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    out << "sets:from_list([";
-    vector<t_const_value*>::const_iterator i, end = value->get_list().end();
-    for (i = value->get_list().begin(); i != end;) {
-      out << render_const_value(etype, *i);
-      if (++i != end) {
-        out << ",";
-      }
-    }
-    out << "])";
-  } else if (type->is_list()) {
-    t_type* etype;
-    etype = ((t_list*)type)->get_elem_type();
-    out << "[";
-
-    bool first = true;
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      if (first) {
-        first = false;
-      } else {
-        out << ",";
-      }
-      out << render_const_value(etype, *v_iter);
-    }
-    out << "]";
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-  return out.str();
-}
-
-string t_erl_generator::render_default_value(t_field* field) {
-  t_type* type = field->get_type();
-  if (type->is_struct() || type->is_xception()) {
-    return "#" + type_name(type) + "{}";
-  } else if (type->is_map()) {
-    if (maps_) {
-      return "#{}";
-    } else {
-      return "dict:new()";
-    }
-  } else if (type->is_set()) {
-    return "sets:new()";
-  } else if (type->is_list()) {
-    return "[]";
-  } else {
-    return "undefined";
-  }
-}
-
-string t_erl_generator::render_member_type(t_field* field) {
-  t_type* type = get_true_type(field->get_type());
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      return "string() | binary()";
-    case t_base_type::TYPE_BOOL:
-      return "boolean()";
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      return "integer()";
-    case t_base_type::TYPE_DOUBLE:
-      return "float()";
-    default:
-      throw "compiler error: unsupported base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    return "integer()";
-  } else if (type->is_struct() || type->is_xception()) {
-    return type_name(type) + "()";
-  } else if (type->is_map()) {
-    if (maps_) {
-      return "#{}";
-    } else if (otp16_) {
-      return "dict()";
-    } else {
-      return "dict:dict()";
-    }
-  } else if (type->is_set()) {
-    if (otp16_) {
-      return "set()";
-    } else {
-      return "sets:set()";
-    }
-  } else if (type->is_list()) {
-    return "list()";
-  } else {
-    throw "compiler error: unsupported type " + type->get_name();
-  }
-}
-
-string t_erl_generator::render_member_requiredness(t_field* field) {
-  switch (field->get_req()) {
-  case t_field::T_REQUIRED:
-    return "required";
-  case t_field::T_OPTIONAL:
-    return "optional";
-  default:
-    return "undefined";
-  }
-}
-
-/**
- * Generates a struct
- */
-void t_erl_generator::generate_struct(t_struct* tstruct) {
-  v_struct_names_.push_back(type_name(tstruct));
-  generate_erl_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_erl_generator::generate_xception(t_struct* txception) {
-  v_exception_names_.push_back(type_name(txception));
-  generate_erl_struct(txception, true);
-}
-
-/**
- * Generates a struct
- */
-void t_erl_generator::generate_erl_struct(t_struct* tstruct, bool is_exception) {
-  (void)is_exception;
-  generate_erl_struct_definition(f_types_hrl_file_, tstruct);
-  generate_erl_struct_info(f_info_, tstruct);
-  generate_erl_extended_struct_info(f_info_ext_, tstruct);
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_erl_generator::generate_erl_struct_definition(ostream& out, t_struct* tstruct) {
-  indent(out) << "%% struct " << type_name(tstruct) << endl << endl;
-
-  std::stringstream buf;
-  buf << indent() << "-record(" << type_name(tstruct) << ", {";
-  string field_indent(buf.str().size(), ' ');
-
-  const vector<t_field*>& members = tstruct->get_members();
-  for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();) {
-    generate_erl_struct_member(buf, *m_iter);
-    if (++m_iter != members.end()) {
-      buf << "," << endl << field_indent;
-    }
-  }
-  buf << "}).";
-
-  out << buf.str() << endl;
-  out << "-type " + type_name(tstruct) << "() :: #" + type_name(tstruct) + "{}." << endl << endl;
-}
-
-/**
- * Generates the record field definition
- */
-
-void t_erl_generator::generate_erl_struct_member(ostream& out, t_field* tmember) {
-  out << atomify(tmember->get_name());
-  if (has_default_value(tmember))
-    out << " = " << render_member_value(tmember);
-  out << " :: " << render_member_type(tmember);
-}
-
-bool t_erl_generator::has_default_value(t_field* field) {
-  t_type* type = field->get_type();
-  if (!field->get_value()) {
-    if (field->get_req() == t_field::T_REQUIRED) {
-      if (type->is_struct() || type->is_xception() || type->is_map() || type->is_set()
-          || type->is_list()) {
-        return true;
-      } else {
-        return false;
-      }
-    } else {
-      return false;
-    }
-  } else {
-    return true;
-  }
-}
-
-string t_erl_generator::render_member_value(t_field* field) {
-  if (!field->get_value()) {
-    return render_default_value(field);
-  } else {
-    return render_const_value(field->get_type(), field->get_value());
-  }
-}
-
-/**
- * Generates the read method for a struct
- */
-void t_erl_generator::generate_erl_struct_info(ostream& out, t_struct* tstruct) {
-  indent(out) << "struct_info(" << type_name(tstruct) << ") ->" << endl;
-  indent_up();
-  out << indent() << render_type_term(tstruct, true) << ";" << endl;
-  indent_down();
-  out << endl;
-}
-
-void t_erl_generator::generate_erl_extended_struct_info(ostream& out, t_struct* tstruct) {
-  indent(out) << "struct_info_ext(" << type_name(tstruct) << ") ->" << endl;
-  indent_up();
-  out << indent() << render_type_term(tstruct, true, true) << ";" << endl;
-  indent_down();
-  out << endl;
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_erl_generator::generate_service(t_service* tservice) {
-  service_name_ = make_safe_for_module_name(service_name_);
-
-  string f_service_hrl_name = get_out_dir() + service_name_ + "_thrift.hrl";
-  string f_service_name = get_out_dir() + service_name_ + "_thrift.erl";
-  f_service_file_.open(f_service_name.c_str());
-  f_service_hrl_.open(f_service_hrl_name.c_str());
-
-  // Reset service text aggregating stream streams
-  f_service_.str("");
-  export_lines_.str("");
-  export_lines_first_ = true;
-
-  hrl_header(f_service_hrl_, service_name_);
-
-  if (tservice->get_extends() != NULL) {
-    f_service_hrl_ << "-include(\""
-                   << make_safe_for_module_name(tservice->get_extends()->get_name())
-                   << "_thrift.hrl\"). % inherit " << endl;
-  }
-
-  f_service_hrl_ << "-include(\"" << make_safe_for_module_name(program_name_) << "_types.hrl\")."
-                 << endl << endl;
-
-  // Generate the three main parts of the service (well, two for now in PHP)
-  generate_service_helpers(tservice); // cpiro: New Erlang Order
-
-  generate_service_interface(tservice);
-
-  generate_service_metadata(tservice);
-
-  // indent_down();
-
-  f_service_file_ << erl_autogen_comment() << endl << "-module(" << service_name_ << "_thrift)."
-                  << endl << "-behaviour(thrift_service)." << endl << endl << erl_imports() << endl;
-
-  f_service_file_ << "-include(\"" << make_safe_for_module_name(tservice->get_name())
-                  << "_thrift.hrl\")." << endl << endl;
-
-  f_service_file_ << "-export([" << export_lines_.str() << "])." << endl << endl;
-
-  f_service_file_ << f_service_.str();
-
-  hrl_footer(f_service_hrl_, f_service_name);
-
-  // Close service file
-  f_service_file_.close();
-  f_service_hrl_.close();
-}
-
-void t_erl_generator::generate_service_metadata(t_service* tservice) {
-  export_string("function_names", 0);
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  size_t num_functions = functions.size();
-
-  indent(f_service_) << "function_names() -> " << endl;
-  indent_up();
-  indent(f_service_) << "[";
-
-  for (size_t i=0; i < num_functions; i++) {
-    t_function* current = functions.at(i);
-    f_service_ << atomify(current->get_name());
-    if (i < num_functions - 1) {
-      f_service_ << ", ";
-    }
-  }
-
-  f_service_ << "].\n\n";
-  indent_down();
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_erl_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  //  indent(f_service_) <<
-  //  "% HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
-
-  export_string("struct_info", 1);
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_erl_function_helpers(*f_iter);
-  }
-  f_service_ << "struct_info(_) -> erlang:error(function_clause)." << endl;
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_erl_generator::generate_erl_function_helpers(t_function* tfunction) {
-  (void)tfunction;
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_erl_generator::generate_service_interface(t_service* tservice) {
-
-  export_string("function_info", 2);
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  f_service_ << "%%% interface" << endl;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "% " << function_signature(*f_iter) << endl;
-
-    generate_function_info(tservice, *f_iter);
-  }
-
-  // Inheritance - pass unknown functions to base class
-  if (tservice->get_extends() != NULL) {
-    indent(f_service_) << "function_info(Function, InfoType) ->" << endl;
-    indent_up();
-    indent(f_service_) << make_safe_for_module_name(tservice->get_extends()->get_name())
-                       << "_thrift:function_info(Function, InfoType)." << endl;
-    indent_down();
-  } else {
-    // return function_clause error for non-existent functions
-    indent(f_service_) << "function_info(_Func, _Info) -> erlang:error(function_clause)." << endl;
-  }
-
-  indent(f_service_) << endl;
-}
-
-/**
- * Generates a function_info(FunctionName, params_type) and
- * function_info(FunctionName, reply_type)
- */
-void t_erl_generator::generate_function_info(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  string name_atom = atomify(tfunction->get_name());
-
-  t_struct* xs = tfunction->get_xceptions();
-  t_struct* arg_struct = tfunction->get_arglist();
-
-  // function_info(Function, params_type):
-  indent(f_service_) << "function_info(" << name_atom << ", params_type) ->" << endl;
-  indent_up();
-
-  indent(f_service_) << render_type_term(arg_struct, true) << ";" << endl;
-
-  indent_down();
-
-  // function_info(Function, reply_type):
-  indent(f_service_) << "function_info(" << name_atom << ", reply_type) ->" << endl;
-  indent_up();
-
-  if (!tfunction->get_returntype()->is_void())
-    indent(f_service_) << render_type_term(tfunction->get_returntype(), false) << ";" << endl;
-  else if (tfunction->is_oneway())
-    indent(f_service_) << "oneway_void;" << endl;
-  else
-    indent(f_service_) << "{struct, []}"
-                       << ";" << endl;
-  indent_down();
-
-  // function_info(Function, exceptions):
-  indent(f_service_) << "function_info(" << name_atom << ", exceptions) ->" << endl;
-  indent_up();
-  indent(f_service_) << render_type_term(xs, true) << ";" << endl;
-  indent_down();
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_erl_generator::function_signature(t_function* tfunction, string prefix) {
-  return prefix + tfunction->get_name() + "(This"
-         + capitalize(argument_list(tfunction->get_arglist())) + ")";
-}
-
-/**
- * Add a function to the exports list
- */
-void t_erl_generator::export_string(string name, int num) {
-  if (export_lines_first_) {
-    export_lines_first_ = false;
-  } else {
-    export_lines_ << ", ";
-  }
-  export_lines_ << name << "/" << num;
-}
-
-void t_erl_generator::export_types_function(t_function* tfunction, string prefix) {
-
-  export_types_string(prefix + tfunction->get_name(),
-                      1 // This
-                      + ((tfunction->get_arglist())->get_members()).size());
-}
-
-void t_erl_generator::export_types_string(string name, int num) {
-  if (export_types_lines_first_) {
-    export_types_lines_first_ = false;
-  } else {
-    export_types_lines_ << ", ";
-  }
-  export_types_lines_ << name << "/" << num;
-}
-
-void t_erl_generator::export_function(t_function* tfunction, string prefix) {
-
-  export_string(prefix + tfunction->get_name(),
-                1 // This
-                + ((tfunction->get_arglist())->get_members()).size());
-}
-
-/**
- * Renders a field list
- */
-string t_erl_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      result += ", "; // initial comma to compensate for initial This
-    } else {
-      result += ", ";
-    }
-    result += capitalize((*f_iter)->get_name());
-  }
-  return result;
-}
-
-string t_erl_generator::type_name(t_type* ttype) {
-  string prefix = "";
-  string erl_namespace = ttype->get_program()->get_namespace("erl");
-
-  if (erl_namespace.length() > 0) {
-    prefix = erl_namespace + ".";
-  }
-
-  string name = ttype->get_name();
-
-  if (ttype->is_struct() || ttype->is_xception() || ttype->is_service()) {
-    name = ttype->get_name();
-  }
-
-  return atomify(prefix + name);
-}
-
-/**
- * Converts the parse type to a Erlang "type" (macro for int constants)
- */
-string t_erl_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "?tType_STRING";
-    case t_base_type::TYPE_BOOL:
-      return "?tType_BOOL";
-    case t_base_type::TYPE_I8:
-      return "?tType_I8";
-    case t_base_type::TYPE_I16:
-      return "?tType_I16";
-    case t_base_type::TYPE_I32:
-      return "?tType_I32";
-    case t_base_type::TYPE_I64:
-      return "?tType_I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "?tType_DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "?tType_I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "?tType_STRUCT";
-  } else if (type->is_map()) {
-    return "?tType_MAP";
-  } else if (type->is_set()) {
-    return "?tType_SET";
-  } else if (type->is_list()) {
-    return "?tType_LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-/**
- * Generate an Erlang term which represents a thrift type
- */
-std::string t_erl_generator::render_type_term(t_type* type,
-                                              bool expand_structs,
-                                              bool extended_info) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "string";
-    case t_base_type::TYPE_BOOL:
-      return "bool";
-    case t_base_type::TYPE_I8:
-      return "byte";
-    case t_base_type::TYPE_I16:
-      return "i16";
-    case t_base_type::TYPE_I32:
-      return "i32";
-    case t_base_type::TYPE_I64:
-      return "i64";
-    case t_base_type::TYPE_DOUBLE:
-      return "double";
-    }
-  } else if (type->is_enum()) {
-    return "i32";
-  } else if (type->is_struct() || type->is_xception()) {
-    if (expand_structs) {
-
-      std::stringstream buf;
-      buf << "{struct, [";
-      string field_indent(buf.str().size(), ' ');
-
-      t_struct::members_type const& fields = static_cast<t_struct*>(type)->get_members();
-      t_struct::members_type::const_iterator i, end = fields.end();
-      for (i = fields.begin(); i != end;) {
-        t_struct::members_type::value_type member = *i;
-        int32_t key = member->get_key();
-        string type = render_type_term(member->get_type(), false, false); // recursive call
-
-        if (!extended_info) {
-          // Convert to format: {struct, [{Fid, Type}|...]}
-          buf << "{" << key << ", " << type << "}";
-        } else {
-          // Convert to format: {struct, [{Fid, Req, Type, Name, Def}|...]}
-          string name = member->get_name();
-          string value = render_member_value(member);
-          string requiredness = render_member_requiredness(member);
-          buf << "{" << key << ", " << requiredness << ", " << type << ", " << atomify(name) << ", "
-              << value << "}";
-        }
-
-        if (++i != end) {
-          buf << "," << endl << field_indent;
-        }
-      }
-
-      buf << "]}" << endl;
-      return buf.str();
-    } else {
-      return "{struct, {" + atomify(type_module(type)) + ", " + type_name(type) + "}}";
-    }
-  } else if (type->is_map()) {
-    // {map, KeyType, ValType}
-    t_type* key_type = ((t_map*)type)->get_key_type();
-    t_type* val_type = ((t_map*)type)->get_val_type();
-
-    return "{map, " + render_type_term(key_type, false) + ", " + render_type_term(val_type, false)
-           + "}";
-
-  } else if (type->is_set()) {
-    t_type* elem_type = ((t_set*)type)->get_elem_type();
-
-    return "{set, " + render_type_term(elem_type, false) + "}";
-
-  } else if (type->is_list()) {
-    t_type* elem_type = ((t_list*)type)->get_elem_type();
-
-    return "{list, " + render_type_term(elem_type, false) + "}";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-std::string t_erl_generator::type_module(t_type* ttype) {
-  return make_safe_for_module_name(ttype->get_program()->get_name()) + "_types";
-}
-
-THRIFT_REGISTER_GENERATOR(
-    erl,
-    "Erlang",
-    "    legacynames: Output files retain naming conventions of Thrift 0.9.1 and earlier.\n"
-    "    maps:        Generate maps instead of dicts.\n"
-    "    otp16:       Generate non-namespaced dict and set instead of dict:dict and sets:set.\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_generator.cc b/compiler/cpp/src/generate/t_generator.cc
deleted file mode 100644
index 7f5daf4..0000000
--- a/compiler/cpp/src/generate/t_generator.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include "t_generator.h"
-using namespace std;
-
-/**
- * Top level program generation function. Calls the generator subclass methods
- * for preparing file streams etc. then iterates over all the parts of the
- * program to perform the correct actions.
- *
- * @param program The thrift program to compile into C++ source
- */
-void t_generator::generate_program() {
-  // Initialize the generator
-  init_generator();
-
-  // Generate enums
-  vector<t_enum*> enums = program_->get_enums();
-  vector<t_enum*>::iterator en_iter;
-  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-    generate_enum(*en_iter);
-  }
-
-  // Generate typedefs
-  vector<t_typedef*> typedefs = program_->get_typedefs();
-  vector<t_typedef*>::iterator td_iter;
-  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-    generate_typedef(*td_iter);
-  }
-
-  // Generate structs, exceptions, and unions in declared order
-  vector<t_struct*> objects = program_->get_objects();
-
-  vector<t_struct*>::iterator o_iter;
-  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-    generate_forward_declaration(*o_iter);
-  }
-  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-    if ((*o_iter)->is_xception()) {
-      generate_xception(*o_iter);
-    } else {
-      generate_struct(*o_iter);
-    }
-  }
-
-  // Generate constants
-  vector<t_const*> consts = program_->get_consts();
-  generate_consts(consts);
-
-  // Generate services
-  vector<t_service*> services = program_->get_services();
-  vector<t_service*>::iterator sv_iter;
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    service_name_ = get_service_name(*sv_iter);
-    generate_service(*sv_iter);
-  }
-
-  // Close the generator
-  close_generator();
-}
-
-string t_generator::escape_string(const string& in) const {
-  string result = "";
-  for (string::const_iterator it = in.begin(); it < in.end(); it++) {
-    std::map<char, std::string>::const_iterator res = escape_.find(*it);
-    if (res != escape_.end()) {
-      result.append(res->second);
-    } else {
-      result.push_back(*it);
-    }
-  }
-  return result;
-}
-
-void t_generator::generate_consts(vector<t_const*> consts) {
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    generate_const(*c_iter);
-  }
-}
-
-void t_generator::generate_docstring_comment(ostream& out,
-                                             const string& comment_start,
-                                             const string& line_prefix,
-                                             const string& contents,
-                                             const string& comment_end) {
-  if (comment_start != "")
-    indent(out) << comment_start;
-  stringstream docs(contents, ios_base::in);
-  while (!(docs.eof() || docs.fail())) {
-    char line[1024];
-    docs.getline(line, 1024);
-
-    // Just prnt a newline when the line & prefix are empty.
-    if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) {
-      out << std::endl;
-    } else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line
-      indent(out) << line_prefix << line << std::endl;
-    }
-  }
-  if (comment_end != "")
-    indent(out) << comment_end;
-}
-
-void t_generator_registry::register_generator(t_generator_factory* factory) {
-  gen_map_t& the_map = get_generator_map();
-  if (the_map.find(factory->get_short_name()) != the_map.end()) {
-    failure("Duplicate generators for language \"%s\"!\n", factory->get_short_name().c_str());
-  }
-  the_map[factory->get_short_name()] = factory;
-}
-
-void t_generator::parse_options(const string& options,
-                                string& language,
-                                map<string, string>& parsed_options) {
-  string::size_type colon = options.find(':');
-  language = options.substr(0, colon);
-
-  if (colon != string::npos) {
-    string::size_type pos = colon + 1;
-    while (pos != string::npos && pos < options.size()) {
-      string::size_type next_pos = options.find(',', pos);
-      string option = options.substr(pos, next_pos - pos);
-      pos = ((next_pos == string::npos) ? next_pos : next_pos + 1);
-
-      string::size_type separator = option.find('=');
-      string key, value;
-      if (separator == string::npos) {
-        key = option;
-        value = "";
-      } else {
-        key = option.substr(0, separator);
-        value = option.substr(separator + 1);
-      }
-
-      parsed_options[key] = value;
-    }
-  }
-}
-
-t_generator* t_generator_registry::get_generator(t_program* program,
-                                                 const string& language,
-                                                 const map<string, string>& parsed_options,
-                                                 const std::string& options) {
-  gen_map_t& the_map = get_generator_map();
-  gen_map_t::iterator iter = the_map.find(language);
-
-  if (iter == the_map.end()) {
-    return NULL;
-  }
-
-  return iter->second->get_generator(program, parsed_options, options);
-}
-
-t_generator* t_generator_registry::get_generator(t_program* program, const string& options) {
-  string language;
-  map<string, string> parsed_options;
-  t_generator::parse_options(options, language, parsed_options);
-  return get_generator(program, language, parsed_options, options);
-}
-
-t_generator_registry::gen_map_t& t_generator_registry::get_generator_map() {
-  // http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
-  static gen_map_t* the_map = new gen_map_t();
-  return *the_map;
-}
-
-t_generator_factory::t_generator_factory(const std::string& short_name,
-                                         const std::string& long_name,
-                                         const std::string& documentation)
-  : short_name_(short_name), long_name_(long_name), documentation_(documentation) {
-  t_generator_registry::register_generator(this);
-}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_generator.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_generator.h b/compiler/cpp/src/generate/t_generator.h
deleted file mode 100644
index 590efdb..0000000
--- a/compiler/cpp/src/generate/t_generator.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_GENERATOR_H
-#define T_GENERATOR_H
-
-#include <string>
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include "parse/t_program.h"
-#include "common.h"
-#include "t_generator_registry.h"
-#include "version.h"
-
-/**
- * Base class for a thrift code generator. This class defines the basic
- * routines for code generation and contains the top level method that
- * dispatches code generation across various components.
- *
- */
-class t_generator {
-public:
-  t_generator(t_program* program) {
-    tmp_ = 0;
-    indent_ = 0;
-    program_ = program;
-    program_name_ = get_program_name(program);
-    escape_['\n'] = "\\n";
-    escape_['\r'] = "\\r";
-    escape_['\t'] = "\\t";
-    escape_['"'] = "\\\"";
-    escape_['\\'] = "\\\\";
-  }
-
-  virtual ~t_generator() {}
-
-  /**
-   * Framework generator method that iterates over all the parts of a program
-   * and performs general actions. This is implemented by the base class and
-   * should not normally be overwritten in the subclasses.
-   */
-  virtual void generate_program();
-
-  const t_program* get_program() const { return program_; }
-
-  void generate_docstring_comment(std::ostream& out,
-                                  const std::string& comment_start,
-                                  const std::string& line_prefix,
-                                  const std::string& contents,
-                                  const std::string& comment_end);
-
-  static void parse_options(const std::string& options, std::string& language,
-                     std::map<std::string, std::string>& parsed_options);
-
-  /**
-   * check whether sub-namespace declaraction is used by generator.
-   * e.g. allow
-   * namespace py.twisted bar
-   * to specify namespace to use when -gen py:twisted is specified.
-   * Will be called with subnamespace, i.e. is_valid_namespace("twisted")
-   * will be called for the above example.
-   */
-  static bool is_valid_namespace(const std::string& sub_namespace) {
-    (void)sub_namespace;
-    return false;
-  }
-
-  /**
-   * Escape string to use one in generated sources.
-   */
-  virtual std::string escape_string(const std::string& in) const;
-
-  std::string get_escaped_string(t_const_value* constval) {
-    return escape_string(constval->get_string());
-  }
-
-protected:
-  /**
-   * Optional methods that may be imlemented by subclasses to take necessary
-   * steps at the beginning or end of code generation.
-   */
-
-  virtual void init_generator() {}
-  virtual void close_generator() {}
-
-  virtual void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Pure virtual methods implemented by the generator subclasses.
-   */
-
-  virtual void generate_typedef(t_typedef* ttypedef) = 0;
-  virtual void generate_enum(t_enum* tenum) = 0;
-  virtual void generate_const(t_const* tconst) { (void)tconst; }
-  virtual void generate_struct(t_struct* tstruct) = 0;
-  virtual void generate_service(t_service* tservice) = 0;
-  virtual void generate_forward_declaration(t_struct*) {}
-  virtual void generate_xception(t_struct* txception) {
-    // By default exceptions are the same as structs
-    generate_struct(txception);
-  }
-
-  /**
-   * Method to get the program name, may be overridden
-   */
-  virtual std::string get_program_name(t_program* tprogram) { return tprogram->get_name(); }
-
-  /**
-   * Method to get the service name, may be overridden
-   */
-  virtual std::string get_service_name(t_service* tservice) { return tservice->get_name(); }
-
-  /**
-   * Get the current output directory
-   */
-  virtual std::string get_out_dir() const {
-    if (program_->is_out_path_absolute()) {
-      return program_->get_out_path() + "/";
-    }
-
-    return program_->get_out_path() + out_dir_base_ + "/";
-  }
-
-  /**
-   * Creates a unique temporary variable name, which is just "name" with a
-   * number appended to it (i.e. name35)
-   */
-  std::string tmp(std::string name) {
-    std::ostringstream out;
-    out << name << tmp_++;
-    return out.str();
-  }
-
-  /**
-   * Generates a comment about this code being autogenerated, using C++ style
-   * comments, which are also fair game in Java / PHP, yay!
-   *
-   * @return C-style comment mentioning that this file is autogenerated.
-   */
-  virtual std::string autogen_comment() {
-    return std::string("/**\n") + " * " + autogen_summary() + "\n" + " *\n"
-           + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
-           + " *  @generated\n" + " */\n";
-  }
-
-  virtual std::string autogen_summary() {
-    return std::string("Autogenerated by Thrift Compiler (") + THRIFT_VERSION + ")";
-  }
-
-  /**
-   * Indentation level modifiers
-   */
-
-  void indent_up() { ++indent_; }
-
-  void indent_down() { --indent_; }
-
-  /**
-   * Indentation print function
-   */
-  std::string indent() {
-    std::string ind = "";
-    int i;
-    for (i = 0; i < indent_; ++i) {
-      ind += indent_str();
-    }
-    return ind;
-  }
-
-  /**
-   * Indentation utility wrapper
-   */
-  std::ostream& indent(std::ostream& os) { return os << indent(); }
-
-  /**
-   * Capitalization helpers
-   */
-  std::string capitalize(std::string in) {
-    in[0] = toupper(in[0]);
-    return in;
-  }
-  std::string decapitalize(std::string in) {
-    in[0] = tolower(in[0]);
-    return in;
-  }
-  static std::string lowercase(std::string in) {
-    for (size_t i = 0; i < in.size(); ++i) {
-      in[i] = tolower(in[i]);
-    }
-    return in;
-  }
-  static std::string uppercase(std::string in) {
-    for (size_t i = 0; i < in.size(); ++i) {
-      in[i] = toupper(in[i]);
-    }
-    return in;
-  }
-  /**
-   * Transforms a camel case string to an equivalent one separated by underscores
-   * e.g. aMultiWord -> a_multi_word
-   *      someName   -> some_name
-   *      CamelCase  -> camel_case
-   *      name       -> name
-   *      Name       -> name
-   */
-  std::string underscore(std::string in) {
-    in[0] = tolower(in[0]);
-    for (size_t i = 1; i < in.size(); ++i) {
-      if (isupper(in[i])) {
-        in[i] = tolower(in[i]);
-        in.insert(i, "_");
-      }
-    }
-    return in;
-  }
-  /**
-    * Transforms a string with words separated by underscores to a camel case equivalent
-    * e.g. a_multi_word -> aMultiWord
-    *      some_name    ->  someName
-    *      name         ->  name
-    */
-  std::string camelcase(std::string in) {
-    std::ostringstream out;
-    bool underscore = false;
-
-    for (size_t i = 0; i < in.size(); i++) {
-      if (in[i] == '_') {
-        underscore = true;
-        continue;
-      }
-      if (underscore) {
-        out << (char)toupper(in[i]);
-        underscore = false;
-        continue;
-      }
-      out << in[i];
-    }
-
-    return out.str();
-  }
-
-public:
-  /**
-   * Get the true type behind a series of typedefs.
-   */
-  static const t_type* get_true_type(const t_type* type) { return type->get_true_type(); }
-  static t_type* get_true_type(t_type* type) { return type->get_true_type(); }
-
-protected:
-  /**
-   * The program being generated
-   */
-  t_program* program_;
-
-  /**
-   * Quick accessor for formatted program name that is currently being
-   * generated.
-   */
-  std::string program_name_;
-
-  /**
-   * Quick accessor for formatted service name that is currently being
-   * generated.
-   */
-  std::string service_name_;
-
-  /**
-   * Output type-specifc directory name ("gen-*")
-   */
-  std::string out_dir_base_;
-
-  /**
-   * Map of characters to escape in string literals.
-   */
-  std::map<char, std::string> escape_;
-
-  virtual std::string indent_str() const {
-    return "  ";
-  }
-
-private:
-  /**
-   * Current code indentation level
-   */
-  int indent_;
-
-  /**
-   * Temporary variable counter, for making unique variable names
-   */
-  int tmp_;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_generator_registry.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_generator_registry.h b/compiler/cpp/src/generate/t_generator_registry.h
deleted file mode 100644
index 1f02167..0000000
--- a/compiler/cpp/src/generate/t_generator_registry.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_GENERATOR_REGISTRY_H
-#define T_GENERATOR_REGISTRY_H
-
-class t_generator;
-
-/**
- * A factory for producing generator classes of a particular language.
- *
- * This class is also responsible for:
- *  - Registering itself with the generator registry.
- *  - Providing documentation for the generators it produces.
- */
-class t_generator_factory {
-public:
-  t_generator_factory(const std::string& short_name,
-                      const std::string& long_name,
-                      const std::string& documentation);
-
-  virtual ~t_generator_factory() {}
-
-  virtual t_generator* get_generator(
-      // The program to generate.
-      t_program* program,
-      // Note: parsed_options will not exist beyond the call to get_generator.
-      const std::map<std::string, std::string>& parsed_options,
-      // Note: option_string might not exist beyond the call to get_generator.
-      const std::string& option_string) = 0;
-
-  virtual bool is_valid_namespace(const std::string& sub_namespace) = 0;
-
-  std::string get_short_name() { return short_name_; }
-  std::string get_long_name() { return long_name_; }
-  std::string get_documentation() { return documentation_; }
-
-private:
-  std::string short_name_;
-  std::string long_name_;
-  std::string documentation_;
-};
-
-template <typename generator>
-class t_generator_factory_impl : public t_generator_factory {
-public:
-  t_generator_factory_impl(const std::string& short_name,
-                           const std::string& long_name,
-                           const std::string& documentation)
-    : t_generator_factory(short_name, long_name, documentation) {}
-
-  virtual t_generator* get_generator(t_program* program,
-                                     const std::map<std::string, std::string>& parsed_options,
-                                     const std::string& option_string) {
-    return new generator(program, parsed_options, option_string);
-  }
-
-  virtual bool is_valid_namespace(const std::string& sub_namespace) {
-    return generator::is_valid_namespace(sub_namespace);
-  }
-};
-
-class t_generator_registry {
-public:
-  static void register_generator(t_generator_factory* factory);
-
-  static t_generator* get_generator(t_program* program, const std::string& options);
-  static t_generator* get_generator(t_program* program,
-                                    const std::string& laugnage,
-                                    const std::map<std::string, std::string>& parsed_options,
-                                    const std::string& options);
-
-  typedef std::map<std::string, t_generator_factory*> gen_map_t;
-  static gen_map_t& get_generator_map();
-
-private:
-  t_generator_registry();
-  t_generator_registry(const t_generator_registry&);
-};
-
-#define THRIFT_REGISTER_GENERATOR(language, long_name, doc)                                        \
-  class t_##language##_generator_factory_impl                                                      \
-      : public t_generator_factory_impl<t_##language##_generator> {                                \
-  public:                                                                                          \
-    t_##language##_generator_factory_impl()                                                        \
-      : t_generator_factory_impl<t_##language##_generator>(#language, long_name, doc) {}           \
-  };                                                                                               \
-  static t_##language##_generator_factory_impl _registerer;
-
-#endif


[08/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_javame_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_javame_generator.cc b/compiler/cpp/src/thrift/generate/t_javame_generator.cc
new file mode 100644
index 0000000..aa7eccf
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_javame_generator.cc
@@ -0,0 +1,3295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <sstream>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <stdexcept>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Java code generator.
+ *
+ */
+class t_javame_generator : public t_oop_generator {
+public:
+  t_javame_generator(t_program* program,
+                     const std::map<std::string, std::string>& parsed_options,
+                     const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)parsed_options;
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option javame:" + iter->first;
+    }
+
+    out_dir_base_ = "gen-javame";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_union(t_struct* tunion);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ofstream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false);
+  std::string render_const_value(std::ofstream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_java_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_java_struct_definition(std::ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false,
+                                       bool in_class = false,
+                                       bool is_result = false);
+  void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_java_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  std::string get_java_type_string(t_type* type);
+  void generate_reflection_setters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_reflection_getters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
+  void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
+
+  void generate_function_helpers(t_function* tfunction);
+  std::string get_cap_name(std::string name);
+  std::string generate_isset_check(t_field* field);
+  std::string generate_isset_check(std::string field);
+  void generate_isset_set(ofstream& out, t_field* field);
+  std::string isset_field_id(t_field* field);
+
+  void generate_primitive_service_interface(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  void generate_java_union(t_struct* tstruct);
+  void generate_union_constructor(ofstream& out, t_struct* tstruct);
+  void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
+  void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
+  void generate_check_type(ofstream& out, t_struct* tstruct);
+  void generate_read_value(ofstream& out, t_struct* tstruct);
+  void generate_write_value(ofstream& out, t_struct* tstruct);
+  void generate_get_field_desc(ofstream& out, t_struct* tstruct);
+  void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
+  void generate_get_field_name(ofstream& out, t_struct* tstruct);
+
+  void generate_union_comparisons(ofstream& out, t_struct* tstruct);
+  void generate_union_hashcode(ofstream& out, t_struct* tstruct);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_java_doc(std::ofstream& out, t_field* field);
+
+  void generate_java_doc(std::ofstream& out, t_doc* tdoc);
+
+  void generate_java_doc(std::ofstream& out, t_function* tdoc);
+
+  void generate_java_docstring_comment(std::ofstream& out, string contents);
+
+  void generate_deep_copy_container(std::ofstream& out,
+                                    std::string source_name_p1,
+                                    std::string source_name_p2,
+                                    std::string result_name,
+                                    t_type* type);
+  void generate_deep_copy_non_container(std::ofstream& out,
+                                        std::string source_name,
+                                        std::string dest_name,
+                                        t_type* type);
+
+  bool has_bit_vector(t_struct* tstruct);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string java_package();
+  std::string java_type_imports();
+  std::string java_thrift_imports();
+  std::string type_name(t_type* ttype,
+                        bool in_container = false,
+                        bool in_init = false,
+                        bool skip_generic = false);
+  std::string base_type_name(t_base_type* tbase, bool in_container = false);
+  std::string declare_field(t_field* tfield, bool init = false);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct, bool include_types = true);
+  std::string type_to_enum(t_type* ttype);
+  std::string get_enum_class_name(t_type* type);
+  void generate_struct_desc(ofstream& out, t_struct* tstruct);
+  void generate_field_descs(ofstream& out, t_struct* tstruct);
+  std::string box_type(t_type* type, string value);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()
+           || ttype->is_enum();
+  }
+
+  std::string constant_name(std::string name);
+
+private:
+  /**
+   * File streams
+   */
+
+  std::string package_name_;
+  std::ofstream f_service_;
+  std::string package_dir_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_javame_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  package_name_ = program_->get_namespace("java");
+
+  string dir = package_name_;
+  string subdir = get_out_dir();
+  string::size_type loc;
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  package_dir_ = subdir;
+}
+
+/**
+ * Packages the generated file
+ *
+ * @return String of the package, i.e. "package org.apache.thriftdemo;"
+ */
+string t_javame_generator::java_package() {
+  if (!package_name_.empty()) {
+    return string("package ") + package_name_ + ";\n\n";
+  }
+  return "";
+}
+
+/**
+ * Prints standard java imports
+ *
+ * @return List of imports for Java types that are used in here
+ */
+string t_javame_generator::java_type_imports() {
+  return string() + "import java.util.Hashtable;\n" + "import java.util.Vector;\n"
+         + "import java.util.Enumeration;\n\n";
+}
+
+/**
+ * Prints standard java imports
+ *
+ * @return List of imports necessary for thrift
+ */
+string t_javame_generator::java_thrift_imports() {
+  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
+         + "import org.apache.thrift.transport.*;\n" + "import org.apache.thrift.protocol.*;\n\n";
+}
+
+/**
+ * Nothing in Java
+ */
+void t_javame_generator::close_generator() {
+}
+
+/**
+ * Generates a typedef. This is not done in Java, since it does
+ * not support arbitrary name replacements, and it'd be a wacky waste
+ * of overhead to make wrapper classes.
+ *
+ * @param ttypedef The type definition
+ */
+void t_javame_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Enums are a class with a set of static constants.
+ *
+ * @param tenum The enumeration
+ */
+void t_javame_generator::generate_enum(t_enum* tenum) {
+  // Make output file
+  string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".java";
+  ofstream f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  // Comment and package it
+  f_enum << autogen_comment() << java_package();
+
+  generate_java_doc(f_enum, tenum);
+  indent(f_enum) << "public class " << tenum->get_name() << " implements org.apache.thrift.TEnum ";
+  scope_up(f_enum);
+  f_enum << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    generate_java_doc(f_enum, *c_iter);
+    indent(f_enum) << "public static final " << tenum->get_name() << " " << (*c_iter)->get_name()
+                   << " = new " << tenum->get_name() << "(" << value << ");" << endl;
+  }
+  f_enum << endl;
+
+  // Field for thriftCode
+  indent(f_enum) << "private final int value;" << endl << endl;
+
+  indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl;
+  indent(f_enum) << "  this.value = value;" << endl;
+  indent(f_enum) << "}" << endl << endl;
+
+  indent(f_enum) << "/**" << endl;
+  indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL."
+                 << endl;
+  indent(f_enum) << " */" << endl;
+  indent(f_enum) << "public int getValue() {" << endl;
+  indent(f_enum) << "  return value;" << endl;
+  indent(f_enum) << "}" << endl << endl;
+
+  indent(f_enum) << "/**" << endl;
+  indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL."
+                 << endl;
+  indent(f_enum) << " * @return null if the value is not found." << endl;
+  indent(f_enum) << " */" << endl;
+  indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl;
+
+  indent_up();
+
+  indent(f_enum) << "switch (value) {" << endl;
+  indent_up();
+
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "case " << value << ":" << endl;
+    indent(f_enum) << "  return " << (*c_iter)->get_name() << ";" << endl;
+  }
+
+  indent(f_enum) << "default:" << endl;
+  indent(f_enum) << "  return null;" << endl;
+
+  indent_down();
+
+  indent(f_enum) << "}" << endl;
+
+  indent_down();
+
+  indent(f_enum) << "}" << endl;
+
+  scope_down(f_enum);
+
+  f_enum.close();
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_javame_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.java";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  // Print header
+  f_consts << autogen_comment() << java_package() << java_type_imports();
+
+  f_consts << "public class " << program_name_ << "Constants {" << endl << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value(),
+                      false);
+  }
+  indent_down();
+  indent(f_consts) << "}" << endl;
+  f_consts.close();
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+void t_javame_generator::print_const_value(std::ofstream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value,
+                                           bool in_static,
+                                           bool defval) {
+  type = get_true_type(type);
+
+  indent(out);
+  if (!defval) {
+    out << (in_static ? "" : "public static final ") << type_name(type) << " ";
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    out << name << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    out << name << " = " << render_const_value(out, name, type, value) << ";" << endl << endl;
+  } else if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    out << name << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "static {" << endl;
+      indent_up();
+    }
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << ".";
+      std::string cap_name = get_cap_name(v_iter->first->get_string());
+      out << "set" << cap_name << "(" << val << ");" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    out << name << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "static {" << endl;
+      indent_up();
+    }
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << ".put(" << box_type(ktype, key) << ", " << box_type(vtype, val) << ");"
+                  << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "static {" << endl;
+      indent_up();
+    }
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      if (type->is_list()) {
+        indent(out) << name << ".addElement(" << box_type(etype, val) << ");" << endl;
+      } else {
+        indent(out) << name << ".put(" << box_type(etype, val) << ", " << box_type(etype, val)
+                    << ");" << endl;
+      }
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_javame_generator::render_const_value(ofstream& out,
+                                              string name,
+                                              t_type* type,
+                                              t_const_value* value) {
+  (void)name;
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+      render << "(byte)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I16:
+      render << "(short)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "L";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << "(double)" << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << type_name(type, false, false) << "." << value->get_identifier();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+string t_javame_generator::box_type(t_type* type, string value) {
+  if (type->is_base_type()) {
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_BOOL:
+      return "new Boolean(" + value + ")";
+    case t_base_type::TYPE_I8:
+      return "new Byte(" + value + ")";
+    case t_base_type::TYPE_I16:
+      return "new Short(" + value + ")";
+    case t_base_type::TYPE_I32:
+      return "new Integer(" + value + ")";
+    case t_base_type::TYPE_I64:
+      return "new Long(" + value + ")";
+    case t_base_type::TYPE_DOUBLE:
+      return "new Double(" + value + ")";
+    default:
+      break;
+    }
+  }
+  return value;
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This will be a TBase
+ * implementor.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_struct(t_struct* tstruct) {
+  if (tstruct->is_union()) {
+    generate_java_union(tstruct);
+  } else {
+    generate_java_struct(tstruct, false);
+  }
+}
+
+/**
+ * Exceptions are structs, but they inherit from Exception
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_xception(t_struct* txception) {
+  generate_java_struct(txception, true);
+}
+
+/**
+ * Java struct definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_struct(t_struct* tstruct, bool is_exception) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
+
+  generate_java_struct_definition(f_struct, tstruct, is_exception);
+  f_struct.close();
+}
+
+/**
+ * Java union definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_union(t_struct* tstruct) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
+
+  generate_java_doc(f_struct, tstruct);
+
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+
+  indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
+                   << " extends TUnion ";
+
+  scope_up(f_struct);
+
+  generate_struct_desc(f_struct, tstruct);
+  generate_field_descs(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_constructor(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_abstract_methods(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_getters_and_setters(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_comparisons(f_struct, tstruct);
+
+  f_struct << endl;
+
+  generate_union_hashcode(f_struct, tstruct);
+
+  f_struct << endl;
+
+  scope_down(f_struct);
+
+  f_struct.close();
+}
+
+void t_javame_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public " << type_name(tstruct) << "() {" << endl;
+  indent(out) << "  super();" << endl;
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "public " << type_name(tstruct) << "(_Fields setField, Object value) {" << endl;
+  indent(out) << "  super(setField, value);" << endl;
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {"
+              << endl;
+  indent(out) << "  super(other);" << endl;
+  indent(out) << "}" << endl;
+
+  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
+  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
+  indent(out) << "}" << endl << endl;
+
+  // generate "constructors" for each field
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "("
+                << type_name((*m_iter)->get_type()) << " value) {" << endl;
+    indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl;
+    indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl;
+    indent(out) << "  return x;" << endl;
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+void t_javame_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  bool first = true;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if (first) {
+      first = false;
+    } else {
+      out << endl;
+    }
+
+    t_field* field = (*m_iter);
+
+    generate_java_doc(out, field);
+    indent(out) << "public " << type_name(field->get_type()) << " get"
+                << get_cap_name(field->get_name()) << "() {" << endl;
+    indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
+                << endl;
+    indent(out) << "    return (" << type_name(field->get_type(), true) << ")getFieldValue();"
+                << endl;
+    indent(out) << "  } else {" << endl;
+    indent(out) << "    throw new RuntimeException(\"Cannot get field '" << field->get_name()
+                << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
+                << endl;
+    indent(out) << "  }" << endl;
+    indent(out) << "}" << endl;
+
+    out << endl;
+
+    generate_java_doc(out, field);
+    indent(out) << "public void set" << get_cap_name(field->get_name()) << "("
+                << type_name(field->get_type()) << " value) {" << endl;
+    if (type_can_be_null(field->get_type())) {
+      indent(out) << "  if (value == null) throw new NullPointerException();" << endl;
+    }
+    indent(out) << "  setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl;
+    indent(out) << "  value_ = value;" << endl;
+    indent(out) << "}" << endl;
+  }
+}
+
+void t_javame_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
+  generate_check_type(out, tstruct);
+  out << endl;
+  generate_read_value(out, tstruct);
+  out << endl;
+  generate_write_value(out, tstruct);
+  out << endl;
+  generate_get_field_desc(out, tstruct);
+  out << endl;
+  generate_get_struct_desc(out, tstruct);
+  out << endl;
+}
+
+void t_javame_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
+  indent(out)
+      << "protected void checkType(_Fields setField, Object value) throws ClassCastException {"
+      << endl;
+  indent_up();
+
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent(out) << "  if (value instanceof " << type_name(field->get_type(), true, false, true)
+                << ") {" << endl;
+    indent(out) << "    break;" << endl;
+    indent(out) << "  }" << endl;
+    indent(out) << "  throw new ClassCastException(\"Was expecting value of type "
+                << type_name(field->get_type(), true, false) << " for field '" << field->get_name()
+                << "', but got \" + value.getClass().getSimpleName());" << endl;
+    // do the real check here
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_javame_generator::generate_read_value(ofstream& out, t_struct* tstruct) {
+  indent(out) << "protected Object readValue(TProtocol iprot, TField field) throws TException {"
+              << endl;
+
+  indent_up();
+
+  indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl;
+  indent(out) << "if (setField != null) {" << endl;
+  indent_up();
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {"
+                << endl;
+    indent_up();
+    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";"
+                << endl;
+    generate_deserialize_field(out, field, "");
+    indent(out) << "return " << field->get_name() << ";" << endl;
+    indent_down();
+    indent(out) << "} else {" << endl;
+    indent(out) << "  TProtocolUtil.skip(iprot, field.type);" << endl;
+    indent(out) << "  return null;" << endl;
+    indent(out) << "}" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalStateException(\"setField wasn't null, but didn't match any "
+                 "of the case statements!\");" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "} else {" << endl;
+  indent_up();
+  indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl;
+  indent(out) << "return null;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_javame_generator::generate_write_value(ofstream& out, t_struct* tstruct) {
+  indent(out) << "protected void writeValue(TProtocol oprot) throws TException {" << endl;
+
+  indent_up();
+
+  indent(out) << "switch (setField_) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = ("
+                << type_name(field->get_type(), true, false) << ")value_;" << endl;
+    generate_serialize_field(out, field, "");
+    indent(out) << "return;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + "
+                 "setField_);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+
+  indent(out) << "}" << endl;
+}
+
+void t_javame_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
+  indent(out) << "protected TField getFieldDesc(_Fields setField) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  indent(out) << "switch (setField) {" << endl;
+  indent_up();
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
+    indent(out) << "  return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl;
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_javame_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "protected TStruct getStructDesc() {" << endl;
+  indent(out) << "  return STRUCT_DESC;" << endl;
+  indent(out) << "}" << endl;
+}
+
+void t_javame_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
+  // equality
+  indent(out) << "public boolean equals(Object other) {" << endl;
+  indent(out) << "  if (other instanceof " << tstruct->get_name() << ") {" << endl;
+  indent(out) << "    return equals((" << tstruct->get_name() << ")other);" << endl;
+  indent(out) << "  } else {" << endl;
+  indent(out) << "    return false;" << endl;
+  indent(out) << "  }" << endl;
+  indent(out) << "}" << endl;
+
+  out << endl;
+
+  indent(out) << "public boolean equals(" << tstruct->get_name() << " other) {" << endl;
+  indent(out) << "  return other != null && getSetField() == other.getSetField() && "
+                 "getFieldValue().equals(other.getFieldValue());" << endl;
+  indent(out) << "}" << endl;
+  out << endl;
+
+  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
+  indent(out) << "  int lastComparison = TBaseHelper.compareTo(getSetField(), other.getSetField());"
+              << endl;
+  indent(out) << "  if (lastComparison == 0) {" << endl;
+  indent(out) << "    return TBaseHelper.compareTo(getFieldValue(), other.getFieldValue());"
+              << endl;
+  indent(out) << "  }" << endl;
+  indent(out) << "  return lastComparison;" << endl;
+  indent(out) << "}" << endl;
+  out << endl;
+}
+
+void t_javame_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
+  (void)tstruct;
+  indent(out) << "/**" << endl;
+  indent(out)
+      << " * If you'd like this to perform more respectably, use the hashcode generator option."
+      << endl;
+  indent(out) << " */" << endl;
+  indent(out) << "public int hashCode() {" << endl;
+  indent(out) << "  return 0;" << endl;
+  indent(out) << "}" << endl;
+}
+
+/**
+ * Java struct definition. This has various parameters, as it could be
+ * generated standalone or inside another class as a helper. If it
+ * is a helper than it is a static class.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param in_class     If inside a class, needs to be static class
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_javame_generator::generate_java_struct_definition(ofstream& out,
+                                                         t_struct* tstruct,
+                                                         bool is_exception,
+                                                         bool in_class,
+                                                         bool is_result) {
+  generate_java_doc(out, tstruct);
+
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+
+  indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class "
+              << tstruct->get_name() << " ";
+
+  if (is_exception) {
+    out << "extends Exception ";
+  }
+  out << "implements TBase ";
+
+  scope_up(out);
+
+  generate_struct_desc(out, tstruct);
+
+  // Members are public for -java, private for -javabean
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << endl;
+
+  generate_field_descs(out, tstruct);
+
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "private ";
+    out << declare_field(*m_iter, false) << endl;
+  }
+
+  // isset data
+  if (members.size() > 0) {
+    out << endl;
+
+    indent(out) << "// isset id assignments" << endl;
+
+    int i = 0;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (!type_can_be_null((*m_iter)->get_type())) {
+        indent(out) << "private static final int " << isset_field_id(*m_iter) << " = " << i << ";"
+                    << endl;
+        i++;
+      }
+    }
+
+    if (i > 0) {
+      indent(out) << "private boolean[] __isset_vector = new boolean[" << i << "];" << endl;
+    }
+
+    out << endl;
+  }
+
+  bool all_optional_members = true;
+
+  // Default constructor
+  indent(out) << "public " << tstruct->get_name() << "() {" << endl;
+  indent_up();
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL) {
+      print_const_value(out,
+                        "this." + (*m_iter)->get_name(),
+                        t,
+                        (*m_iter)->get_value(),
+                        true,
+                        true);
+    }
+    if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+      all_optional_members = false;
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  if (!members.empty() && !all_optional_members) {
+    // Full constructor for all fields
+    indent(out) << "public " << tstruct->get_name() << "(" << endl;
+    indent_up();
+    bool first = true;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+        if (!first) {
+          out << "," << endl;
+        }
+        first = false;
+        indent(out) << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
+      }
+    }
+    out << ")" << endl;
+    indent_down();
+    indent(out) << "{" << endl;
+    indent_up();
+    indent(out) << "this();" << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+        indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";"
+                    << endl;
+        generate_isset_set(out, (*m_iter));
+      }
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+
+  // copy constructor
+  indent(out) << "/**" << endl;
+  indent(out) << " * Performs a deep copy on <i>other</i>." << endl;
+  indent(out) << " */" << endl;
+  indent(out) << "public " << tstruct->get_name() << "(" << tstruct->get_name() << " other) {"
+              << endl;
+  indent_up();
+
+  if (has_bit_vector(tstruct)) {
+    indent(out) << "System.arraycopy(other.__isset_vector, 0, __isset_vector, 0, "
+                   "other.__isset_vector.length);" << endl;
+  }
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = (*m_iter);
+    std::string field_name = field->get_name();
+    t_type* type = field->get_type();
+    bool can_be_null = type_can_be_null(type);
+
+    if (can_be_null) {
+      indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl;
+      indent_up();
+    }
+
+    if (type->is_container()) {
+      generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type);
+      indent(out) << "this." << field_name << " = __this__" << field_name << ";" << endl;
+    } else {
+      indent(out) << "this." << field_name << " = ";
+      generate_deep_copy_non_container(out, "other." + field_name, field_name, type);
+      out << ";" << endl;
+    }
+
+    if (can_be_null) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // clone method, so that you can deep copy an object when you don't know its class.
+  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
+  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
+  indent(out) << "}" << endl << endl;
+
+  generate_java_struct_clear(out, tstruct);
+
+  generate_java_bean_boilerplate(out, tstruct);
+  generate_generic_field_getters_setters(out, tstruct);
+
+  generate_java_struct_equality(out, tstruct);
+  generate_java_struct_compare_to(out, tstruct);
+
+  generate_java_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_java_struct_result_writer(out, tstruct);
+  } else {
+    generate_java_struct_writer(out, tstruct);
+  }
+  generate_java_struct_tostring(out, tstruct);
+  generate_java_validator(out, tstruct);
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates equals methods and a hashCode method for a structure.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_struct_equality(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public boolean equals(Object that) {" << endl;
+  indent_up();
+  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl
+      << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent()
+      << "  return this.equals((" << tstruct->get_name() << ")that);" << endl << indent()
+      << "return false;" << endl;
+  scope_down(out);
+  out << endl;
+
+  out << indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl;
+  indent_up();
+  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    out << endl;
+
+    t_type* t = get_true_type((*m_iter)->get_type());
+    // Most existing Thrift code does not use isset or optional/required,
+    // so we treat "default" fields as required.
+    bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
+    bool can_be_null = type_can_be_null(t);
+    string name = (*m_iter)->get_name();
+
+    string this_present = "true";
+    string that_present = "true";
+    string unequal;
+
+    if (is_optional || can_be_null) {
+      this_present += " && this." + generate_isset_check(*m_iter);
+      that_present += " && that." + generate_isset_check(*m_iter);
+    }
+
+    out << indent() << "boolean this_present_" << name << " = " << this_present << ";" << endl
+        << indent() << "boolean that_present_" << name << " = " << that_present << ";" << endl
+        << indent() << "if ("
+        << "this_present_" << name << " || that_present_" << name << ") {" << endl;
+    indent_up();
+    out << indent() << "if (!("
+        << "this_present_" << name << " && that_present_" << name << "))" << endl << indent()
+        << "  return false;" << endl;
+
+    if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
+      unequal = "TBaseHelper.compareTo(this." + name + ", that." + name + ") != 0";
+    } else if (can_be_null) {
+      unequal = "!this." + name + ".equals(that." + name + ")";
+    } else {
+      unequal = "this." + name + " != that." + name;
+    }
+
+    out << indent() << "if (" << unequal << ")" << endl << indent() << "  return false;" << endl;
+
+    scope_down(out);
+  }
+  out << endl;
+  indent(out) << "return true;" << endl;
+  scope_down(out);
+  out << endl;
+
+  out << indent() << "public int hashCode() {" << endl;
+  indent_up();
+  indent(out) << "return 0;" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_javame_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public int compareTo(Object otherObject) {" << endl;
+  //  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
+  indent_up();
+
+  indent(out) << "if (!getClass().equals(otherObject.getClass())) {" << endl;
+  indent(out) << "  return getClass().getName().compareTo(otherObject.getClass().getName());"
+              << endl;
+  indent(out) << "}" << endl;
+  out << endl;
+  indent(out) << type_name(tstruct) << " other = (" << type_name(tstruct) << ")otherObject;";
+
+  indent(out) << "int lastComparison = 0;" << endl;
+  out << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* field = *m_iter;
+    indent(out) << "lastComparison = TBaseHelper.compareTo(" << generate_isset_check(field)
+                << ", other." << generate_isset_check(field) << ");" << endl;
+    indent(out) << "if (lastComparison != 0) {" << endl;
+    indent(out) << "  return lastComparison;" << endl;
+    indent(out) << "}" << endl;
+
+    indent(out) << "if (" << generate_isset_check(field) << ") {" << endl;
+    if (field->get_type()->is_struct() || field->get_type()->is_xception()) {
+      indent(out) << "  lastComparison = this." << field->get_name() << ".compareTo(other."
+                  << field->get_name() << ");" << endl;
+    } else {
+      indent(out) << "  lastComparison = TBaseHelper.compareTo(this." << field->get_name()
+                  << ", other." << field->get_name() << ");" << endl;
+    }
+
+    indent(out) << "  if (lastComparison != 0) {" << endl;
+    indent(out) << "    return lastComparison;" << endl;
+    indent(out) << "  }" << endl;
+    indent(out) << "}" << endl;
+  }
+
+  indent(out) << "return 0;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_struct_reader(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public void read(TProtocol iprot) throws TException {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables and read struct header
+  out << indent() << "TField field;" << endl << indent() << "iprot.readStructBegin();" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "field = iprot.readFieldBegin();" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (field.type == TType.STOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (field.id) {" << endl;
+
+  indent_up();
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ": // "
+                << constant_name((*f_iter)->get_name()) << endl;
+    indent_up();
+    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "this.");
+    generate_isset_set(out, *f_iter);
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+        << endl << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  TProtocolUtil.skip(iprot, field.type);" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd();" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl;
+
+  out << indent() << "iprot.readStructEnd();" << endl;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+// generates java method to perform various checks
+// (e.g. check that all required fields are set)
+void t_javame_generator::generate_java_validator(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public void validate() throws TException {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      out << indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl << indent()
+          << "  throw new TProtocolException(\"Required field '" << (*f_iter)->get_name()
+          << "' is unset! Struct:\" + toString());" << endl << indent() << "}" << endl << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_struct_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public void write(TProtocol oprot) throws TException {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl << endl;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
+      indent_up();
+    }
+    bool optional = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (optional) {
+      indent(out) << "if (" << generate_isset_check((*f_iter)) << ") {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    if (optional) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+  // Write the struct map
+  out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
+      << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct,
+ * which is a function result. These fields are only written
+ * if they are set in the Isset array, and only one of them
+ * can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public void write(TProtocol oprot) throws TException {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
+
+    indent_up();
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+  // Write the struct map
+  out << endl << indent() << "oprot.writeFieldStop();" << endl << indent()
+      << "oprot.writeStructEnd();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+void t_javame_generator::generate_reflection_getters(ostringstream& out,
+                                                     t_type* type,
+                                                     string field_name,
+                                                     string cap_name) {
+  indent(out) << "case " << constant_name(field_name) << ":" << endl;
+  indent_up();
+
+  if (type->is_base_type() && !type->is_string()) {
+    t_base_type* base_type = (t_base_type*)type;
+
+    indent(out) << "return new " << type_name(type, true, false) << "("
+                << (base_type->is_bool() ? "is" : "get") << cap_name << "());" << endl << endl;
+  } else {
+    indent(out) << "return get" << cap_name << "();" << endl << endl;
+  }
+
+  indent_down();
+}
+
+void t_javame_generator::generate_reflection_setters(ostringstream& out,
+                                                     t_type* type,
+                                                     string field_name,
+                                                     string cap_name) {
+  indent(out) << "case " << constant_name(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "if (value == null) {" << endl;
+  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
+  indent(out) << "} else {" << endl;
+  indent(out) << "  set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl;
+  indent(out) << "}" << endl;
+  indent(out) << "break;" << endl << endl;
+
+  indent_down();
+}
+
+void t_javame_generator::generate_generic_field_getters_setters(std::ofstream& out,
+                                                                t_struct* tstruct) {
+  (void)out;
+  std::ostringstream getter_stream;
+  std::ostringstream setter_stream;
+
+  // build up the bodies of both the getter and setter at once
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    indent_up();
+    generate_reflection_setters(setter_stream, type, field_name, cap_name);
+    generate_reflection_getters(getter_stream, type, field_name, cap_name);
+    indent_down();
+  }
+}
+
+/**
+ * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
+ * for the given struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_bean_boilerplate(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    if (type->is_container()) {
+      // Method to return the size of the collection
+      indent(out) << "public int get" << cap_name;
+      out << get_cap_name("size() {") << endl;
+
+      indent_up();
+      indent(out) << "return (this." << field_name << " == null) ? 0 : "
+                  << "this." << field_name << ".size();" << endl;
+      indent_down();
+      indent(out) << "}" << endl << endl;
+    }
+
+    if (type->is_set() || type->is_list()) {
+
+      t_type* element_type;
+      if (type->is_set()) {
+        element_type = ((t_set*)type)->get_elem_type();
+      } else {
+        element_type = ((t_list*)type)->get_elem_type();
+      }
+
+      // Iterator getter for sets and lists
+      indent(out) << "public Enumeration get" << cap_name;
+      out << get_cap_name("Enumeration() {") << endl;
+
+      indent_up();
+      indent(out) << "return (this." << field_name << " == null) ? null : "
+                  << "this." << field_name << ".elements();" << endl;
+      indent_down();
+      indent(out) << "}" << endl << endl;
+
+      // Add to set or list, create if the set/list is null
+      indent(out);
+      out << "public void add" << get_cap_name("to");
+      out << cap_name << "(" << type_name(element_type) << " elem) {" << endl;
+
+      indent_up();
+      indent(out) << "if (this." << field_name << " == null) {" << endl;
+      indent_up();
+      indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();"
+                  << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+      if (type->is_set()) {
+        indent(out) << "this." << field_name << ".put(" << box_type(element_type, "elem") << ", "
+                    << box_type(element_type, "elem") << ");" << endl;
+      } else {
+        indent(out) << "this." << field_name << ".addElement(" << box_type(element_type, "elem")
+                    << ");" << endl;
+      }
+      indent_down();
+      indent(out) << "}" << endl << endl;
+
+    } else if (type->is_map()) {
+      // Put to map
+      t_type* key_type = ((t_map*)type)->get_key_type();
+      t_type* val_type = ((t_map*)type)->get_val_type();
+
+      indent(out);
+      out << "public void putTo" << cap_name << "(" << type_name(key_type, true) << " key, "
+          << type_name(val_type, true) << " val) {" << endl;
+
+      indent_up();
+      indent(out) << "if (this." << field_name << " == null) {" << endl;
+      indent_up();
+      indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();"
+                  << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+      indent(out) << "this." << field_name << ".put(key, val);" << endl;
+      indent_down();
+      indent(out) << "}" << endl << endl;
+    }
+
+    // Simple getter
+    generate_java_doc(out, field);
+    indent(out) << "public " << type_name(type);
+    if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) {
+      out << " is";
+    } else {
+      out << " get";
+    }
+    out << cap_name << "() {" << endl;
+    indent_up();
+    indent(out) << "return this." << field_name << ";" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Simple setter
+    generate_java_doc(out, field);
+    indent(out) << "public ";
+    out << "void";
+    out << " set" << cap_name << "(" << type_name(type) << " " << field_name << ") {" << endl;
+    indent_up();
+    indent(out) << "this." << field_name << " = " << field_name << ";" << endl;
+    generate_isset_set(out, field);
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Unsetter
+    indent(out) << "public void unset" << cap_name << "() {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "this." << field_name << " = null;" << endl;
+    } else {
+      indent(out) << "__isset_vector[" << isset_field_id(field) << "] = false;" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // isSet method
+    indent(out) << "/** Returns true if field " << field_name
+                << " is set (has been assigned a value) and false otherwise */" << endl;
+    indent(out) << "public boolean is" << get_cap_name("set") << cap_name << "() {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "return this." << field_name << " != null;" << endl;
+    } else {
+      indent(out) << "return __isset_vector[" << isset_field_id(field) << "];" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    indent(out) << "public void set" << cap_name << get_cap_name("isSet") << "(boolean value) {"
+                << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "if (!value) {" << endl;
+      indent(out) << "  this." << field_name << " = null;" << endl;
+      indent(out) << "}" << endl;
+    } else {
+      indent(out) << "__isset_vector[" << isset_field_id(field) << "] = value;" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a toString() method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_javame_generator::generate_java_struct_tostring(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public String toString() {" << endl;
+  indent_up();
+
+  out << indent() << "StringBuffer sb = new StringBuffer(\"" << tstruct->get_name() << "(\");"
+      << endl;
+  out << indent() << "boolean first = true;" << endl << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+
+    t_field* field = (*f_iter);
+
+    if (!first) {
+      indent(out) << "if (!first) sb.append(\", \");" << endl;
+    }
+    indent(out) << "sb.append(\"" << (*f_iter)->get_name() << ":\");" << endl;
+    bool can_be_null = type_can_be_null(field->get_type());
+    if (can_be_null) {
+      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
+      indent(out) << "  sb.append(\"null\");" << endl;
+      indent(out) << "} else {" << endl;
+      indent_up();
+    }
+
+    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
+      indent(out) << "TBaseHelper.toString(this." << field->get_name() << ", sb);" << endl;
+    } else {
+      indent(out) << "sb.append(this." << (*f_iter)->get_name() << ");" << endl;
+    }
+
+    if (can_be_null) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    indent(out) << "first = false;" << endl;
+
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    first = false;
+  }
+  out << indent() << "sb.append(\")\");" << endl << indent() << "return sb.toString();" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Returns a string with the java representation of the given thrift type
+ * (e.g. for the type struct it returns "TType.STRUCT")
+ */
+std::string t_javame_generator::get_java_type_string(t_type* type) {
+  if (type->is_list()) {
+    return "TType.LIST";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_enum()) {
+    return "TType.ENUM";
+  } else if (type->is_typedef()) {
+    return get_java_type_string(((t_typedef*)type)->get_type());
+  } else if (type->is_base_type()) {
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_VOID:
+      return "TType.VOID";
+      break;
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+      break;
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+      break;
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+      break;
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+      break;
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+      break;
+    default:
+      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
+                               + "\" passed to t_javame_generator::get_java_type_string!");
+      break; // This should never happen!
+    }
+  } else {
+    throw std::runtime_error(
+        "Unknown thrift type \"" + type->get_name()
+        + "\" passed to t_javame_generator::get_java_type_string!"); // This should never happen!
+  }
+}
+
+void t_javame_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+  out << endl;
+  indent_up();
+  indent_up();
+  if (type->is_struct() || type->is_xception()) {
+    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type) << ".class";
+  } else if (type->is_container()) {
+    if (type->is_list()) {
+      indent(out) << "new ListMetaData(TType.LIST, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else if (type->is_set()) {
+      indent(out) << "new SetMetaData(TType.SET, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else { // map
+      indent(out) << "new MapMetaData(TType.MAP, ";
+      t_type* key_type = ((t_map*)type)->get_key_type();
+      t_type* val_type = ((t_map*)type)->get_val_type();
+      generate_field_value_meta_data(out, key_type);
+      out << ", ";
+      generate_field_value_meta_data(out, val_type);
+    }
+  } else if (type->is_enum()) {
+    indent(out) << "new EnumMetaData(TType.ENUM, " << type_name(type) << ".class";
+  } else {
+    indent(out) << "new FieldValueMetaData(" << get_java_type_string(type);
+    if (type->is_typedef()) {
+      indent(out) << ", \"" << ((t_typedef*)type)->get_symbolic() << "\"";
+    }
+  }
+  out << ")";
+  indent_down();
+  indent_down();
+}
+
+/**
+ * Generates a thrift service. In C++, this comprises an entirely separate
+ * header and source file. The header file defines the methods and includes
+ * the data types defined in the main header file, and the implementation
+ * file contains implementations of the basic printer and default interfaces.
+ *
+ * @param tservice The service definition
+ */
+void t_javame_generator::generate_service(t_service* tservice) {
+  // Make output file
+  string f_service_name = package_dir_ + "/" + service_name_ + ".java";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
+
+  f_service_ << "public class " << service_name_ << " {" << endl << endl;
+  indent_up();
+
+  // Generate the three main parts of the service
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+
+  indent_down();
+  f_service_ << "}" << endl;
+  f_service_.close();
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_javame_generator::generate_primitive_service_interface(t_service* tservice) {
+  f_service_ << indent() << "public interface Iface extends " << service_name_ << "Iface { }"
+             << endl << endl;
+
+  string f_interface_name = package_dir_ + "/" + service_name_ + "Iface.java";
+  std::ofstream f_iface;
+  f_iface.open(f_interface_name.c_str());
+
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends_iface = " extends " + type_name(tservice->get_extends()) + "Iface";
+  }
+
+  f_iface << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
+  generate_java_doc(f_iface, tservice);
+  f_iface << "public interface " << service_name_ << "Iface" << extends_iface << " {" << endl
+          << endl;
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_java_doc(f_iface, *f_iter);
+    f_iface << "  public " << function_signature(*f_iter) << ";" << endl << endl;
+  }
+  f_iface << "}" << endl << endl;
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_javame_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_iface = " extends " + extends + ".Iface";
+  }
+
+  generate_java_doc(f_service_, tservice);
+  f_service_ << indent() << "public interface Iface" << extends_iface << " {" << endl << endl;
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_java_doc(f_service_, *f_iter);
+    indent(f_service_) << "public " << function_signature(*f_iter) << ";" << endl << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates structs for all the service args and return types
+ *
+ * @param tservice The service
+ */
+void t_javame_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_java_struct_definition(f_service_, ts, false, true);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_javame_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = " extends " + extends + ".Client";
+  }
+
+  indent(f_service_) << "public static class Client" << extends_client
+                     << " implements TServiceClient, Iface {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public Client(TProtocol prot)" << endl;
+  scope_up(f_service_);
+  indent(f_service_) << "this(prot, prot);" << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)" << endl;
+  scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl;
+  } else {
+    f_service_ << indent() << "super(iprot, oprot);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent()
+               << "protected TProtocol oprot_;" << endl << endl << indent()
+               << "protected int seqid_;" << endl << endl;
+
+    indent(f_service_) << "public TProtocol getInputProtocol()" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.iprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    indent(f_service_) << "public TProtocol getOutputProtocol()" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.oprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "send_" << funname << "(";
+
+    // Get the struct of function call params
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    // Declare the function arguments
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << (*fld_iter)->get_name();
+    }
+    f_service_ << ");" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "recv_" << funname << "();" << endl;
+    }
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    t_function send_function(g_type_void,
+                             string("send_") + (*f_iter)->get_name(),
+                             (*f_iter)->get_arglist());
+
+    string argsname = (*f_iter)->get_name() + "_args";
+
+    // Open function
+    indent(f_service_) << "public " << function_signature(&send_function) << endl;
+    scope_up(f_service_);
+
+    // Serialize the request
+    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
+               << ", ++seqid_));" << endl << indent() << argsname << " args = new " << argsname
+               << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args.set" << get_cap_name((*fld_iter)->get_name()) << "("
+                 << (*fld_iter)->get_name() << ");" << endl;
+    }
+
+    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
+               << "oprot_.writeMessageEnd();" << endl << indent()
+               << "oprot_.getTransport().flush();" << endl;
+
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      string resultname = (*f_iter)->get_name() + "_result";
+
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      // Open function
+      indent(f_service_) << "public " << function_signature(&recv_function) << endl;
+      scope_up(f_service_);
+
+      f_service_ << indent() << "TMessage msg = iprot_.readMessageBegin();" << endl << indent()
+                 << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent()
+                 << "  TApplicationException x = TApplicationException.read(iprot_);" << endl
+                 << indent() << "  iprot_.readMessageEnd();" << endl << indent() << "  throw x;"
+                 << endl << indent() << "}" << endl << indent() << "if (msg.seqid != seqid_) {"
+                 << endl << indent()
+                 << "  throw new TApplicationException(TApplicationException.BAD_SEQUENCE_ID, \""
+                 << (*f_iter)->get_name() << " failed: out of sequence response\");" << endl
+                 << indent() << "}" << endl << indent() << resultname << " result = new "
+                 << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl
+                 << indent() << "iprot_.readMessageEnd();" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl
+                   << indent() << "  return result.success;" << endl << indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl
+                   << indent() << "  throw result." << (*x_iter)->get_name() << ";" << endl
+                   << indent() << "}" << endl;
+      }
+
+      // If you get here it's an exception, unless a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return;" << endl;
+      } else {
+        f_service_ << indent()
+                   << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \""
+                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
+      }
+
+      // Close function
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl;
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_javame_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // Extends stuff
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = " extends " + extends + ".Processor";
+  }
+
+  // Generate the header portion
+  indent(f_service_) << "public static class Processor" << extends_processor
+                     << " implements TProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public Processor(Iface iface)" << endl;
+  scope_up(f_service_);
+  if (!extends.empty()) {
+    f_service_ << indent() << "super(iface);" << endl;
+  }
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "processMap_.put(\"" << (*f_iter)->get_name() << "\", new "
+               << (*f_iter)->get_name() << "());" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_
+        << indent() << "protected static interface ProcessFunction {" << endl << indent()
+        << "  public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException;"
+        << endl << indent() << "}" << endl << endl;
+  }
+
+  f_service_ << indent() << "private Iface iface_;" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected final Hashtable processMap_ = new Hashtable();" << endl;
+  }
+
+  f_service_ << endl;
+
+  // Generate the server implementation
+  indent(f_service_) << "public boolean process(TProtocol iprot, TProtocol oprot) throws TException"
+                     << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "TMessage msg = iprot.readMessageBegin();" << endl;
+
+  // TODO(mcslee): validate message, was the seqid etc. legit?
+
+  f_service_
+      << indent() << "ProcessFunction fn = (ProcessFunction)processMap_.get(msg.name);" << endl
+      << indent() << "if (fn == null) {" << endl << indent()
+      << "  TProtocolUtil.skip(iprot, TType.STRUCT);" << endl << indent()
+      << "  iprot.readMessageEnd();" << endl << indent()
+      << "  TApplicationException x = new "
+         "TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid method name: "
+         "'\"+msg.name+\"'\");" << endl << indent()
+      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
+      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
+      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
+      << "  return true;" << endl << indent() << "}" << endl << indent()
+      << "fn.process(msg.seqid, iprot, oprot);" << endl;
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_javame_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  t_struct result(program_, tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_java_struct_definition(f_service_, &result, false, true, true);
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_javame_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open class
+  indent(f_service_) << "private class " << tfunction->get_name() << " implements ProcessFunction {"
+                     << endl;
+  indent_up();
+
+  // Open function
+  indent(f_service_)
+      << "public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException"
+      << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl << indent()
+             << "try {" << endl;
+  indent_up();
+  f_service_ << indent() << "args.read(iprot);" << endl;
+  indent_down();
+  f_service_ << indent() << "} catch (TProtocolException e) {" << endl;
+  indent_up();
+  f_service_ << indent() << "iprot.readMessageEnd();" << endl << indent()
+             << "TApplicationException x = new "
+                "TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());"
+             << endl << indent() << "oprot.writeMessageBegin(new TMessage(\""
+             << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl << indent()
+             << "x.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();" << endl
+             << indent() << "oprot.getTransport().flush();" << endl << indent() << "return;"
+             << endl;
+  indent_down();
+  f_service_ << indent() << "}" << endl;
+  f_service_ << indent() << "iprot.readMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try {" << endl;
+    indent_up();
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result.success = ";
+  }
+  f_service_ << "iface_." << tfunction->get_name() << "(";
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << (*f_iter)->get_name();
+  }
+  f_service_ << ");" << endl;
+
+  // Set isset on success field
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()
+      && !type_can_be_null(tfunction->get_returntype())) {
+    f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet")
+               << "(true);" << endl;
+  }
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}";
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << " catch (" << type_name((*x_iter)->get_type(), false, false) << " "
+                 << (*x_iter)->get_name() << ") {" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                   << (*x_iter)->get_name() << ";" << endl;
+        indent_down();
+        f_service_ << indent() << "}";
+      } else {
+        f_service_ << "}";
+      }
+    }
+    f_service_ << " catch (Throwable th) {" << endl;
+    indent_up();
+    f_service_ << indent() << "TApplicationException x = new "
+                              "TApplicationException(TApplicationException.INTERNAL_ERROR, "
+                              "\"Internal error processing " << tfunction->get_name() << "\");"
+               << endl << indent() << "oprot.writeMessageBegin(new TMessage(\""
+               << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl
+               << indent() << "x.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();"
+               << endl << indent() << "oprot.getTransport().flush();" << endl << indent()
+               << "return;" << endl;
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "return;" << endl;
+    scope_down(f_service_);
+
+    // Close class
+    indent_down();
+    f_service_ << indent() << "}" << endl << endl;
+    return;
+  }
+
+  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
+             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
+             << "oprot.getTransport().flush();" << endl;
+
+  // Close function
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Close class
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param prefix The variable name or container for this field
+ */
+void t_javame_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type()) {
+    indent(out) << name << " = iprot.";
+
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "compiler error: cannot serialize void field in a struct: " + name;
+      break;
+    case t_base_type::TYPE_STRING:
+      if (!((t_base_type*)type)->is_binary()) {
+        out << "readString();";
+      } else {
+        out << "readBinary();";
+      }
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << "readBool();";
+      break;
+    case t_base_type::TYPE_I8:
+      out << "readByte();";
+      break;
+    case t_base_type::TYPE_I16:
+      out << "readI16();";
+      break;
+    case t_base_type::TYPE_I32:
+      out << "readI32();";
+      break;
+    case t_base_type::TYPE_I64:
+      out << "readI64();";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      out << "readDouble();";
+      break;
+    default:
+      throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
+    }
+    out << endl;
+  } else if (type->is_enum()) {
+    indent(out) << name << " = "
+                << type_nam

<TRUNCATED>

[39/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_haxe_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_haxe_generator.cc b/compiler/cpp/src/generate/t_haxe_generator.cc
deleted file mode 100644
index d15958e..0000000
--- a/compiler/cpp/src/generate/t_haxe_generator.cc
+++ /dev/null
@@ -1,2981 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <sstream>
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <cctype>
-
-#include <sys/stat.h>
-#include <stdexcept>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Haxe code generator.
- *
- */
-class t_haxe_generator : public t_oop_generator {
-public:
-  t_haxe_generator(t_program* program,
-                   const std::map<std::string, std::string>& parsed_options,
-                   const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    callbacks_ = false;
-    rtti_ = false;
-    buildmacro_ = "";
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("callbacks") == 0) {
-        callbacks_ = true;
-      } else if( iter->first.compare("rtti") == 0) {
-        rtti_ = true;
-      } else if( iter->first.compare("buildmacro") == 0) {
-        buildmacro_ = (iter->second);
-      } else {
-        throw "unknown option haxe:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-haxe";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(std::ofstream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool in_static,
-                         bool defval = false);
-  std::string render_const_value(ofstream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result = false);
-
-  void generate_haxe_struct_definition(std::ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_xception = false,
-                                       bool is_result = false);
-  // removed -- equality,compare_to
-  void generate_haxe_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_meta_data_map(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
-  std::string get_haxe_type_string(t_type* type);
-  void generate_reflection_setters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_reflection_getters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_property_getters_setters(std::ofstream& out, t_struct* tstruct);
-
-  void generate_function_helpers(t_function* tfunction);
-  std::string get_cap_name(std::string name);
-  std::string generate_isset_check(t_field* field);
-  std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
-  // removed std::string isset_field_id(t_field* field);
-
-  void generate_service_interface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-  void generate_service_method_signature(t_function* tfunction, bool is_interface);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map);
-
-  void generate_haxe_doc(std::ofstream& out, t_doc* tdoc);
-  void generate_haxe_doc(std::ofstream& out, t_function* tdoc);
-
-  void generate_rtti_decoration(std::ofstream& out);
-  void generate_macro_decoration(std::ofstream& out);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string haxe_package();
-  std::string haxe_type_imports();
-  std::string haxe_thrift_imports();
-  std::string haxe_thrift_gen_imports(t_struct* tstruct, string& imports);
-  std::string haxe_thrift_gen_imports(t_service* tservice);
-  std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false);
-  std::string base_type_name(t_base_type* tbase, bool in_container = false);
-  std::string declare_field(t_field* tfield, bool init = false);
-  std::string function_signature_callback(t_function* tfunction);
-  std::string function_signature_normal(t_function* tfunction);
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string get_enum_class_name(t_type* type);
-  string generate_service_method_onsuccess(t_function* tfunction, bool as_type, bool omit_name);
-  void generate_service_method_signature_callback(t_function* tfunction, bool is_interface);
-  void generate_service_method_signature_normal(t_function* tfunction, bool is_interface);
-
-  bool type_can_be_null(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    if (ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()) {
-      return true;
-    }
-
-    if (ttype->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_STRING:
-        // case t_base_type::TYPE_I64:  - Int64 is not really nullable, even though it behaved that
-        // way before Haxe 3.2.0
-        return true;
-      default:
-        return false;
-      }
-    }
-
-    return false;
-  }
-
-  std::string constant_name(std::string name);
-
-private:
-  bool callbacks_;
-  bool rtti_;
-  string buildmacro_;
-
-  /**
-   * File streams
-   */
-
-  std::string package_name_;
-  std::ofstream f_service_;
-  std::string package_dir_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_haxe_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  package_name_ = program_->get_namespace("haxe");
-
-  // Haxe package names are lowercase
-  if (package_name_.length() > 0) {
-    package_name_[0] = tolower(package_name_[0]);
-    size_t index = package_name_.find('.');
-    while (index != std::string::npos) {
-      if (++index < package_name_.length()) {
-        package_name_[index] = tolower(package_name_[index]);
-      }
-      index = package_name_.find('.', index);
-    }
-  }
-
-  string dir = package_name_;
-  string subdir = get_out_dir();
-  string::size_type loc;
-  while ((loc = dir.find(".")) != string::npos) {
-    subdir = subdir + "/" + dir.substr(0, loc);
-    MKDIR(subdir.c_str());
-    dir = dir.substr(loc + 1);
-  }
-  if (dir.size() > 0) {
-    subdir = subdir + "/" + dir;
-    MKDIR(subdir.c_str());
-  }
-
-  package_dir_ = subdir;
-}
-
-/**
- * Packages the generated file
- *
- * @return String of the package, i.e. "package org.apache.thriftdemo;"
- */
-string t_haxe_generator::haxe_package() {
-  if (!package_name_.empty()) {
-    return string("package ") + package_name_;
-  }
-  return "package";
-}
-
-/**
- * Prints standard haxe imports
- *
- * @return List of imports for haxe types that are used in here
- */
-string t_haxe_generator::haxe_type_imports() {
-  return string() + "import org.apache.thrift.helper.*;\n" + "import haxe.io.Bytes;\n"
-         + "import haxe.ds.IntMap;\n" + "import haxe.ds.StringMap;\n"
-         + "import haxe.ds.ObjectMap;\n" + "\n" + "#if flash\n"
-         + "import flash.errors.ArgumentError;\n" + "#end\n" + "\n";
-}
-
-/**
- * Prints standard haxe imports
- *
- * @return List of imports necessary for thrift
- */
-string t_haxe_generator::haxe_thrift_imports() {
-  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
-         + "import org.apache.thrift.protocol.*;\n" + "\n";
-}
-
-/**
- * Prints imports needed for a given type
- *
- * @return List of imports necessary for a given t_struct
- */
-string t_haxe_generator::haxe_thrift_gen_imports(t_struct* tstruct, string& imports) {
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  // For each type check if it is from a different namespace
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_program* program = (*m_iter)->get_type()->get_program();
-    if (program != NULL && program != program_) {
-      string package = program->get_namespace("haxe");
-      if (!package.empty()) {
-        if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) {
-          imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n");
-        }
-      }
-    }
-  }
-  return imports;
-}
-
-/**
- * Prints imports needed for a given type
- *
- * @return List of imports necessary for a given t_service
- */
-string t_haxe_generator::haxe_thrift_gen_imports(t_service* tservice) {
-  string imports;
-  const vector<t_function*>& functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-
-  // For each type check if it is from a different namespace
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_program* program = (*f_iter)->get_returntype()->get_program();
-    if (program != NULL && program != program_) {
-      string package = program->get_namespace("haxe");
-      if (!package.empty()) {
-        if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) {
-          imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name()
-                         + ";\n");
-        }
-      }
-    }
-
-    haxe_thrift_gen_imports((*f_iter)->get_arglist(), imports);
-    haxe_thrift_gen_imports((*f_iter)->get_xceptions(), imports);
-  }
-
-  return imports;
-}
-
-/**
- * Nothing in haxe
- */
-void t_haxe_generator::close_generator() {
-}
-
-/**
- * Generates a typedef. This is not done in haxe, since it does
- * not support arbitrary name replacements, and it'd be a wacky waste
- * of overhead to make wrapper classes.
- *
- * @param ttypedef The type definition
- */
-void t_haxe_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Enums are a class with a set of static constants.
- *
- * @param tenum The enumeration
- */
-void t_haxe_generator::generate_enum(t_enum* tenum) {
-  // Make output file
-  string f_enum_name = package_dir_ + "/" + get_cap_name(tenum->get_name()) + ".hx";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
-
-  // Comment and package it
-  f_enum << autogen_comment() << haxe_package() << ";" << endl << endl;
-
-  // Add haxe imports
-  f_enum << string() + "import org.apache.thrift.helper.*;" << endl << endl;
-
-  generate_rtti_decoration(f_enum);
-  generate_macro_decoration(f_enum);
-  indent(f_enum) << "class " << get_cap_name(tenum->get_name()) << " ";
-  scope_up(f_enum);
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << "public static inline var " << (*c_iter)->get_name() << " : Int = " << value
-                   << ";" << endl;
-  }
-
-  // Create a static Set with all valid values for this enum
-  f_enum << endl;
-
-  indent(f_enum) << "public static var VALID_VALUES = { new IntSet( [";
-  indent_up();
-  bool firstValue = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    // populate set
-    f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name();
-    firstValue = false;
-  }
-  indent_down();
-  f_enum << "]); };" << endl;
-
-  indent(f_enum) << "public static var VALUES_TO_NAMES = { [";
-  indent_up();
-  firstValue = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    f_enum << (firstValue ? "" : ",") << endl;
-    indent(f_enum) << (*c_iter)->get_name() << " => \"" << (*c_iter)->get_name() << "\"";
-    firstValue = false;
-  }
-  f_enum << endl;
-  indent_down();
-  indent(f_enum) << "]; };" << endl;
-
-  scope_down(f_enum); // end class
-
-  f_enum.close();
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_haxe_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-
-  string f_consts_name = package_dir_ + "/" + get_cap_name(program_name_) + "Constants.hx";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  // Print header
-  f_consts << autogen_comment() << haxe_package() << ";" << endl << endl;
-
-  f_consts << endl;
-
-  f_consts << haxe_type_imports();
-
-  generate_rtti_decoration(f_consts);
-  generate_macro_decoration(f_consts);
-  indent(f_consts) << "class " << get_cap_name(program_name_) << "Constants {" << endl << endl;
-  indent_up();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    print_const_value(f_consts,
-                      (*c_iter)->get_name(),
-                      (*c_iter)->get_type(),
-                      (*c_iter)->get_value(),
-                      false);
-  }
-  indent_down();
-  indent(f_consts) << "}" << endl;
-  f_consts.close();
-}
-
-void t_haxe_generator::print_const_value(std::ofstream& out,
-                                         string name,
-                                         t_type* type,
-                                         t_const_value* value,
-                                         bool in_static,
-                                         bool defval) {
-  type = get_true_type(type);
-
-  indent(out);
-  if (!defval) {
-    out << (in_static ? "var " : "public static inline var  ");
-  }
-  if (type->is_base_type()) {
-    string v2 = render_const_value(out, name, type, value);
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = " << v2 << ";" << endl << endl;
-  } else if (type->is_enum()) {
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = " << value->get_integer() << ";" << endl << endl;
-  } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
-        << endl;
-    if (!in_static) {
-      indent(out) << "{" << endl;
-      indent_up();
-      indent(out) << "new function() : Void {" << endl;
-      indent_up();
-    }
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(out, name, field_type, v_iter->second);
-      indent(out) << name << ".";
-      out << v_iter->first->get_string() << " = " << val << ";" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}();" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_map()) {
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "{" << endl;
-      indent_up();
-      indent(out) << "new function() : Void {" << endl;
-      indent_up();
-    }
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, name, ktype, v_iter->first);
-      string val = render_const_value(out, name, vtype, v_iter->second);
-      indent(out) << name << "[" << key << "] = " << val << ";" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}();" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_list() || type->is_set()) {
-    out << name;
-    if (!defval) {
-      out << ":" << type_name(type);
-    }
-    out << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "{" << endl;
-      indent_up();
-      indent(out) << "new function() : Void {" << endl;
-      indent_up();
-    }
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      indent(out) << name << "." << (type->is_list() ? "push" : "add") << "(" << val << ");"
-                  << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}();" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else {
-    throw "compiler error: no const of type " + type->get_name();
-  }
-}
-
-string t_haxe_generator::render_const_value(ofstream& out,
-                                            string name,
-                                            t_type* type,
-                                            t_const_value* value) {
-  (void)name;
-  type = get_true_type(type);
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-      render << "(byte)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I16:
-      render << "(short)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << value->get_integer() << "L";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << "(double)" << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << value->get_integer();
-  } else {
-    string t = tmp("tmp");
-    print_const_value(out, t, type, value, true);
-    render << t;
-  }
-
-  return render.str();
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is a class
- * with data members, read(), write(), and an inner Isset class.
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_struct(t_struct* tstruct) {
-  generate_haxe_struct(tstruct, false);
-}
-
-/**
- * Exceptions are structs, but they inherit from Exception
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_xception(t_struct* txception) {
-  generate_haxe_struct(txception, true);
-}
-
-/**
- * Haxe struct definition.
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result) {
-  // Make output file
-  string f_struct_name = package_dir_ + "/" + get_cap_name(tstruct->get_name()) + ".hx";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << haxe_package() << ";" << endl;
-
-  f_struct << endl;
-
-  string imports;
-
-  f_struct << haxe_type_imports() << haxe_thrift_imports()
-           << haxe_thrift_gen_imports(tstruct, imports) << endl;
-
-  generate_haxe_struct_definition(f_struct, tstruct, is_exception, is_result);
-
-  f_struct.close();
-}
-
-/**
- * haxe struct definition. This has various parameters, as it could be
- * generated standalone or inside another class as a helper. If it
- * is a helper than it is a static class.
- *
- * @param tstruct      The struct definition
- * @param is_exception Is this an exception?
- * @param in_class     If inside a class, needs to be static class
- * @param is_result    If this is a result it needs a different writer
- */
-void t_haxe_generator::generate_haxe_struct_definition(ofstream& out,
-                                                       t_struct* tstruct,
-                                                       bool is_exception,
-                                                       bool is_result) {
-  generate_haxe_doc(out, tstruct);
-
-  string clsname = get_cap_name(tstruct->get_name());
-
-  generate_rtti_decoration(out);
-  generate_macro_decoration(out);
-  indent(out) << "class " << clsname << " ";
-
-  if (is_exception) {
-    out << "extends TException ";
-  }
-  out << "implements TBase ";
-
-  scope_up(out);
-  indent(out) << endl;
-
-  indent(out) << "static var STRUCT_DESC = { new TStruct(\"" << tstruct->get_name() << "\"); };"
-              << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "static var " << constant_name((*m_iter)->get_name())
-                << "_FIELD_DESC = { new TField(\"" << (*m_iter)->get_name() << "\", "
-                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << "); };"
-                << endl;
-  }
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_haxe_doc(out, *m_iter);
-    // indent(out) << "private var _" << (*m_iter)->get_name() + " : " +
-    // type_name((*m_iter)->get_type()) << ";" << endl;
-    indent(out) << "@:isVar" << endl;
-    indent(out) << "public var "
-                << (*m_iter)->get_name() + "(get,set) : "
-                   + get_cap_name(type_name((*m_iter)->get_type())) << ";" << endl;
-  }
-
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "inline static var " << upcase_string((*m_iter)->get_name())
-                << "_FIELD_ID : Int = " << (*m_iter)->get_key() << ";" << endl;
-  }
-
-  out << endl;
-
-  // Inner Isset class
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (!type_can_be_null((*m_iter)->get_type())) {
-        indent(out) << "private var __isset_" << (*m_iter)->get_name() << " : Bool = false;"
-                    << endl;
-      }
-    }
-  }
-
-  out << endl;
-
-  // Static initializer to populate global class to struct metadata map
-  if (false) {
-    // TODO: reactivate when needed
-    generate_haxe_meta_data_map(out, tstruct);
-    indent(out) << "{" << endl;
-    indent_up();
-    indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);"
-                << endl;
-    indent_down();
-    indent(out) << "}" << endl;
-    indent(out) << "}" << endl;
-  }
-
-  // Default constructor
-  indent(out) << "public function new() {" << endl;
-  indent_up();
-  if (is_exception) {
-    indent(out) << "super();" << endl;
-  }
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if ((*m_iter)->get_value() != NULL) {
-      indent(out) << "this." << (*m_iter)->get_name() << " = "
-                  << (*m_iter)->get_value()->get_integer() << ";" << endl;
-    }
-  }
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  generate_property_getters_setters(out, tstruct);
-  generate_generic_field_getters_setters(out, tstruct);
-  generate_generic_isset_method(out, tstruct);
-
-  generate_haxe_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_haxe_struct_result_writer(out, tstruct);
-  } else {
-    generate_haxe_struct_writer(out, tstruct);
-  }
-  generate_haxe_struct_tostring(out, tstruct);
-  generate_haxe_validator(out, tstruct);
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generates a function to read all the fields of the struct.
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_haxe_struct_reader(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public function read( iprot : TProtocol) : Void {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "iprot.IncrementRecursionDepth();" << endl;
-  indent(out) << "try" << endl;
-  scope_up(out);
-
-  // Declare stack tmp variables and read struct header
-  out << indent() << "var field : TField;" << endl << indent() << "iprot.readStructBegin();"
-      << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-  scope_up(out);
-
-  // Read beginning field marker
-  indent(out) << "field = iprot.readFieldBegin();" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if (field.type == TType.STOP) { " << endl;
-  indent_up();
-  indent(out) << "break;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  // Switch statement on the field we are reading
-  indent(out) << "switch (field.id)" << endl;
-
-  scope_up(out);
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << "_FIELD_ID:" << endl;
-    indent_up();
-    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-    indent_up();
-
-    generate_deserialize_field(out, *f_iter, "this.");
-    generate_isset_set(out, *f_iter);
-    indent_down();
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
-        << endl << indent() << "}" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  out << indent() << "default:" << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
-      << endl;
-
-  scope_down(out);
-
-  // Read field end marker
-  indent(out) << "iprot.readFieldEnd();" << endl;
-
-  scope_down(out);
-
-  out << indent() << "iprot.readStructEnd();" << endl << endl;
-
-  indent(out) << "iprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-  indent(out) << "catch(e:Dynamic)" << endl;
-  scope_up(out);
-  indent(out) << "iprot.DecrementRecursionDepth();" << endl;
-  indent(out) << "throw e;" << endl;
-  scope_down(out);
-
-  // check for required fields of primitive type
-  // (which can be checked here but not in the general validate method)
-  out << endl << indent() << "// check for required fields of primitive type, which can't be "
-                             "checked in the validate method" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
-      out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent()
-          << "  throw new TProtocolException(TProtocolException.UNKNOWN, \"Required field '"
-          << (*f_iter)->get_name()
-          << "' was not found in serialized data! Struct: \" + toString());" << endl << indent()
-          << "}" << endl;
-    }
-  }
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl;
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-// generates haxe method to perform various checks
-// (e.g. check that all required fields are set)
-void t_haxe_generator::generate_haxe_validator(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public function validate() : Void {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "// check for required fields" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      if (type_can_be_null((*f_iter)->get_type())) {
-        indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
-        indent(out)
-            << "  throw new TProtocolException(TProtocolException.UNKNOWN, \"Required field '"
-            << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl;
-        indent(out) << "}" << endl;
-      } else {
-        indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
-                    << "' because it's a primitive." << endl;
-      }
-    }
-  }
-
-  // check that fields of type enum have valid values
-  out << indent() << "// check that fields of type enum have valid values" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = (*f_iter);
-    t_type* type = field->get_type();
-    // if field is an enum, check that its value is valid
-    if (type->is_enum()) {
-      indent(out) << "if (" << generate_isset_check(field) << " && !"
-                  << get_cap_name(get_enum_class_name(type)) << ".VALID_VALUES.contains("
-                  << field->get_name() << ")){" << endl;
-      indent_up();
-      indent(out) << "throw new TProtocolException(TProtocolException.UNKNOWN, \"The field '"
-                  << field->get_name() << "' has been assigned the invalid value \" + "
-                  << field->get_name() << ");" << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_haxe_struct_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public function write(oprot:TProtocol) : Void {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl;
-  indent(out) << "oprot.IncrementRecursionDepth();" << endl;
-  indent(out) << "try" << endl;
-  scope_up(out);
-
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
-      indent_up();
-    }
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
-      indent_up();
-    }
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    if (null_allowed) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    if (could_be_unset) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-  
-  indent(out) << "oprot.writeFieldStop();" << endl;
-  indent(out) << "oprot.writeStructEnd();" << endl;
-  
-  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-  indent(out) << "catch(e:Dynamic)" << endl;
-  scope_up(out);
-  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
-  indent(out) << "throw e;" << endl;
-  scope_down(out);
-  
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct,
- * which is a function result. These fields are only written
- * if they are set in the Isset array, and only one of them
- * can be set at a time.
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_haxe_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public function write(oprot:TProtocol) : Void {" << endl;
-  indent_up();
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "oprot.IncrementRecursionDepth();" << endl;
-  indent(out) << "try" << endl;
-  scope_up(out);
-  
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out << endl << indent() << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
-
-    indent_up();
-
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}";
-  }
-  
-  indent(out) << endl;
-  indent(out) << "oprot.writeFieldStop();" << endl;
-  indent(out) << "oprot.writeStructEnd();" << endl;
-  
-  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
-  scope_down(out);
-  indent(out) << "catch(e:Dynamic)" << endl;
-  scope_up(out);
-  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
-  indent(out) << "throw e;" << endl;
-  scope_down(out);
-  
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-void t_haxe_generator::generate_reflection_getters(ostringstream& out,
-                                                   t_type* type,
-                                                   string field_name,
-                                                   string cap_name) {
-  (void)type;
-  (void)cap_name;
-  indent(out) << "case " << upcase_string(field_name) << "_FIELD_ID:" << endl;
-  indent_up();
-  indent(out) << "return this." << field_name << ";" << endl;
-  indent_down();
-}
-
-void t_haxe_generator::generate_reflection_setters(ostringstream& out,
-                                                   t_type* type,
-                                                   string field_name,
-                                                   string cap_name) {
-  (void)type;
-  (void)cap_name;
-  indent(out) << "case " << upcase_string(field_name) << "_FIELD_ID:" << endl;
-  indent_up();
-  indent(out) << "if (value == null) {" << endl;
-  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
-  indent(out) << "} else {" << endl;
-  indent(out) << "  this." << field_name << " = value;" << endl;
-  indent(out) << "}" << endl << endl;
-
-  indent_down();
-}
-
-void t_haxe_generator::generate_generic_field_getters_setters(std::ofstream& out,
-                                                              t_struct* tstruct) {
-
-  std::ostringstream getter_stream;
-  std::ostringstream setter_stream;
-
-  // build up the bodies of both the getter and setter at once
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    indent_up();
-    generate_reflection_setters(setter_stream, type, field_name, cap_name);
-    generate_reflection_getters(getter_stream, type, field_name, cap_name);
-    indent_down();
-  }
-
-  // create the setter
-  indent(out) << "public function setFieldValue(fieldID : Int, value : Dynamic) : Void {" << endl;
-  indent_up();
-
-  if (fields.size() > 0) {
-    indent(out) << "switch (fieldID) {" << endl;
-    out << setter_stream.str();
-    indent(out) << "default:" << endl;
-    indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-    indent(out) << "}" << endl;
-  } else {
-    indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  // create the getter
-  indent(out) << "public function getFieldValue(fieldID : Int) : Dynamic {" << endl;
-  indent_up();
-
-  if (fields.size() > 0) {
-    indent(out) << "switch (fieldID) {" << endl;
-    out << getter_stream.str();
-    indent(out) << "default:" << endl;
-    indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-    indent(out) << "}" << endl;
-  } else {
-    indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-  }
-
-  indent_down();
-
-  indent(out) << "}" << endl << endl;
-}
-
-// Creates a generic isSet method that takes the field number as argument
-void t_haxe_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // create the isSet method
-  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
-                 "value) and false otherwise" << endl;
-  indent(out) << "public function isSet(fieldID : Int) : Bool {" << endl;
-  indent_up();
-  if (fields.size() > 0) {
-    indent(out) << "switch (fieldID) {" << endl;
-
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* field = *f_iter;
-      indent(out) << "case " << upcase_string(field->get_name()) << "_FIELD_ID:" << endl;
-      indent_up();
-      indent(out) << "return " << generate_isset_check(field) << ";" << endl;
-      indent_down();
-    }
-
-    indent(out) << "default:" << endl;
-    indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-    indent(out) << "}" << endl;
-  } else {
-    indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a set of property setters/getters for the given struct.
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_property_getters_setters(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    // Simple getter
-    generate_haxe_doc(out, field);
-    indent(out) << "public function get_" << field_name << "() : " << get_cap_name(type_name(type))
-                << " {" << endl;
-    indent_up();
-    indent(out) << "return this." << field_name << ";" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Simple setter
-    generate_haxe_doc(out, field);
-    indent(out) << "public function set_" << field_name << "(" << field_name << ":"
-                << get_cap_name(type_name(type)) << ") : " << get_cap_name(type_name(type)) << " {"
-                << endl;
-    indent_up();
-    indent(out) << "this." << field_name << " = " << field_name << ";" << endl;
-    generate_isset_set(out, field);
-    indent(out) << "return this." << field_name << ";" << endl;
-
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // Unsetter
-    indent(out) << "public function unset" << cap_name << "() : Void {" << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "this." << field_name << " = null;" << endl;
-    } else {
-      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-
-    // isSet method
-    indent(out) << "// Returns true if field " << field_name
-                << " is set (has been assigned a value) and false otherwise" << endl;
-    indent(out) << "public function is" << get_cap_name("set") << cap_name << "() : Bool {" << endl;
-    indent_up();
-    if (type_can_be_null(type)) {
-      indent(out) << "return this." << field_name << " != null;" << endl;
-    } else {
-      indent(out) << "return this.__isset_" << field_name << ";" << endl;
-    }
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates a toString() method for the given struct
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_haxe_struct_tostring(ofstream& out, t_struct* tstruct) {
-  out << indent() << "public "
-      << "function toString() : String {" << endl;
-  indent_up();
-
-  out << indent() << "var ret : String = \"" << tstruct->get_name() << "(\";" << endl;
-  out << indent() << "var first : Bool = true;" << endl << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
-      indent_up();
-    }
-
-    t_field* field = (*f_iter);
-
-    if (!first) {
-      indent(out) << "if (!first) ret +=  \", \";" << endl;
-    }
-    indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl;
-    bool can_be_null = type_can_be_null(field->get_type());
-    if (can_be_null) {
-      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
-      indent(out) << "  ret += \"null\";" << endl;
-      indent(out) << "} else {" << endl;
-      indent_up();
-    }
-
-    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
-      indent(out) << "  ret += \"BINARY\";" << endl;
-    } else if (field->get_type()->is_enum()) {
-      indent(out) << "var " << field->get_name()
-                  << "_name : String = " << get_cap_name(get_enum_class_name(field->get_type()))
-                  << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl;
-      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
-      indent(out) << "  ret += " << field->get_name() << "_name;" << endl;
-      indent(out) << "  ret += \" (\";" << endl;
-      indent(out) << "}" << endl;
-      indent(out) << "ret += this." << field->get_name() << ";" << endl;
-      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
-      indent(out) << "  ret += \")\";" << endl;
-      indent(out) << "}" << endl;
-    } else {
-      indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl;
-    }
-
-    if (can_be_null) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    indent(out) << "first = false;" << endl;
-
-    if (could_be_unset) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    first = false;
-  }
-  out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a static map with meta data to store information such as fieldID to
- * fieldName mapping
- *
- * @param tstruct The struct definition
- */
-void t_haxe_generator::generate_haxe_meta_data_map(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Static Map with fieldID -> FieldMetaData mappings
-  indent(out) << "inline static var metaDataMap : IntMap = new IntMap();" << endl;
-
-  if (fields.size() > 0) {
-    // Populate map
-    scope_up(out);
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* field = *f_iter;
-      std::string field_name = field->get_name();
-      indent(out) << "metaDataMap[" << upcase_string(field_name)
-                  << "_FIELD_ID] = new FieldMetaData(\"" << field_name << "\", ";
-
-      // Set field requirement type (required, optional, etc.)
-      if (field->get_req() == t_field::T_REQUIRED) {
-        out << "TFieldRequirementType.REQUIRED, ";
-      } else if (field->get_req() == t_field::T_OPTIONAL) {
-        out << "TFieldRequirementType.OPTIONAL, ";
-      } else {
-        out << "TFieldRequirementType.DEFAULT, ";
-      }
-
-      // Create value meta data
-      generate_field_value_meta_data(out, field->get_type());
-      out << ");" << endl;
-    }
-    scope_down(out);
-  }
-}
-
-/**
- * Returns a string with the haxe representation of the given thrift type
- * (e.g. for the type struct it returns "TType.STRUCT")
- */
-std::string t_haxe_generator::get_haxe_type_string(t_type* type) {
-  if (type->is_list()) {
-    return "TType.LIST";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_enum()) {
-    return "TType.I32";
-  } else if (type->is_typedef()) {
-    return get_haxe_type_string(((t_typedef*)type)->get_type());
-  } else if (type->is_base_type()) {
-    switch (((t_base_type*)type)->get_base()) {
-    case t_base_type::TYPE_VOID:
-      return "TType.VOID";
-      break;
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-      break;
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-      break;
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-      break;
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-      break;
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-      break;
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-      break;
-    default:
-      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
-                               + "\" passed to t_haxe_generator::get_haxe_type_string!");
-      break; // This should never happen!
-    }
-  } else {
-    throw std::runtime_error(
-        "Unknown thrift type \"" + type->get_name()
-        + "\" passed to t_haxe_generator::get_haxe_type_string!"); // This should never happen!
-  }
-}
-
-void t_haxe_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
-  out << endl;
-  indent_up();
-  indent_up();
-  if (type->is_struct()) {
-    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type);
-  } else if (type->is_container()) {
-    if (type->is_list()) {
-      indent(out) << "new ListMetaData(TType.LIST, ";
-      t_type* elem_type = ((t_list*)type)->get_elem_type();
-      generate_field_value_meta_data(out, elem_type);
-    } else if (type->is_set()) {
-      indent(out) << "new SetMetaData(TType.SET, ";
-      t_type* elem_type = ((t_list*)type)->get_elem_type();
-      generate_field_value_meta_data(out, elem_type);
-    } else { // map
-      indent(out) << "new MapMetaData(TType.MAP, ";
-      t_type* key_type = ((t_map*)type)->get_key_type();
-      t_type* val_type = ((t_map*)type)->get_val_type();
-      generate_field_value_meta_data(out, key_type);
-      out << ", ";
-      generate_field_value_meta_data(out, val_type);
-    }
-  } else {
-    indent(out) << "new FieldValueMetaData(" << get_haxe_type_string(type);
-  }
-  out << ")";
-  indent_down();
-  indent_down();
-}
-
-/**
- * Generates a thrift service. In C++, this comprises an entirely separate
- * header and source file. The header file defines the methods and includes
- * the data types defined in the main header file, and the implementation
- * file contains implementations of the basic printer and default interfaces.
- *
- * @param tservice The service definition
- */
-void t_haxe_generator::generate_service(t_service* tservice) {
-  // Make interface file
-  string f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + ".hx";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << haxe_package() << ";" << endl;
-
-  f_service_ << endl << haxe_type_imports() << haxe_thrift_imports()
-             << haxe_thrift_gen_imports(tservice);
-
-  if (tservice->get_extends() != NULL) {
-    t_type* parent = tservice->get_extends();
-    string parent_namespace = parent->get_program()->get_namespace("haxe");
-    if (!parent_namespace.empty() && parent_namespace != package_name_) {
-      f_service_ << "import " << type_name(parent) << ";" << endl;
-    }
-  }
-
-  f_service_ << endl;
-
-  generate_service_interface(tservice);
-
-  f_service_.close();
-
-  // Now make the implementation/client file
-  f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "Impl.hx";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << haxe_package() << ";" << endl << endl << haxe_type_imports()
-             << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice) << endl;
-
-  if (tservice->get_extends() != NULL) {
-    t_type* parent = tservice->get_extends();
-    string parent_namespace = parent->get_program()->get_namespace("haxe");
-    if (!parent_namespace.empty() && parent_namespace != package_name_) {
-      f_service_ << "import " << type_name(parent) << "Impl;" << endl;
-    }
-  }
-
-  f_service_ << endl;
-
-  generate_service_client(tservice);
-
-  f_service_.close();
-
-  // Now make the helper class files
-  generate_service_helpers(tservice);
-
-  // Now make the processor/server file
-  f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "Processor.hx";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << haxe_package() << ";" << endl << endl << haxe_type_imports()
-             << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice) << endl;
-
-  if (!package_name_.empty()) {
-    f_service_ << "import " << package_name_ << ".*;" << endl;
-    f_service_ << "import " << package_name_ << "." << get_cap_name(service_name_).c_str()
-               << "Impl;" << endl;
-    f_service_ << endl;
-  }
-
-  generate_service_server(tservice);
-
-  f_service_.close();
-}
-
-/**
- * Generates the code snippet for the onSuccess callbacks
- *
- * @param tfunction The service function to generate code for.
- */
-string t_haxe_generator::generate_service_method_onsuccess(t_function* tfunction,
-                                                           bool as_type,
-                                                           bool omit_name) {
-  if (tfunction->is_oneway()) {
-    return "";
-  }
-
-  string name = "";
-  if (!omit_name) {
-    name = "onSuccess";
-    if (as_type) {
-      name += " : ";
-    }
-  }
-
-  if (tfunction->get_returntype()->is_void()) {
-    if (as_type) {
-      return name + "Void->Void = null";
-    } else {
-      return name + "() : Void";
-    }
-  }
-
-  if (as_type) {
-    return name + type_name(tfunction->get_returntype()) + "->Void = null";
-  } else {
-    return name + "( retval : " + type_name(tfunction->get_returntype()) + ")";
-  }
-}
-
-/**
- * Generates a service method header
- *
- * @param tfunction The service function to generate code for.
- */
-void t_haxe_generator::generate_service_method_signature(t_function* tfunction, bool is_interface) {
-  if (callbacks_) {
-    generate_service_method_signature_callback(tfunction, is_interface);
-  } else {
-    generate_service_method_signature_normal(tfunction, is_interface);
-  }
-}
-
-/**
- * Generates a service method header in "normal" style
- *
- * @param tfunction The service function to generate code for.
- */
-void t_haxe_generator::generate_service_method_signature_normal(t_function* tfunction,
-                                                                bool is_interface) {
-  if (is_interface) {
-    indent(f_service_) << function_signature_normal(tfunction) << ";" << endl << endl;
-  } else {
-    indent(f_service_) << "public " << function_signature_normal(tfunction) << " {" << endl;
-  }
-}
-
-/**
- * Generates a service method header in "callback" style
- *
- * @param tfunction The service function to generate code for.
- */
-void t_haxe_generator::generate_service_method_signature_callback(t_function* tfunction,
-                                                                  bool is_interface) {
-  if (!tfunction->is_oneway()) {
-    std::string on_success_impl = generate_service_method_onsuccess(tfunction, false, false);
-    indent(f_service_) << "// function onError(Dynamic) : Void;" << endl;
-    indent(f_service_) << "// function " << on_success_impl.c_str() << ";" << endl;
-  }
-
-  if (is_interface) {
-    indent(f_service_) << function_signature_callback(tfunction) << ";" << endl << endl;
-  } else {
-    indent(f_service_) << "public " << function_signature_callback(tfunction) << " {" << endl;
-  }
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_haxe_generator::generate_service_interface(t_service* tservice) {
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends_iface = " extends " + tservice->get_extends()->get_name();
-  }
-
-  generate_haxe_doc(f_service_, tservice);
-  // generate_rtti_decoration(f_service_); - not yet, because of
-  // https://github.com/HaxeFoundation/haxe/issues/3626
-  generate_macro_decoration(f_service_);
-  f_service_ << indent() << "interface " << get_cap_name(service_name_) << extends_iface << " {"
-             << endl << endl;
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_haxe_doc(f_service_, *f_iter);
-    generate_service_method_signature(*f_iter, true);
-  }
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates structs for all the service args and return types
- *
- * @param tservice The service
- */
-void t_haxe_generator::generate_service_helpers(t_service* tservice) {
-  f_service_ << endl << endl;
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_haxe_struct(ts, false);
-    generate_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_haxe_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = get_cap_name(tservice->get_extends()->get_name());
-    extends_client = " extends " + extends + "Impl";
-  }
-
-  generate_rtti_decoration(f_service_);
-  // build macro is inherited from interface
-  indent(f_service_) << "class " << get_cap_name(service_name_) << "Impl" << extends_client
-                     << " implements " << get_cap_name(service_name_) << " {" << endl << endl;
-  indent_up();
-
-  indent(f_service_) << "public function new( iprot : TProtocol, oprot : TProtocol = null)" << endl;
-  scope_up(f_service_);
-  if (extends.empty()) {
-    f_service_ << indent() << "iprot_ = iprot;" << endl;
-    f_service_ << indent() << "if (oprot == null) {" << endl;
-    indent_up();
-    f_service_ << indent() << "oprot_ = iprot;" << endl;
-    indent_down();
-    f_service_ << indent() << "} else {" << endl;
-    indent_up();
-    f_service_ << indent() << "oprot_ = oprot;" << endl;
-    indent_down();
-    f_service_ << indent() << "}" << endl;
-  } else {
-    f_service_ << indent() << "super(iprot, oprot);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent() << "private var iprot_ : TProtocol;" << endl << indent()
-               << "private var oprot_ : TProtocol;" << endl << indent()
-               << "private var seqid_ : Int;" << endl << endl;
-
-    indent(f_service_) << "public function getInputProtocol() : TProtocol" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return this.iprot_;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    indent(f_service_) << "public function getOutputProtocol() : TProtocol" << endl;
-    scope_up(f_service_);
-    indent(f_service_) << "return this.oprot_;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    generate_service_method_signature(*f_iter, false);
-
-    indent_up();
-
-    // Get the struct of function call params
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    string argsname = get_cap_name((*f_iter)->get_name() + "_args");
-    vector<t_field*>::const_iterator fld_iter;
-    const vector<t_field*>& fields = arg_struct->get_members();
-
-    // Serialize the request
-    string calltype = (*f_iter)->is_oneway() ? "ONEWAY" : "CALL";
-    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname
-               << "\", TMessageType." << calltype << ", seqid_));" << endl << indent()
-               << "var args : " << argsname << " = new " << argsname << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
-                 << (*fld_iter)->get_name() << ";" << endl;
-    }
-
-    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
-               << "oprot_.writeMessageEnd();" << endl;
-
-    if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
-      f_service_ << indent() << "var retval : " << type_name((*f_iter)->get_returntype()) << ";"
-                 << endl;
-    }
-
-    if ((*f_iter)->is_oneway()) {
-      f_service_ << indent() << "oprot_.getTransport().flush();" << endl;
-    } else {
-      indent(f_service_) << "oprot_.getTransport().flush(function(error:Dynamic) : Void {" << endl;
-      indent_up();
-      if (callbacks_) {
-        indent(f_service_) << "try {" << endl;
-        indent_up();
-      }
-      string resultname = get_cap_name((*f_iter)->get_name() + "_result");
-      indent(f_service_) << "if (error != null) {" << endl;
-      indent_up();
-      if (callbacks_) {
-        indent(f_service_) << "if (onError != null) onError(error);" << endl;
-        indent(f_service_) << "return;" << endl;
-      } else {
-        indent(f_service_) << "throw error;" << endl;
-      }
-      indent_down();
-      indent(f_service_) << "}" << endl;
-      indent(f_service_) << "var msg : TMessage = iprot_.readMessageBegin();" << endl;
-      indent(f_service_) << "if (msg.type == TMessageType.EXCEPTION) {" << endl;
-      indent_up();
-      indent(f_service_) << "var x = TApplicationException.read(iprot_);" << endl;
-      indent(f_service_) << "iprot_.readMessageEnd();" << endl;
-      if (callbacks_) {
-        indent(f_service_) << "if (onError != null) onError(x);" << endl;
-        indent(f_service_) << "return;" << endl;
-      } else {
-        indent(f_service_) << "throw x;" << endl;
-      }
-      indent_down();
-      indent(f_service_) << "}" << endl;
-      indent(f_service_) << "var result : " << resultname << " = new " << resultname << "();"
-                         << endl;
-      indent(f_service_) << "result.read(iprot_);" << endl;
-      indent(f_service_) << "iprot_.readMessageEnd();" << endl;
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "if (result." << generate_isset_check("success") << ") {" << endl;
-        indent_up();
-        if (callbacks_) {
-          indent(f_service_) << "if (onSuccess != null) onSuccess(result.success);" << endl;
-          indent(f_service_) << "return;" << endl;
-        } else {
-          indent(f_service_) << "retval = result.success;" << endl;
-          indent(f_service_) << "return;" << endl;
-        }
-        indent_down();
-        indent(f_service_) << "}" << endl;
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        indent(f_service_) << "if (result." << (*x_iter)->get_name() << " != null) {" << endl;
-        indent_up();
-        if (callbacks_) {
-          indent(f_service_) << "if (onError != null) onError(result." << (*x_iter)->get_name()
-                             << ");" << endl;
-          indent(f_service_) << "return;" << endl;
-        } else {
-          indent(f_service_) << "throw result." << (*x_iter)->get_name() << ";" << endl;
-        }
-        indent_down();
-        indent(f_service_) << "}" << endl;
-      }
-
-      // If you get here it's an exception, unless a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        if (callbacks_) {
-          indent(f_service_) << "if (onSuccess != null) onSuccess();" << endl;
-        }
-        indent(f_service_) << "return;" << endl;
-      } else {
-        if (callbacks_) {
-          indent(f_service_) << "if (onError != null)" << endl;
-          indent_up();
-          indent(f_service_)
-              << "onError( new TApplicationException(TApplicationException.MISSING_RESULT," << endl;
-          indent(f_service_) << "                               \"" << (*f_iter)->get_name()
-                             << " failed: unknown result\"));" << endl;
-          indent_down();
-        } else {
-          indent(f_service_)
-              << "throw new TApplicationException(TApplicationException.MISSING_RESULT," << endl;
-          indent(f_service_) << "                            \"" << (*f_iter)->get_name()
-                             << " failed: unknown result\");" << endl;
-        }
-      }
-
-      if (callbacks_) {
-        indent_down();
-        indent(f_service_) << "} catch( e : TException) {" << endl;
-        indent_up();
-        indent(f_service_) << "if (onError != null) onError(e);" << endl;
-        indent_down();
-        indent(f_service_) << "}" << endl;
-      }
-
-      indent_down();
-      indent(f_service_) << "});" << endl;
-    }
-
-    if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
-      f_service_ << indent() << "return retval;" << endl;
-    }
-
-    // Close function
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl;
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_haxe_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  // Extends stuff
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = get_cap_name(type_name(tservice->get_extends()));
-    extends_processor = " extends " + extends + "Processor";
-  }
-
-  // Generate the header portion
-  generate_rtti_decoration(f_service_);
-  generate_macro_decoration(f_service_);
-  indent(f_service_) << "class " << get_cap_name(service_name_) << "Processor" << extends_processor
-                     << " implements TProcessor {" << endl << endl;
-  indent_up();
-
-  f_service_ << indent() << "private var " << get_cap_name(service_name_)
-             << "_iface_ : " << get_cap_name(service_name_) << ";" << endl;
-
-  if (extends.empty()) {
-    f_service_ << indent()
-               << "private var PROCESS_MAP = new StringMap< Int->TProtocol->TProtocol->Void >();"
-               << endl;
-  }
-
-  f_service_ << endl;
-
-  indent(f_service_) << "public function new( iface : " << get_cap_name(service_name_) << ")"
-                     << endl;
-  scope_up(f_service_);
-  if (!extends.empty()) {
-    f_service_ << indent() << "super(iface);" << endl;
-  }
-  f_service_ << indent() << get_cap_name(service_name_) << "_iface_ = iface;" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "PROCESS_MAP.set(\"" << (*f_iter)->get_name() << "\", "
-               << (*f_iter)->get_name() << "());" << endl;
-  }
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the server implementation
-  string override = "";
-  if (tservice->get_extends() != NULL) {
-    override = "override ";
-  }
-  indent(f_service_) << override
-                     << "public function process( iprot : TProtocol, oprot : TProtocol) : Bool"
-                     << endl;
-  scope_up(f_service_);
-
-  f_service_ << indent() << "var msg : TMessage = iprot.readMessageBegin();" << endl;
-
-  // TODO(mcslee): validate message, was the seqid etc. legit?
-  // AS- If all method is oneway:
-  // do you have an oprot?
-  // do you you need nullcheck?
-  f_service_
-      << indent() << "var fn  = PROCESS_MAP.get(msg.name);" << endl << indent()
-      << "if (fn == null) {" << endl << indent() << "  TProtocolUtil.skip(iprot, TType.STRUCT);"
-      << endl << indent() << "  iprot.readMessageEnd();" << endl << indent()
-      << "  var x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid "
-         "method name: '\"+msg.name+\"'\");" << endl << indent()
-      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
-      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
-      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
-      << "  return true;" << endl << indent() << "}" << endl << indent()
-      << "fn( msg.seqid, iprot, oprot);" << endl;
-
-  f_service_ << indent() << "return true;" << endl;
-
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  indent_down();
-  indent(f_service_) << "}" << endl << endl;
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_haxe_generator::generate_function_helpers(t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  string resultname = get_cap_name(tfunction->get_name() + "_result");
-  t_struct result(program_, resultname);
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_haxe_struct(&result, false, true);
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_haxe_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open class
-  indent(f_service_) << "private function " << tfunction->get_name()
-                     << "() : Int->TProtocol->TProtocol->Void {" << endl;
-  indent_up();
-
-  // Open function
-  indent(f_service_) << "return function( seqid : Int, iprot : TProtocol, oprot : TProtocol) : Void"
-                     << endl;
-  scope_up(f_service_);
-
-  string argsname = get_cap_name(tfunction->get_name() + "_args");
-  string resultname = get_cap_name(tfunction->get_name() + "_result");
-
-  f_service_ << indent() << "var args : " << argsname << " = new " << argsname << "();" << endl
-             << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();"
-             << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "var result : " << resultname << " = new " << resultname << "();"
-               << endl;
-  }
-
-  // Try block for any  function to catch (defined or undefined) exceptions
-  f_service_ << indent() << "try {" << endl;
-  indent_up();
-
-  if (callbacks_) {
-    // callback function style onError/onSuccess
-
-    // Generate the function call
-    t_struct* arg_struct = tfunction->get_arglist();
-    const std::vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    f_service_ << indent();
-    f_service_ << get_cap_name(service_name_) << "_iface_." << tfunction->get_name() << "(";
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-
-    if (tfunction->is_oneway()) {
-      f_service_ << ");" << endl;
-    } else {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      string on_success = generate_service_method_onsuccess(tfunction, false, true);
-      indent_up();
-      f_service_ << endl;
-      indent(f_service_) << "null,  // errors are thrown by the handler" << endl;
-      if (tfunction->get_returntype()->is_void()) {
-        indent(f_service_) << "null); // no retval" << endl;
-      } else {
-        indent(f_service_) << "function" << on_success.c_str() << " {" << endl;
-        if (!tfunction->get_returntype()->is_void()) {
-          indent_up();
-          indent(f_service_) << "result.success = retval;" << endl;
-          indent_down();
-        }
-        indent(f_service_) << "});" << endl;
-      }
-      indent_down();
-    }
-
-  } else {
-    // normal function():result style
-
-    // Generate the function call
-    t_struct* arg_struct = tfunction->get_arglist();
-    const std::vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    f_service_ << indent();
-    if (!(tfunction->is_oneway() || tfunction->get_returntype()->is_void())) {
-      f_service_ << "result.success = ";
-    }
-    f_service_ << get_cap_name(service_name_) << "_iface_." << tfunction->get_name() << "(";
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-    f_service_ << ");" << endl;
-  }
-
-  indent_down();
-  f_service_ << indent() << "}";
-  if (!tfunction->is_oneway()) {
-    // catch exceptions defined in the IDL
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << " catch (" << (*x_iter)->get_name() << ":"
-                 << get_cap_name(type_name((*x_iter)->get_type(), false, false)) << ") {" << endl;
-      if (!tfunction->is_oneway()) {
-        indent_up();
-        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
-                   << (*x_iter)->get_name() << ";" << endl;
-        indent_down();
-        f_service_ << indent() << "}";
-      } else {
-        f_service_ << "}";
-      }
-    }
-  }
-
-  // always catch all exceptions to prevent from service denial
-  f_service_ << " catch (th : Dynamic) {" << endl;
-  indent_up();
-  indent(f_service_) << "trace(\"Internal error processing " << tfunction->get_name() << "\", th);"
-                     << endl;
-  if (!tfunction->is_oneway()) {
-    indent(f_service_) << "var x = new TApplicationException(TApplicationException.INTERNAL_ERROR, "
-                          "\"Internal error processing " << tfunction->get_name() << "\");" << endl;
-    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-                       << "\", TMessageType.EXCEPTION, seqid));" << endl;
-    indent(f_service_) << "x.write(oprot);" << endl;
-    indent(f_service_) << "oprot.writeMessageEnd();" << endl;
-    indent(f_service_) << "oprot.getTransport().flush();" << endl;
-  }
-  indent(f_service_) << "return;" << endl;
-  indent_down();
-  f_service_ << indent() << "}" << endl;
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "return;" << endl;
-    scope_down(f_service_);
-
-    // Close class
-    indent_down();
-    f_service_ << indent() << "}" << endl << endl;
-    return;
-  }
-
-  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
-             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
-             << "oprot.getTransport().flush();" << endl;
-
-  // Close function
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Close class
-  indent_down();
-  f_service_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Deserializes a field of any type.
- *
- * @param tfield The field
- * @param prefix The variable name or container for this field
- */
-void t_haxe_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    indent(out) << name << " = iprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "readBinary();";
-        } else {
-          out << "readString();";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool();";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte();";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16();";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32();";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64();";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble();";
-        break;
-      default:
-        throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32();";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a struct, invokes read()
- */
-void t_haxe_generator::generate_deserialize_struct(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   string prefix) {
-  out << indent() << prefix << " = new " << get_cap_name(type_name(tstruct)) << "();" << endl
-      << indent() << prefix << ".read(iprot);" << endl;
-}
-
-/**
- * Deserializes a container by reading its size and then iterating
- */
-void t_haxe_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  string obj;
-
-  if (ttype->is_map()) {
-    obj = tmp("_map");
-  } else if (ttype->is_set()) {
-    obj = tmp("_set");
-  } else if (ttype->is_list()) {
-    obj = tmp("_list");
-  }
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    indent(out) << "var " << obj << " = iprot.readMapBegin();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "var " << obj << " = iprot.readSetBegin();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "var " << obj << " = iprot.readListBegin();" << endl;
-  }
-
-  indent(out) << prefix << " = new " << type_name(ttype, false, true)
-              // size the collection correctly
-              << "("
-              << ");" << endl;
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) << "for( " << i << " in 0 ... " << obj << ".size)" << endl;
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  scope_down(out);
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "iprot.readMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "iprot.readSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "iprot.readListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_haxe_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("_key");
-  string val = tmp("_val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  indent(out) << declare_field(&fkey) << endl;
-  indent(out) << declare_field(&fval) << endl;
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << prefix << ".set( " << key << ", " << val << ");" << endl;
-}
-
-/**
- * Deserializes a set element
- */
-void t_haxe_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  indent(out) << declare_field(&felem) << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".add(" << elem << ");" << endl;
-}
-
-/**
- * Deserializes a list element
- */
-void t_haxe_generator::generate_deserialize_list_element(ofstream& out,
-                                                         t_list* tlist,
-                                                         string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  indent(out) << declare_field(&felem) << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".add(" << elem << ");" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_haxe_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + tfield->get_name());
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = prefix + tfield->get_name();
-    indent(out) << "oprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "writeBinary(" << name << ");";
-        } else {
-          out << "writeString(" << name << ");";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ");";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ");";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ");";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ");";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ");";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ");";
-        break;
-      default:
-        throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32(" << name << ");";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           tfield->get_name().c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_haxe_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  out << indent() << prefix << ".write(oprot);" << endl;
-}
-
-/**
- * Serializes a container by writing its size then the elements.
- *
- * @param ttype  The type of container
- * @param prefix String prefix for fields
- */
-void t_haxe_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    string iter = tmp("_key");
-    string counter = tmp("_sizeCounter");
-    indent(out) << "var " << counter << " : Int = 0;" << endl;
-    indent(out) << "for( " << iter << " in " << prefix << ") {" << endl;
-    indent(out) << "  " << counter << +"++;" << endl;
-    indent(out) << "}" << endl;
-
-    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
-                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));"
-                << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
-                << ", " << prefix << ".size));" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListBegin(new TList("
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
-                << endl;
-  }
-
-  string iter = tmp("elem");
-  if (ttype->is_map()) {
-    indent(out) << "for( " << iter << " in " << prefix << ".keys())" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "for( " << iter << " in " << prefix << ".toArray())" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "for( " << iter << " in " << prefix << ")" << endl;
-  }
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
-  } else if (ttype->is_set()) {
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-  } else if (ttype->is_list()) {
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-  }
-
-  scope_down(out);
-
-  if (ttype->is_map()) {
-    indent(out) << "oprot.writeMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Serializes the members of a map.
- */
-void t_haxe_generator::generate_serialize_map_element(ofstream& out

<TRUNCATED>

[44/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_dart_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_dart_generator.cc b/compiler/cpp/src/generate/t_dart_generator.cc
deleted file mode 100644
index 7a744cf..0000000
--- a/compiler/cpp/src/generate/t_dart_generator.cc
+++ /dev/null
@@ -1,2516 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <sstream>
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <cctype>
-
-#include <sys/stat.h>
-#include <stdexcept>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-static const string endl2 = "\n\n";
-
-/**
- * Use the current Thrift version for static libraries.  When releasing, update
- * the version in these files.
- * - lib/dart/pubspec.yaml
- * - test/dart/test_client/pubspec.yaml
- * - tutorial/dart/client/pubspec.yaml
- * - tutorial/dart/console_client/pubspec.yaml
- * - tutorial/dart/server/pubspec.yaml
- * See https://thrift.apache.org/docs/committers/HowToVersion
- */
-static const string dart_thrift_version = THRIFT_VERSION;
-
-/* forward declarations */
-string initial_caps_to_underscores(string name);
-
-/**
- * Dart code generator
- *
- */
-class t_dart_generator : public t_oop_generator {
-public:
-  t_dart_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    library_name_ = "";
-    library_prefix_ = "";
-    package_prefix_ = "";
-    pubspec_lib_ = "";
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("library_name") == 0) {
-        library_name_ = (iter->second);
-      } else if( iter->first.compare("library_prefix") == 0) {
-        library_prefix_ = (iter->second) + ".";
-        package_prefix_ = replace_all(library_prefix_, ".", "/");
-      } else if( iter->first.compare("pubspec_lib") == 0) {
-        pubspec_lib_ = (iter->second);
-      } else {
-        throw "unknown option dart:" + iter->first;
-      }
-    }
-
-    out_dir_base_ = "gen-dart";
-  }
-
-  void scope_up(std::ostream& out, std::string prefix=" ") {
-    out << prefix << "{" << endl;
-    indent_up();
-  }
-
-  void scope_down(std::ostream& out, std::string postfix=endl) {
-    indent_down();
-    indent(out) << "}" << postfix;
-  }
-
-  string replace_all(string contents, string search, string repl) {
-    string str(contents);
-
-    size_t slen = search.length();
-    size_t rlen = repl.length();
-    size_t incr = (rlen > 0) ? rlen : 1;
-
-    if (slen > 0) {
-      size_t found = str.find(search);
-      while ((found != string::npos) && (found < str.length())) {
-        str.replace(found, slen, repl);
-        found = str.find(search, found + incr);
-      }
-    }
-
-    return str;
-  }
-
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void export_class_to_library(string file_name, string class_name);
-
-  void generate_dart_library();
-  void generate_dart_pubspec();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(std::ofstream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool in_static,
-                         bool defval = false);
-  std::string render_const_value(ofstream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_dart_struct(t_struct* tstruct, bool is_exception);
-
-  void generate_dart_struct_definition(std::ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_xception = false,
-                                       bool is_result = false,
-                                       string export_file_name = "");
-  void generate_dart_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  std::string get_dart_type_string(t_type* type);
-  void generate_generic_field_getters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_field_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
-
-  void generate_function_helpers(t_function* tfunction);
-  std::string init_value(t_field* tfield);
-  std::string get_cap_name(std::string name);
-  std::string get_member_name(std::string name);
-  std::string get_args_class_name(std::string name);
-  std::string get_result_class_name(std::string name);
-  std::string get_file_name(std::string name);
-  std::string get_constants_class_name(std::string name);
-  std::string generate_isset_check(t_field* field);
-  std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
-
-  void generate_service_interface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_dart_doc(std::ofstream& out, t_doc* tdoc);
-
-  void generate_dart_doc(std::ofstream& out, t_function* tdoc);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string find_library_name(t_program* program);
-  std::string dart_library(string file_name);
-  std::string service_imports();
-  std::string dart_thrift_imports();
-  std::string type_name(t_type* ttype);
-  std::string base_type_name(t_base_type* tbase);
-  std::string declare_field(t_field* tfield, bool init = false);
-  std::string function_signature(t_function* tfunction);
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string get_ttype_class_name(t_type* ttype);
-
-  bool type_can_be_null(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
-           || ttype->is_string();
-  }
-
-  vector<std::string> split(const string& s, char delim) {
-    vector<std::string> elems;
-    stringstream ss(s);
-    string item;
-    while (getline(ss, item, delim)) {
-      elems.push_back(item);
-    }
-    return elems;
-  }
-
-  std::string constant_name(std::string name);
-
-private:
-  std::ofstream f_service_;
-
-  std::string library_name_;
-  std::string library_prefix_;
-  std::string package_prefix_;
-  std::string pubspec_lib_;
-
-  std::string base_dir_;
-  std::string src_dir_;
-  std::string library_exports_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_dart_generator::init_generator() {
-  MKDIR(get_out_dir().c_str());
-
-  if (library_name_.empty()) {
-    library_name_ = find_library_name(program_);
-  }
-
-  string subdir = get_out_dir() + "/" + library_name_;
-  MKDIR(subdir.c_str());
-  base_dir_ = subdir;
-
-  if (library_prefix_.empty()) {
-    subdir += "/lib";
-    MKDIR(subdir.c_str());
-    subdir += "/src";
-    MKDIR(subdir.c_str());
-    src_dir_ = subdir;
-  } else {
-    src_dir_ = base_dir_;
-  }
-}
-
-string t_dart_generator::find_library_name(t_program* program) {
-  string name = program->get_namespace("dart");
-  if (name.empty()) {
-    name = program->get_name();
-  }
-  name = replace_all(name, ".", "_");
-  name = replace_all(name, "-", "_");
-  return name;
-}
-
-/**
- * The Dart library
- *
- * @return String of the library, e.g. "library myservice;"
- */
-string t_dart_generator::dart_library(string file_name) {
-  string out = "library " + library_prefix_ + library_name_;
-  if (!file_name.empty()) {
-    if (library_prefix_.empty()) {
-      out += ".src." + file_name;
-    } else {
-      out += "." + file_name;
-    }
-  }
-  return out + ";\n";
-}
-
-/**
- * Prints imports for services
- *
- * @return List of imports for services
- */
-string t_dart_generator::service_imports() {
-  return "import 'dart:async';" + endl;
-}
-
-/**
- * Prints standard dart imports
- *
- * @return List of imports necessary for thrift
- */
-string t_dart_generator::dart_thrift_imports() {
-  string imports = "import 'dart:typed_data' show Uint8List;" + endl +
-                   "import 'package:thrift/thrift.dart';" + endl;
-
-  // add import for this library
-  if (package_prefix_.empty()) {
-    imports += "import 'package:" + library_name_ + "/" + library_name_ + ".dart';" + endl;
-  } else {
-    imports += "import 'package:" + package_prefix_ + library_name_ + ".dart';" + endl;
-  }
-
-  // add imports for included thrift files
-  const vector<t_program*>& includes = program_->get_includes();
-  for (size_t i = 0; i < includes.size(); ++i) {
-    string include_name = find_library_name(includes[i]);
-    string named_import = "t_" + include_name;
-    if (package_prefix_.empty()) {
-      imports += "import 'package:" + include_name + "/" + include_name + ".dart' as " + named_import + ";" + endl;
-    } else {
-      imports += "import 'package:" + package_prefix_ + include_name + ".dart' as " + named_import + ";" + endl;
-    }
-  }
-
-  return imports;
-}
-
-/**
- * Not used
- */
-void t_dart_generator::close_generator() {
-  generate_dart_library();
-
-  if (library_prefix_.empty()) {
-    generate_dart_pubspec();
-  }
-}
-
-void t_dart_generator::generate_dart_library() {
-  string f_library_name;
-  if (library_prefix_.empty()) {
-    f_library_name = base_dir_ + "/lib/" + library_name_ + ".dart";
-  } else {
-    f_library_name = get_out_dir() + "/" + library_name_ + ".dart";
-  }
-
-  ofstream f_library;
-  f_library.open(f_library_name.c_str());
-
-  f_library << autogen_comment() << endl;
-  f_library << "library " << library_prefix_ << library_name_ << ";" << endl2;
-  f_library << library_exports_;
-
-  f_library.close();
-}
-
-void t_dart_generator::export_class_to_library(string file_name, string class_name) {
-  string subdir;
-  if (library_prefix_.empty()) {
-    subdir = "src";
-  } else {
-    subdir = library_name_;
-  }
-  library_exports_ += "export '" + subdir + "/" + file_name + ".dart' show " + class_name + ";" + endl;
-}
-
-void t_dart_generator::generate_dart_pubspec() {
-  string f_pubspec_name = base_dir_ + "/pubspec.yaml";
-  ofstream f_pubspec;
-  f_pubspec.open(f_pubspec_name.c_str());
-
-  indent(f_pubspec) << "name: " << library_name_ << endl;
-  indent(f_pubspec) << "version: 0.0.1" << endl;
-  indent(f_pubspec) << "description: Autogenerated by Thrift Compiler" << endl;
-  f_pubspec << endl;
-
-  indent(f_pubspec) << "environment:" << endl;
-  indent_up();
-  indent(f_pubspec) << "sdk: ^1.12.0" << endl;
-  indent_down();
-  f_pubspec << endl;
-
-  indent(f_pubspec) << "dependencies:" << endl;
-  indent_up();
-
-  if (pubspec_lib_.empty()) {
-    // default to relative path within working directory, which works for tests
-    indent(f_pubspec) << "thrift:  # ^" << dart_thrift_version << endl;
-    indent_up();
-    indent(f_pubspec) << "path: ../../../../lib/dart" << endl;
-    indent_down();
-  } else {
-    const vector<std::string> lines = split(pubspec_lib_, '|');
-    for (size_t line_index = 0; line_index < lines.size(); line_index++) {
-      indent(f_pubspec) << lines[line_index] << endl;
-    }
-  }
-
-  // add included thrift files as dependencies
-  const vector<t_program*>& includes = program_->get_includes();
-  for (size_t i = 0; i < includes.size(); ++i) {
-    string include_name = find_library_name(includes[i]);
-    indent(f_pubspec) << include_name << ":" << endl;
-    indent_up();
-    indent(f_pubspec) << "path: ../" << include_name << endl;
-    indent_down();
-  }
-
-  indent_down();
-  f_pubspec << endl;
-
-  f_pubspec.close();
-}
-
-/**
- * Not used
- *
- * @param ttypedef The type definition
- */
-void t_dart_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Enums are a class with a set of static constants.
- *
- * @param tenum The enumeration
- */
-void t_dart_generator::generate_enum(t_enum* tenum) {
-  // Make output file
-  string file_name = get_file_name(tenum->get_name());
-
-  string f_enum_name = src_dir_ + "/" + file_name + ".dart";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
-
-  // Comment and add library
-  f_enum << autogen_comment() << dart_library(file_name) << endl;
-
-  string class_name = tenum->get_name();
-  export_class_to_library(file_name, class_name);
-  f_enum << "class " << class_name;
-  scope_up(f_enum);
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << "static const int " << (*c_iter)->get_name() << " = " << value << ";"
-                   << endl;
-  }
-
-  // Create a static Set with all valid values for this enum
-  f_enum << endl;
-
-  indent(f_enum) << "static final Set<int> VALID_VALUES = new Set.from([" << endl;
-  indent_up();
-  bool firstValue = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    // populate set
-    indent(f_enum) << (firstValue ? "" : ", ");
-    f_enum << (*c_iter)->get_name() << endl;
-    firstValue = false;
-  }
-  indent_down();
-  indent(f_enum) << "]);" << endl;
-
-  indent(f_enum) << "static final Map<int, String> VALUES_TO_NAMES = {" << endl;
-  indent_up();
-  firstValue = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    indent(f_enum) << (firstValue ? "" : ", ");
-    f_enum  << (*c_iter)->get_name() << ": '" << (*c_iter)->get_name() << "'" << endl;
-    firstValue = false;
-  }
-  indent_down();
-  indent(f_enum) << "};" << endl;
-
-  scope_down(f_enum); // end class
-
-  f_enum.close();
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_dart_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-
-  string class_name = get_constants_class_name(program_name_);
-  string file_name = get_file_name(class_name);
-
-  string f_consts_name = src_dir_ + "/" + file_name + ".dart";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  // Print header
-  f_consts << autogen_comment() << dart_library(file_name) << endl;
-  f_consts << dart_thrift_imports() << endl;
-
-  export_class_to_library(file_name, class_name);
-  indent(f_consts) << "class " << class_name;
-  scope_up(f_consts);
-
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    print_const_value(f_consts,
-                      (*c_iter)->get_name(),
-                      (*c_iter)->get_type(),
-                      (*c_iter)->get_value(),
-                      false);
-    f_consts << endl;
-  }
-
-  scope_down(f_consts);
-
-  f_consts.close();
-}
-
-void t_dart_generator::print_const_value(std::ofstream& out,
-                                        string name,
-                                        t_type* type,
-                                        t_const_value* value,
-                                        bool in_static,
-                                        bool defval) {
-  type = get_true_type(type);
-
-  indent(out);
-  if (!defval) {
-    out << (in_static ? "var " : "static final ");
-  }
-  if (type->is_base_type()) {
-    if (!defval) {
-      out << type_name(type) << " ";
-    }
-    string v2 = render_const_value(out, name, type, value);
-    out << name;
-    out << " = " << v2 << ";" << endl << endl;
-  } else if (type->is_enum()) {
-    if (!defval) {
-      out << type_name(type) << " ";
-    }
-    out << name;
-    out << " = " << value->get_integer() << ";" << endl << endl;
-  } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    out << type_name(type) << " " << name << " = new " << type_name(type) << "()";
-    indent_up();
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(out, name, field_type, v_iter->second);
-      out << endl;
-      indent(out) << ".." << v_iter->first->get_string() << " = " << val;
-    }
-    indent_down();
-    out << ";" << endl;
-  } else if (type->is_map()) {
-    if (!defval) {
-      out << type_name(type) << " ";
-    }
-    out << name << " =";
-    scope_up(out);
-
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, name, ktype, v_iter->first);
-      string val = render_const_value(out, name, vtype, v_iter->second);
-      indent(out) << key << ": " << val << "," << endl;
-    }
-    scope_down(out, ";" + endl);
-
-    out << endl;
-  } else if (type->is_list() || type->is_set()) {
-    if (!defval) {
-      out << type_name(type) << " ";
-    }
-    out << name << " = ";
-    t_type* etype;
-    if (type->is_list()) {
-      out << "[" << endl;
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      out << "new " << type_name(type) << ".from([" << endl;
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-
-    indent_up();
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      indent(out) << val << "," << endl;
-    }
-    indent_down();
-
-    if (type->is_list()) {
-      indent(out) << "];" << endl;
-    } else {
-      indent(out) << "]);" << endl;
-    }
-
-  } else {
-    throw "compiler error: no const of type " + type->get_name();
-  }
-}
-
-string t_dart_generator::render_const_value(ofstream& out,
-                                           string name,
-                                           t_type* type,
-                                           t_const_value* value) {
-  (void)name;
-  type = get_true_type(type);
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << "'" << get_escaped_string(value) << "'";
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << value->get_integer();
-  } else {
-    string t = tmp("tmp");
-    print_const_value(out, t, type, value, true);
-    out << endl;
-    render << t;
-  }
-
-  return render.str();
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is a class
- * with data members, read(), write(), and an inner Isset class.
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_struct(t_struct* tstruct) {
-  generate_dart_struct(tstruct, false);
-}
-
-/**
- * Exceptions are structs, but they inherit from Exception
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_xception(t_struct* txception) {
-  generate_dart_struct(txception, true);
-}
-
-/**
- * Dart struct definition.
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_dart_struct(t_struct* tstruct, bool is_exception) {
-  string file_name = get_file_name(tstruct->get_name());
-  string f_struct_name = src_dir_ + "/" + file_name + ".dart";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << dart_library(file_name) << endl;
-
-  string imports;
-
-  f_struct << dart_thrift_imports() << endl;
-
-  generate_dart_struct_definition(f_struct, tstruct, is_exception, false, file_name);
-
-  f_struct.close();
-}
-
-/**
- * Dart struct definition. This has various parameters, as it could be
- * generated standalone or inside another class as a helper. If it
- * is a helper than it is a static class.
- *
- * @param tstruct      The struct definition
- * @param is_exception Is this an exception?
- * @param in_class     If inside a class, needs to be static class
- * @param is_result    If this is a result it needs a different writer
- */
-void t_dart_generator::generate_dart_struct_definition(ofstream& out,
-                                                       t_struct* tstruct,
-                                                       bool is_exception,
-                                                       bool is_result,
-                                                       string export_file_name) {
-  generate_dart_doc(out, tstruct);
-
-  string class_name = tstruct->get_name();
-  if (!export_file_name.empty()) {
-    export_class_to_library(export_file_name, class_name);
-  }
-  indent(out) << "class " << class_name << " ";
-
-  if (is_exception) {
-    out << "extends Error ";
-  }
-  out << "implements TBase";
-  scope_up(out);
-
-  indent(out) << "static final TStruct _STRUCT_DESC = new TStruct(\"" << class_name
-              << "\");" << endl;
-
-  // Members are public for -dart, private for -dartbean
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "static final TField _" << constant_name((*m_iter)->get_name())
-                << "_FIELD_DESC = new TField(\"" << (*m_iter)->get_name() << "\", "
-                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");"
-                << endl;
-  }
-
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_dart_doc(out, *m_iter);
-    indent(out) << type_name((*m_iter)->get_type()) + " _"
-                << get_member_name((*m_iter)->get_name()) << init_value(*m_iter) << ";" << endl;
-
-    indent(out) << "static const int " << upcase_string((*m_iter)->get_name())
-                << " = " << (*m_iter)->get_key() << ";" << endl;
-  }
-
-  out << endl;
-
-  // Inner Isset class
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (!type_can_be_null((*m_iter)->get_type())) {
-        string field_name = get_member_name((*m_iter)->get_name());
-        indent(out) << "bool __isset_" << field_name << " = false;" << endl;
-      }
-    }
-  }
-
-  out << endl;
-
-  // Default constructor
-  indent(out) << tstruct->get_name() << "()";
-  scope_up(out);
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL) {
-      print_const_value(out,
-                        "this." + get_member_name((*m_iter)->get_name()),
-                        t,
-                        (*m_iter)->get_value(),
-                        true,
-                        true);
-    }
-  }
-  scope_down(out);
-  out << endl;
-
-  generate_dart_bean_boilerplate(out, tstruct);
-  generate_generic_field_getters(out, tstruct);
-  generate_generic_field_setters(out, tstruct);
-  generate_generic_isset_method(out, tstruct);
-
-  generate_dart_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_dart_struct_result_writer(out, tstruct);
-  } else {
-    generate_dart_struct_writer(out, tstruct);
-  }
-  generate_dart_struct_tostring(out, tstruct);
-  generate_dart_validator(out, tstruct);
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * Generates a function to read all the fields of the struct.
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_dart_struct_reader(ofstream& out, t_struct* tstruct) {
-  indent(out) << "read(TProtocol iprot)";
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Declare stack tmp variables and read struct header
-  indent(out) << "TField field;" << endl;
-  indent(out) << "iprot.readStructBegin();" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)";
-  scope_up(out);
-
-  // Read beginning field marker
-  indent(out) << "field = iprot.readFieldBegin();" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if (field.type == TType.STOP)";
-  scope_up(out);
-  indent(out) << "break;" << endl;
-  scope_down(out);
-
-  // Switch statement on the field we are reading
-  indent(out) << "switch (field.id)";
-  scope_up(out);
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl;
-    indent_up();
-
-    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ")";
-    scope_up(out);
-
-    generate_deserialize_field(out, *f_iter, "this.");
-    generate_isset_set(out, *f_iter);
-
-    scope_down(out, " else");
-    scope_up(out);
-    indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl;
-    scope_down(out);
-
-    indent(out) << "break;" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  indent(out) << "default:" << endl;
-  indent_up();
-  indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl;
-  indent(out) << "break;" << endl;
-  indent_down();
-
-  scope_down(out);
-
-  // Read field end marker
-  indent(out) << "iprot.readFieldEnd();" << endl;
-
-  scope_down(out);
-
-  indent(out) << "iprot.readStructEnd();" << endl2;
-
-  // in non-beans style, check for required fields of primitive type
-  // (which can be checked here but not in the general validate method)
-  indent(out) << "// check for required fields of primitive type, which can't be "
-                 "checked in the validate method" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
-      string field_name = get_member_name((*f_iter)->get_name());
-      indent(out) << "if (!__isset_" << field_name << ")";
-      scope_up(out);
-      indent(out) << "  throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '"
-          << field_name
-          << "' was not found in serialized data! Struct: \" + toString());" << endl;
-      scope_down(out, endl2);
-    }
-  }
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl;
-
-  scope_down(out, endl2);
-}
-
-// generates dart method to perform various checks
-// (e.g. check that all required fields are set)
-void t_dart_generator::generate_dart_validator(ofstream& out, t_struct* tstruct) {
-  indent(out) << "validate()";
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "// check for required fields" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      string field_name = get_member_name((*f_iter)->get_name());
-      if (type_can_be_null((*f_iter)->get_type())) {
-        indent(out) << "if (" << field_name << " == null)";
-        scope_up(out);
-        indent(out) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '"
-                    << field_name << "' was not present! Struct: \" + toString());"
-                    << endl;
-        scope_down(out);
-      } else {
-        indent(out) << "// alas, we cannot check '" << field_name
-                    << "' because it's a primitive and you chose the non-beans generator." << endl;
-      }
-    }
-  }
-
-  // check that fields of type enum have valid values
-  indent(out) << "// check that fields of type enum have valid values" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = (*f_iter);
-    t_type* type = field->get_type();
-    // if field is an enum, check that its value is valid
-    if (type->is_enum()) {
-      string field_name = get_member_name(field->get_name());
-      indent(out) << "if (" << generate_isset_check(field) << " && !" << get_ttype_class_name(type)
-                  << ".VALID_VALUES.contains(" << field_name << "))";
-      scope_up(out);
-      indent(out) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"The field '"
-                  << field_name << "' has been assigned the invalid value "
-                  << "$" << field_name << "\");" << endl;
-      scope_down(out);
-    }
-  }
-
-  scope_down(out, endl2);
-}
-
-/**
- * Generates a function to write all the fields of the struct
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_dart_struct_writer(ofstream& out, t_struct* tstruct) {
-  out << indent() << "write(TProtocol oprot)";
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // performs various checks (e.g. check that all required fields are set)
-  indent(out) << "validate();" << endl2;
-
-  indent(out) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    string field_name = get_member_name((*f_iter)->get_name());
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ")";
-      scope_up(out);
-    }
-    bool null_allowed = type_can_be_null((*f_iter)->get_type());
-    if (null_allowed) {
-      indent(out) << "if (this." << field_name << " != null)";
-      scope_up(out);
-    }
-
-    indent(out) << "oprot.writeFieldBegin(_" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    if (null_allowed) {
-      scope_down(out);
-    }
-    if (could_be_unset) {
-      scope_down(out);
-    }
-  }
-  // Write the struct map
-  indent(out) << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
-      << endl;
-
-  scope_down(out, endl2);
-}
-
-/**
- * Generates a function to write all the fields of the struct,
- * which is a function result. These fields are only written
- * if they are set in the Isset array, and only one of them
- * can be set at a time.
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_dart_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  indent(out) << "write(TProtocol oprot)";
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl2;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      indent(out) << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(this." << generate_isset_check(*f_iter) << ")";
-    scope_up(out);
-
-    indent(out) << "oprot.writeFieldBegin(_" << constant_name((*f_iter)->get_name())
-                << "_FIELD_DESC);" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "this.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd();" << endl;
-
-    scope_down(out, "");
-  }
-  out << endl;
-
-  // Write the struct map
-  indent(out) << "oprot.writeFieldStop();" << endl << indent()
-      << "oprot.writeStructEnd();" << endl;
-
-  scope_down(out, endl2);
-}
-
-void t_dart_generator::generate_generic_field_getters(std::ofstream& out,
-                                                      t_struct* tstruct) {
-  // create the getter
-  indent(out) << "getFieldValue(int fieldID)";
-  scope_up(out);
-
-  indent(out) << "switch (fieldID)";
-  scope_up(out);
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    std::string field_name = get_member_name(field->get_name());
-
-    indent(out) << "case " << upcase_string(field_name) << ":" << endl;
-    indent_up();
-    indent(out) << "return this." << field_name << ";" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent_up();
-  indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl;
-  indent_down();
-
-  scope_down(out);  // switch
-  scope_down(out, endl2);  // method
-}
-
-void t_dart_generator::generate_generic_field_setters(std::ofstream& out,
-                                                      t_struct* tstruct) {
-
-  // create the setter
-  indent(out) << "setFieldValue(int fieldID, Object value)";
-  scope_up(out);
-
-  indent(out) << "switch (fieldID)";
-  scope_up(out);
-
-  // build up the bodies of both the getter and setter at once
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    std::string field_name = get_member_name(field->get_name());
-
-    indent(out) << "case " << upcase_string(field_name) << ":" << endl;
-    indent_up();
-
-    indent(out) << "if (value == null)";
-    scope_up(out);
-    indent(out) << "unset" << get_cap_name(field_name) << "();" << endl;
-
-    scope_down(out, " else");
-    scope_up(out);
-    indent(out) << "this." << field_name << " = value;" << endl;
-    scope_down(out);
-
-    indent(out) << "break;" << endl;
-
-    indent_down();
-    out << endl;
-  }
-
-  indent(out) << "default:" << endl;
-  indent_up();
-  indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl;
-  indent_down();
-
-  scope_down(out);  // switch
-  scope_down(out, endl2);  // method
-}
-
-// Creates a generic isSet method that takes the field number as argument
-void t_dart_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // create the isSet method
-  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
-                 "value) and false otherwise" << endl;
-  indent(out) << "bool isSet(int fieldID)";
-  scope_up(out);
-
-  indent(out) << "switch (fieldID)";
-  scope_up(out);
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent_up();
-  indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl;
-  indent_down();
-
-  scope_down(out);  // switch
-  scope_down(out, endl2);  // method
-}
-
-/**
- * Generates a set of Dart Bean boilerplate functions (setters, getters, etc.)
- * for the given struct.
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_dart_bean_boilerplate(ofstream& out,
-                                                    t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = get_member_name(field->get_name());
-    std::string cap_name = get_cap_name(field_name);
-
-    indent(out) << "// " << field_name << endl;
-
-    // Simple getter
-    generate_dart_doc(out, field);
-    indent(out) << type_name(type) << " get " << field_name << " => this._" << field_name << ";" << endl2;
-
-    // Simple setter
-    generate_dart_doc(out, field);
-    indent(out) << "set " << field_name << "(" << type_name(type) << " " << field_name << ")";
-    scope_up(out);
-    indent(out) << "this._" << field_name << " = " << field_name << ";" << endl;
-    generate_isset_set(out, field);
-    scope_down(out, endl2);
-
-    // isSet method
-    indent(out) << "bool is" << get_cap_name("set") << cap_name << "()";
-    if (type_can_be_null(type)) {
-      out << " => this." << field_name << " != null;" << endl2;
-    } else {
-      out << " => this.__isset_" << field_name << ";" << endl2;
-    }
-
-    // Unsetter
-    indent(out) << "unset" << cap_name << "()";
-    scope_up(out);
-    if (type_can_be_null(type)) {
-      indent(out) << "this." << field_name << " = null;" << endl;
-    } else {
-      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
-    }
-    scope_down(out, endl2);
-  }
-}
-
-/**
- * Generates a toString() method for the given struct
- *
- * @param tstruct The struct definition
- */
-void t_dart_generator::generate_dart_struct_tostring(ofstream& out,
-                                                   t_struct* tstruct) {
-  indent(out) << "String toString()";
-  scope_up(out);
-
-  indent(out) << "StringBuffer ret = new StringBuffer(\""
-              << tstruct->get_name() << "(\");" << endl2;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
-    if (could_be_unset) {
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ")";
-      scope_up(out);
-    }
-
-    t_field* field = (*f_iter);
-    std::string field_name = get_member_name(field->get_name());
-
-    if (!first) {
-      indent(out) << "ret.write(\", \");" << endl;
-    }
-    indent(out) << "ret.write(\"" << field_name << ":\");" << endl;
-    bool can_be_null = type_can_be_null(field->get_type());
-    if (can_be_null) {
-      indent(out) << "if (this." << field_name << " == null)";
-      scope_up(out);
-      indent(out) << "ret.write(\"null\");" << endl;
-      scope_down(out, " else");
-      scope_up(out);
-    }
-
-    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
-      indent(out) << "ret.write(\"BINARY\");" << endl;
-    } else if (field->get_type()->is_enum()) {
-      indent(out) << "String " << field_name << "_name = "
-                  << get_ttype_class_name(field->get_type())
-                  << ".VALUES_TO_NAMES[this." << field_name << "];" << endl;
-      indent(out) << "if (" << field_name << "_name != null)";
-      scope_up(out);
-      indent(out) << "ret.write(" << field_name << "_name);" << endl;
-      indent(out) << "ret.write(\" (\");" << endl;
-      scope_down(out);
-      indent(out) << "ret.write(this." << field_name << ");" << endl;
-      indent(out) << "if (" << field_name << "_name != null)";
-      scope_up(out);
-      indent(out) << "ret.write(\")\");" << endl;
-      scope_down(out);
-    } else {
-      indent(out) << "ret.write(this." << field_name << ");" << endl;
-    }
-
-    if (can_be_null) {
-      scope_down(out);
-    }
-    if (could_be_unset) {
-      scope_down(out);
-    }
-
-    out << endl;
-    first = false;
-  }
-
-  indent(out) << "ret.write(\")\");" << endl2;
-
-  indent(out) << "return ret.toString();" << endl;
-
-  scope_down(out, endl2);
-}
-
-/**
- * Returns a string with the dart representation of the given thrift type
- * (e.g. for the type struct it returns "TType.STRUCT")
- */
-std::string t_dart_generator::get_dart_type_string(t_type* type) {
-  if (type->is_list()) {
-    return "TType.LIST";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_enum()) {
-    return "TType.I32";
-  } else if (type->is_typedef()) {
-    return get_dart_type_string(((t_typedef*)type)->get_type());
-  } else if (type->is_base_type()) {
-    switch (((t_base_type*)type)->get_base()) {
-    case t_base_type::TYPE_VOID:
-      return "TType.VOID";
-      break;
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-      break;
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-      break;
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-      break;
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-      break;
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-      break;
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-      break;
-    default:
-      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
-                               + "\" passed to t_dart_generator::get_dart_type_string!");
-      break; // This should never happen!
-    }
-  } else {
-    throw std::runtime_error(
-        "Unknown thrift type \"" + type->get_name()
-        + "\" passed to t_dart_generator::get_dart_type_string!"); // This should never happen!
-  }
-}
-
-void t_dart_generator::generate_service(t_service* tservice) {
-  string file_name = get_file_name(service_name_);
-  string f_service_name = src_dir_ + "/" + file_name + ".dart";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << autogen_comment() << dart_library(file_name) << endl;
-  f_service_ << service_imports() << dart_thrift_imports() << endl;
-  f_service_ << endl;
-
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-
-  f_service_.close();
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_dart_generator::generate_service_interface(t_service* tservice) {
-  string extends_iface = "";
-  if (tservice->get_extends() != NULL) {
-    extends_iface = " extends " + get_ttype_class_name(tservice->get_extends());
-  }
-
-  generate_dart_doc(f_service_, tservice);
-
-  string class_name = service_name_;
-  export_class_to_library(get_file_name(service_name_), class_name);
-  indent(f_service_) << "abstract class " << class_name << extends_iface;
-  scope_up(f_service_);
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << endl;
-    generate_dart_doc(f_service_, *f_iter);
-    indent(f_service_) << function_signature(*f_iter) << ";" << endl;
-  }
-
-  scope_down(f_service_, endl2);
-}
-
-/**
- * Generates structs for all the service args and return types
- *
- * @param tservice The service
- */
-void t_dart_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_dart_struct_definition(f_service_, ts, false, false);
-    generate_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_dart_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = get_ttype_class_name(tservice->get_extends());
-    extends_client = " extends " + extends + "Client";
-  }
-
-  string class_name = service_name_ + "Client";
-  export_class_to_library(get_file_name(service_name_), class_name);
-  indent(f_service_) << "class " << class_name << extends_client
-                     << " implements " << service_name_;
-  scope_up(f_service_);
-  f_service_ << endl;
-
-  indent(f_service_) << class_name << "(TProtocol iprot, [TProtocol oprot = null])";
-
-  if (!extends.empty()) {
-    indent_up();
-    f_service_ << endl;
-    indent(f_service_) << ": super(iprot, oprot);" << endl;
-    indent_down();
-  } else {
-    scope_up(f_service_);
-    indent(f_service_) << "_iprot = iprot;" << endl;
-    indent(f_service_) << "_oprot = (oprot == null) ? iprot : oprot;" << endl;
-    scope_down(f_service_);
-  }
-  f_service_ << endl;
-
-  if (extends.empty()) {
-    indent(f_service_) << "TProtocol _iprot;" << endl2;
-    indent(f_service_) << "TProtocol get iprot => _iprot;" << endl2;
-    indent(f_service_) << "TProtocol _oprot;" << endl2;
-    indent(f_service_) << "TProtocol get oprot => _oprot;" << endl2;
-    indent(f_service_) << "int _seqid = 0;" << endl2;
-    indent(f_service_) << "int get seqid => _seqid;" << endl2;
-    indent(f_service_) << "int nextSeqid() => ++_seqid;" << endl2;
-  }
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    // Open function
-    indent(f_service_) << function_signature(*f_iter) << " async";
-    scope_up(f_service_);
-
-    // Get the struct of function call params
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    string argsname = get_args_class_name((*f_iter)->get_name());
-    vector<t_field*>::const_iterator fld_iter;
-    const vector<t_field*>& fields = arg_struct->get_members();
-
-    // Serialize the request
-    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << (*f_iter)->get_name() << "\", "
-               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
-               << ", nextSeqid()));" << endl;
-    indent(f_service_) << argsname << " args = new " << argsname << "();" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      string arg_field_name = get_member_name((*fld_iter)->get_name());
-      indent(f_service_) << "args." << arg_field_name << " = "
-                 << arg_field_name << ";" << endl;
-    }
-
-    indent(f_service_) << "args.write(oprot);" << endl;
-    indent(f_service_) << "oprot.writeMessageEnd();" << endl2;
-
-    indent(f_service_) << "await oprot.transport.flush();" << endl2;
-
-    if (!(*f_iter)->is_oneway()) {
-      indent(f_service_) << "TMessage msg = iprot.readMessageBegin();" << endl;
-      indent(f_service_) << "if (msg.type == TMessageType.EXCEPTION)";
-      scope_up(f_service_);
-      indent(f_service_) << "TApplicationError error = TApplicationError.read(iprot);" << endl;
-      indent(f_service_) << "iprot.readMessageEnd();" << endl;
-      indent(f_service_) << "throw error;" << endl;
-      scope_down(f_service_, endl2);
-
-      string result_class = get_result_class_name((*f_iter)->get_name());
-      indent(f_service_) << result_class << " result = new " << result_class << "();" << endl;
-      indent(f_service_) << "result.read(iprot);" << endl;
-      indent(f_service_) << "iprot.readMessageEnd();" << endl;
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "if (result." << generate_isset_check("success") << ")";
-        scope_up(f_service_);
-        indent(f_service_) << "return result.success;" << endl;
-        scope_down(f_service_, endl2);
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        string result_field_name = get_member_name((*x_iter)->get_name());
-        indent(f_service_) << "if (result." << result_field_name << " != null)";
-        scope_up(f_service_);
-        indent(f_service_) << "throw result." << result_field_name << ";" << endl;
-        scope_down(f_service_);
-      }
-
-      // If you get here it's an exception, unless a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "return;" << endl;
-      } else {
-        indent(f_service_) << "throw new TApplicationError(TApplicationErrorType.MISSING_RESULT, \""
-                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
-      }
-    }
-
-    scope_down(f_service_, endl2);
-  }
-
-  scope_down(f_service_, endl2);
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_dart_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  // typedef
-  indent(f_service_) << "typedef void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" << endl2;
-
-  // Extends stuff
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = get_ttype_class_name(tservice->get_extends());
-    extends_processor = " extends " + extends + "Processor";
-  }
-
-  // Generate the header portion
-  string class_name =  service_name_ + "Processor";
-  export_class_to_library(get_file_name(service_name_), class_name);
-  indent(f_service_) << "class " << class_name << extends_processor << " implements TProcessor";
-  scope_up(f_service_);
-
-  indent(f_service_) << class_name << "(" << service_name_ << " iface)";
-  if (!extends.empty()) {
-    indent_up();
-    f_service_ << endl;
-    indent(f_service_) << ": super(iface)";
-    indent_down();
-  }
-  scope_up(f_service_);
-
-  if (extends.empty()) {
-    indent(f_service_) << "iface_ = iface;" << endl;
-  }
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    indent(f_service_) << "PROCESS_MAP[\"" << (*f_iter)->get_name()
-               << "\"] = " << get_member_name((*f_iter)->get_name()) << ";" << endl;
-  }
-  scope_down(f_service_, endl2);
-
-  indent(f_service_) << service_name_ << " iface_;" << endl;
-
-  if (extends.empty()) {
-    indent(f_service_) << "final Map<String, ProcessFunction> PROCESS_MAP = {};" << endl;
-  }
-
-  f_service_ << endl;
-
-  // Generate the server implementation
-  indent(f_service_) << "bool process(TProtocol iprot, TProtocol oprot)";
-  scope_up(f_service_);
-  indent(f_service_) << "TMessage msg = iprot.readMessageBegin();" << endl;
-  indent(f_service_) << "ProcessFunction fn = PROCESS_MAP[msg.name];" << endl;
-  indent(f_service_) << "if (fn == null)";
-  scope_up(f_service_);
-  indent(f_service_) << "TProtocolUtil.skip(iprot, TType.STRUCT);" << endl;
-  indent(f_service_) << "iprot.readMessageEnd();" << endl;
-  indent(f_service_) << "TApplicationError x = new TApplicationError(TApplicationErrorType.UNKNOWN_METHOD, "
-         "\"Invalid method name: '\"+msg.name+\"'\");" << endl;
-  indent(f_service_) << "oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl;
-  indent(f_service_) << "x.write(oprot);" << endl;
-  indent(f_service_) << "oprot.writeMessageEnd();" << endl;
-  indent(f_service_) << "oprot.transport.flush();" << endl;
-  indent(f_service_) << "return true;" << endl;
-  scope_down(f_service_);
-  indent(f_service_) << "fn(msg.seqid, iprot, oprot);" << endl;
-  indent(f_service_) << "return true;" << endl;
-  scope_down(f_service_, endl2); // process function
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  scope_down(f_service_, endl2); // class
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_dart_generator::generate_function_helpers(t_function* tfunction) {
-  if (tfunction->is_oneway()) {
-    return;
-  }
-
-  t_struct result(program_, get_result_class_name(tfunction->get_name()));
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-
-  generate_dart_struct_definition(f_service_, &result, false, true);
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_dart_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-
-  bool await_result = (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void());
-
-  indent(f_service_) << get_member_name(tfunction->get_name()) << "(int seqid, TProtocol iprot, TProtocol oprot)";
-  if (await_result) {
-    f_service_ << " async";
-  }
-  scope_up(f_service_);
-
-  string argsname = get_args_class_name(tfunction->get_name());
-  string resultname = get_result_class_name(tfunction->get_name());
-
-  indent(f_service_) << argsname << " args = new " << argsname << "();" << endl;
-  indent(f_service_) << "args.read(iprot);" << endl;
-  indent(f_service_) << "iprot.readMessageEnd();" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  if (!tfunction->is_oneway()) {
-    indent(f_service_) << resultname << " result = new " << resultname << "();" << endl;
-  }
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    indent(f_service_) << "try";
-    scope_up(f_service_);
-  }
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  f_service_ << indent();
-  if (await_result) {
-    f_service_ << "result.success = await ";
-  }
-  f_service_ << "iface_." << get_member_name(tfunction->get_name()) << "(";
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_service_ << ", ";
-    }
-    f_service_ << "args." << get_member_name((*f_iter)->get_name());
-  }
-  f_service_ << ");" << endl;
-
-  if (!tfunction->is_oneway() && xceptions.size() > 0) {
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      string result_field_name = get_member_name((*x_iter)->get_name());
-      scope_down(f_service_, "");
-      f_service_ << " on " << type_name((*x_iter)->get_type())
-              << " catch(" << result_field_name << ")";
-      scope_up(f_service_);
-      if (!tfunction->is_oneway()) {
-        indent(f_service_) << "result." << result_field_name << " = "
-                   << result_field_name << ";" << endl;
-      }
-    }
-    scope_down(f_service_, " ");
-    f_service_ << "catch (th)";
-    scope_up(f_service_);
-    indent(f_service_) << "// Internal error" << endl;
-    indent(f_service_) << "TApplicationError x = new "
-               "TApplicationError(TApplicationErrorType.INTERNAL_ERROR, \"Internal error processing "
-               << tfunction->get_name() << "\");" << endl;
-    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-               << "\", TMessageType.EXCEPTION, seqid));" << endl;
-    indent(f_service_) << "x.write(oprot);" << endl;
-    indent(f_service_) << "oprot.writeMessageEnd();" << endl;
-    indent(f_service_) << "oprot.transport.flush();" << endl;
-    indent(f_service_) << "return;" << endl;
-    scope_down(f_service_);
-  }
-
-  if (tfunction->is_oneway()) {
-    indent(f_service_) << "return;" << endl;
-  } else {
-    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
-               << "\", TMessageType.REPLY, seqid));" << endl;
-    indent(f_service_) << "result.write(oprot);" << endl;
-    indent(f_service_) << "oprot.writeMessageEnd();" << endl;
-    indent(f_service_) << "oprot.transport.flush();" << endl;
-  }
-
-  scope_down(f_service_, endl2);
-}
-
-/**
- * Deserializes a field of any type.
- *
- * @param tfield The field
- * @param prefix The variable name or container for this field
- */
-void t_dart_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-  string field_name = get_member_name(tfield->get_name());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + field_name;
-  }
-
-  string name = prefix + field_name;
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    indent(out) << name << " = iprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "readBinary();";
-        } else {
-          out << "readString();";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool();";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte();";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16();";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32();";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64();";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble();";
-        break;
-      default:
-        throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32();";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           field_name.c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a struct, invokes read()
- */
-void t_dart_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  indent(out) << prefix << " = new " << type_name(tstruct) << "();" << endl;
-  indent(out) << prefix << ".read(iprot);" << endl;
-}
-
-/**
- * Deserializes a container by reading its size and then iterating
- */
-void t_dart_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  indent(out);
-  scope_up(out, "");
-
-  string obj;
-
-  if (ttype->is_map()) {
-    obj = tmp("_map");
-  } else if (ttype->is_set()) {
-    obj = tmp("_set");
-  } else if (ttype->is_list()) {
-    obj = tmp("_list");
-  }
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    indent(out) << "TMap " << obj << " = iprot.readMapBegin();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "TSet " << obj << " = iprot.readSetBegin();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "TList " << obj << " = iprot.readListBegin();" << endl;
-  }
-
-  indent(out) << prefix << " = new " << type_name(ttype) << "();" << endl;
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".length"
-              << "; "
-              << "++" << i << ")";
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  scope_down(out);
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "iprot.readMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "iprot.readSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "iprot.readListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_dart_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("_key");
-  string val = tmp("_val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  indent(out) << declare_field(&fkey) << endl;
-  indent(out) << declare_field(&fval) << endl;
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
-}
-
-/**
- * Deserializes a set element
- */
-void t_dart_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  indent(out) << declare_field(&felem) << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".add(" << elem << ");" << endl;
-}
-
-/**
- * Deserializes a list element
- */
-void t_dart_generator::generate_deserialize_list_element(ofstream& out,
-                                                        t_list* tlist,
-                                                        string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  indent(out) << declare_field(&felem) << endl;
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".add(" << elem << ");" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_dart_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-  string field_name = get_member_name(tfield->get_name());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + field_name;
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + field_name);
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + field_name);
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = prefix + field_name;
-    indent(out) << "oprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "writeBinary(" << name << ");";
-        } else {
-          out << "writeString(" << name << ");";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ");";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ");";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ");";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ");";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ");";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ");";
-        break;
-      default:
-        throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32(" << name << ");";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           field_name.c_str(),
-           type_name(type).c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_dart_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << prefix << ".write(oprot);" << endl;
-}
-
-/**
- * Serializes a container by writing its size then the elements.
- *
- * @param ttype  The type of container
- * @param prefix String prefix for fields
- */
-void t_dart_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  indent(out);
-  scope_up(out, "");
-
-  if (ttype->is_map()) {
-    string iter = tmp("_key");
-    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
-                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix << ".length));"
-                << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
-                << ", " << prefix << ".length));" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListBegin(new TList("
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
-                << endl;
-  }
-
-  string iter = tmp("elem");
-  if (ttype->is_map()) {
-    indent(out) << "for (var " << iter << " in " << prefix << ".keys)";
-  } else if (ttype->is_set() || ttype->is_list()) {
-    indent(out) << "for (var " << iter << " in " << prefix << ")";
-  }
-
-  scope_up(out);
-
-  if (ttype->is_map()) {
-    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
-  } else if (ttype->is_set()) {
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-  } else if (ttype->is_list()) {
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-  }
-
-  scope_down(out);
-
-  if (ttype->is_map()) {
-    indent(out) << "oprot.writeMapEnd();" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetEnd();" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListEnd();" << endl;
-  }
-
-  scope_down(out);
-}
-
-/**
- * Serializes the members of a map.
- */
-void t_dart_generator::generate_serialize_map_element(ofstream& out,
-                                                     t_map* tmap,
-                                                     string iter,
-                                                     string map) {
-  t_field kfield(tmap->get_key_type(), iter);
-  generate_serialize_field(out, &kfield, "");
-  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
-  generate_serialize_field(out, &vfield, "");
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_dart_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_dart_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Returns a Dart type name
- *
- * @param ttype The type
- * @return Dart type name, i.e. Map<Key, Value>
- */
-string t_dart_generator::type_name(t_type* ttype) {
-  ttype = get_true_type(ttype);
-
-  if (ttype->is_base_type()) {
-    return base_type_name((t_base_type*)ttype);
-  } else if (ttype->is_enum()) {
-    return "int";
-  } else if (ttype->is_map()) {
-    t_map* tmap = (t_map*)ttype;
-    return "Map<" + type_name(tmap->get_key_type()) + ", "
-                  + type_name(tmap->get_val_type()) + ">";
-  } else if (ttype->is_set()) {
-    t_set* tset = (t_set*)ttype;
-    return "Set<" + type_name(tset->get_elem_type()) + ">";
-  } else if (ttype->is_list()) {
-    t_list* tlist = (t_list*)ttype;
-    return "List<" + type_name(tlist->get_elem_type()) + ">";
-  }
-
-  return get_ttype_class_name(ttype);
-}
-
-/**
- * Returns the Dart type that corresponds to the thrift type.
- *
- * @param tbase The base type
- */
-string t_dart_generator::base_type_name(t_base_type* type) {
-  t_base_type::t_base tbase = type->get_base();
-
-  switch (tbase) {
-  case t_base_type::TYPE_VOID:
-    return "void";
-  case t_base_type::TYPE_STRING:
-    if (type->is_binary()) {
-      return "Uint8List";
-    } else {
-      return "String";
-    }
-  case t_base_type::TYPE_BOOL:
-    return "bool";
-  case t_base_type::TYPE_I8:
-  case t_base_type::TYPE_I16:
-  case t_base_type::TYPE_I32:
-  case t_base_type::TYPE_I64:
-    return "int";
-  case t_base_type::TYPE_DOUBLE:
-    return "double";
-  default:
-    throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase);
-  }
-}
-
-/**
- * Declares a field, which may include initialization as necessary.
- *
- * @param ttype The type
- */
-string t_dart_generator::declare_field(t_field* tfield, bool init) {
-  string field_name = get_member_name(tfield->get_name());
-  string result = type_name(tfield->get_type()) + " " + field_name;
-  if (init) {
-    t_type* ttype = get_true_type(tfield->get_type());
-    if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
-      result += " = " + render_const_value(dummy, field_name, ttype, tfield->get_value());
-    } else if (ttype->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "NO T_VOID CONSTRUCT";
-      case t_base_type::TYPE_STRING:
-        result += " = null";
-        break;
-      case t_base_type::TYPE_BOOL:
-        result += " = false";
-        break;
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        result += " = 0.0";
-        break;
-      }
-
-    } else if (ttype->is_enum()) {
-      result += " = 0";
-    } else if (ttype->is_container()) {
-      result += " = new " + type_name(ttype) + "()";
-    } else {
-      result += " = new " + type_name(ttype) + "()";
-      ;
-    }
-  }
-  return result + ";";
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_dart_generator::function_signature(t_function* tfunction) {
-  std::string arguments = argument_list(tfunction->get_arglist());
-
-  std::string returntype;
-  if (tfunction->get_returntype()->is_void()) {
-    returntype = "Future";
-  } else {
-    returntype = "Future<" + type_name(tfunction->get_returntype()) + ">";
-  }
-
-  std::string result = returntype + " " + get_member_name(tfunction->get_name()) +
-                       "(" + arguments + ")";
-  return result;
-}
-
-/**
- * Renders a comma separated field list, with type names
- */
-string t_dart_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    string field_name = get_member_name((*f_iter)->get_name());
-    result += type_name((*f_iter)->get_type()) + " " + field_name;
-  }
-  return result;
-}
-
-/**
- * Converts the parse type to a C++ enum string for the given type.
- */
-string t_dart_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "TType.STRING";
-    case t_base_type::TYPE_BOOL:
-      return "TType.BOOL";
-    case t_base_type::TYPE_I8:
-      return "TType.BYTE";
-    case t_base_type::TYPE_I16:
-      return "TType.I16";
-    case t_base_type::TYPE_I32:
-      return "TType.I32";
-    case t_base_type::TYPE_I64:
-      return "TType.I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "TType.DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "TType.I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "TType.STRUCT";
-  } else if (type->is_map()) {
-    return "TType.MAP";
-  } else if (type->is_set()) {
-    return "TType.SET";
-  } else if (type->is_list()) {
-    return "TType.LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-std::string t_dart_generator::init_value(t_field* field) {
-  // Do not initialize optional fields
-  if (field->get_req() == t_field::T_OPTIONAL) {
-    return "";
-  }
-
-  t_type* ttype = field->get_type();
-
-  // Get the actual type for a typedef
-  if (ttype->is_typedef()) {
-    ttype = ((t_typedef*)ttype)->get_type();
-  }
-
-  // Only consider base types for default initialization
-  if (!ttype->is_base_type()) {
-    return "";
-  }
-  t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
-
-  // Initialize bools, ints, and doubles with sane defaults
-  string result;
-  switch (tbase) {
-  case t_base_type::TYPE_BOOL:
-    result = " = false";
-    break;
-  case t_base_type::TYPE_I8:
-  case t_base_type::TYPE_I16:
-  case t_base_type::TYPE_I32:
-  case t_base_type::TYPE_I64:
-    result = " = 0";
-    break;
-  case t_base_type::TYPE_DOUBLE:
-    result = " = 0.0";
-    break;
-  case t_base_type::TYPE_VOID:
-  case t_base_type::TYPE_STRING:
-    result = "";
-    break;
-  }
-
-  return result;
-}
-
-std::string t_dart_generator::get_cap_name(std::string name) {
-  name[0] = toupper(name[0]);
-  return name;
-}
-
-std::string t_dart_generator::get_member_name(std::string name) {
-  name[0] = tolower(name[0]);
-  return name;
-}
-
-std::string t_dart_generator::get_args_class_name(std::string name) {
-  return name + "_args";
-}
-
-std::string t_dart_generator::get_result_class_name(std::string name) {
-  return name + "_result";
-}
-
-std::string t_dart_generator::get_file_name(std::string name) {
-  // e.g. change APIForFileIO to api_for_file_io
-
-  string ret;
-  const char* tmp = name.c_str();
-  bool is_prev_lc = true;
-  bool is_current_lc = tmp[0] == tolower(tmp[0]);
-  bool is_next_lc = false;
-
-  for (unsigned int i = 0; i < name.length(); i++) {
-    char lc = tolower(tmp[i]);
-
-    if (i == name.length() - 1) {
-      is_next_lc = false;
-    } else {
-      is_next_lc = (tmp[i+1] == tolower(tmp[i+1]));
-    }
-
-    if (i != 0 && !is_current_lc && (is_prev_lc || is_next_lc)) {
-      ret += "_";
-    }
-    ret += lc;
-
-    is_prev_lc = is_current_lc;
-    is_current_lc = is_next_lc;
-  }
-
-  return ret;
-}
-
-std::string t_dart_generator::get_constants_class_name(std::string name) {
-  // e.g. change my_great_model to MyGreatModelConstants
-  string ret;
-  const char* tmp = name.c_str();
-  bool is_prev_underscore = true;
-
-  for (unsigned int i = 0; i < name.length(); i++) {
-    if (tmp[i] == '_') {
-      is_prev_underscore = true;
-    } else {
-      if (is_prev_underscore) {
-        ret += toupper(tmp[i]);
-      } else {
-        ret += tmp[i];
-      }
-
-      is_prev_underscore = false;
-    }
-  }
-
-  return ret + "Constants";
-}
-
-string t_dart_generator::constant_name(string name) {
-  string constant_name;
-
-  bool is_first = true;
-  bool was_previous_char_upper = false;
-  for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
-    string::value_type character = (*iter);
-
-    bool is_upper = isupper(character);
-
-    if (is_upper && !is_first && !was_previous_char_upper) {
-      constant_name += '_';
-    }
-    constant_name += toupper(character);
-
-    is_first = false;
-    was_previous_char_upper = is_upper;
-  }
-
-  return constant_name;
-}
-
-/**
- * Emits a doc comment if the provided object has a doc in Thrift
- */
-void t_dart_generator::generate_dart_doc(ofstream& out, t_doc* tdoc) {
-  if (tdoc->has_doc()) {
-    generate_docstring_comment(out, "", "/// ", tdoc->get_doc(), "");
-  }
-}
-
-/**
- * Emits a doc comment if the provided function object has a doc in Thrift
- */
-void t_dart_generator::generate_dart_doc(ofstream& out, t_function* tfunction) {
-  if (tfunction->has_doc()) {
-    stringstream ss;
-    ss << tfunction->get_doc();
-    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
-    vector<t_field*>::const_iterator p_iter;
-    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
-      t_field* p = *p_iter;
-      string field_name = get_member_name(p->get_name());
-      ss << "\n@param " << field_name;
-      if (p->has_doc()) {
-        ss << " " << p->get_doc();
-      }
-    }
-    generate_docstring_comment(out, "", "/// ", ss.str(), "");
-  }
-}
-
-std::string t_dart_generator::generate_isset_check(t_field* field) {
-  string field_name = get_member_name(field->get_name());
-  return generate_isset_check(field_name);
-}
-
-std::string t_dart_generator::generate_isset_check(std::string field_name) {
-  return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
-}
-
-void t_dart_generator::generate_isset_set(ofstream& out, t_field* field) {
-  if (!type_can_be_null(field->get_type())) {
-    string field_name = get_member_name(field->get_name());
-    indent(out) << "this.__isset_" << field_name << " = true;" << endl;
-  }
-}
-
-std::string t_dart_generator::get_ttype_class_name(t_type* ttype) {
-  if (program_ == ttype->get_program()) {
-    return ttype->get_name();
-  } else {
-    string named_import = "t_" + find_library_name(ttype->get_program());
-    return named_import + "." + ttype->get_name();
-  }
-}
-
-THRIFT_REGISTER_GENERATOR(
-    dart,
-    "Dart",
-    "    library_name:    Optional override for library name.\n"
-    "    library_prefix:  Generate code that can be used within an existing library.\n"
-    "                     Use a dot-separated string, e.g. \"my_parent_lib.src.gen\"\n"
-    "    pubspec_lib:     Optional override for thrift lib dependency in pubspec.yaml,\n"
-    "                     e.g. \"thrift: 0.x.x\".  Use a pipe delimiter to separate lines,\n"
-    "                     e.g. \"thrift:|  git:|    url: git@foo.com\"\n"
-)


[29/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_py_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc
deleted file mode 100644
index 1ee0fcb..0000000
--- a/compiler/cpp/src/generate/t_py_generator.cc
+++ /dev/null
@@ -1,2625 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-#include <algorithm>
-#include "t_generator.h"
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Python code generator.
- *
- */
-class t_py_generator : public t_generator {
-public:
-  t_py_generator(t_program* program,
-                 const std::map<std::string, std::string>& parsed_options,
-                 const std::string& option_string)
-    : t_generator(program) {
-    std::map<std::string, std::string>::const_iterator iter;
-
-
-    gen_newstyle_ = true;
-    gen_utf8strings_ = true;
-    gen_dynbase_ = false;
-    gen_slots_ = false;
-    gen_tornado_ = false;
-    gen_twisted_ = false;
-    gen_dynamic_ = false;
-    coding_ = "";
-    gen_dynbaseclass_ = "";
-    gen_dynbaseclass_exc_ = "";
-    gen_dynbaseclass_frozen_ = "";
-    import_dynbase_ = "";
-    package_prefix_ = "";
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("new_style") == 0) {
-        pwarning(0, "new_style is enabled by default, so the option will be removed in the near future.\n");
-      } else if( iter->first.compare("old_style") == 0) {
-        gen_newstyle_ = false;
-        pwarning(0, "old_style is deprecated and may be removed in the future.\n");
-      } else if( iter->first.compare("utf8strings") == 0) {
-        pwarning(0, "utf8strings is enabled by default, so the option will be removed in the near future.\n");
-      } else if( iter->first.compare("no_utf8strings") == 0) {
-        gen_utf8strings_ = false;
-      } else if( iter->first.compare("slots") == 0) {
-        gen_slots_ = true;
-      } else if( iter->first.compare("package_prefix") == 0) {
-        package_prefix_ = iter->second;
-      } else if( iter->first.compare("dynamic") == 0) {
-        gen_dynamic_ = true;
-        gen_newstyle_ = false; // dynamic is newstyle
-        if( gen_dynbaseclass_.empty()) {
-          gen_dynbaseclass_ = "TBase";
-        }
-        if( gen_dynbaseclass_frozen_.empty()) {
-          gen_dynbaseclass_frozen_ = "TFrozenBase";
-        }
-        if( gen_dynbaseclass_exc_.empty()) {
-          gen_dynbaseclass_exc_ = "TExceptionBase";
-        }
-        if( import_dynbase_.empty()) {
-          import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TTransport\n";
-        }
-      } else if( iter->first.compare("dynbase") == 0) {
-        gen_dynbase_ = true;
-        gen_dynbaseclass_ = (iter->second);
-      } else if( iter->first.compare("dynfrozen") == 0) {
-        gen_dynbaseclass_frozen_ = (iter->second);
-      } else if( iter->first.compare("dynexc") == 0) {
-        gen_dynbaseclass_exc_ = (iter->second);
-      } else if( iter->first.compare("dynimport") == 0) {
-        gen_dynbase_ = true;
-        import_dynbase_ = (iter->second);
-      } else if( iter->first.compare("twisted") == 0) {
-        gen_twisted_ = true;
-      } else if( iter->first.compare("tornado") == 0) {
-        gen_tornado_ = true;
-      } else if( iter->first.compare("coding") == 0) {
-        coding_ = iter->second;
-      } else {
-        throw "unknown option py:" + iter->first; 
-      }
-    }
-
-    if (gen_twisted_ && gen_tornado_) {
-      throw "at most one of 'twisted' and 'tornado' are allowed";
-    }
-
-    copy_options_ = option_string;
-
-    if (gen_twisted_) {
-      out_dir_base_ = "gen-py.twisted";
-    } else if (gen_tornado_) {
-      out_dir_base_ = "gen-py.tornado";
-    } else {
-      out_dir_base_ = "gen-py";
-    }
-  }
-
-  virtual std::string indent_str() const {
-    return "    ";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_py_struct(t_struct* tstruct, bool is_exception);
-  void generate_py_struct_definition(std::ofstream& out,
-                                     t_struct* tstruct,
-                                     bool is_xception = false);
-  void generate_py_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_py_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_py_struct_required_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_py_function_helpers(t_function* tfunction);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_remote(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "");
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_python_docstring(std::ofstream& out, t_struct* tstruct);
-
-  void generate_python_docstring(std::ofstream& out, t_function* tfunction);
-
-  void generate_python_docstring(std::ofstream& out,
-                                 t_doc* tdoc,
-                                 t_struct* tstruct,
-                                 const char* subheader);
-
-  void generate_python_docstring(std::ofstream& out, t_doc* tdoc);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string py_autogen_comment();
-  std::string py_imports();
-  std::string render_includes();
-  std::string declare_argument(t_field* tfield);
-  std::string render_field_default_value(t_field* tfield);
-  std::string type_name(t_type* ttype);
-  std::string function_signature(t_function* tfunction, bool interface = false);
-  std::string argument_list(t_struct* tstruct,
-                            std::vector<std::string>* pre = NULL,
-                            std::vector<std::string>* post = NULL);
-  std::string type_to_enum(t_type* ttype);
-  std::string type_to_spec_args(t_type* ttype);
-
-  static bool is_valid_namespace(const std::string& sub_namespace) {
-    return sub_namespace == "twisted";
-  }
-
-  static std::string get_real_py_module(const t_program* program, bool gen_twisted, std::string package_dir="") {
-    if (gen_twisted) {
-      std::string twisted_module = program->get_namespace("py.twisted");
-      if (!twisted_module.empty()) {
-        return twisted_module;
-      }
-    }
-
-    std::string real_module = program->get_namespace("py");
-    if (real_module.empty()) {
-      return program->get_name();
-    }
-    return package_dir + real_module;
-  }
-
-  static bool is_immutable(t_type* ttype) {
-    return ttype->annotations_.find("python.immutable") != ttype->annotations_.end();
-  }
-
-private:
-
-  /**
-   * True if we should generate new-style classes.
-   */
-  bool gen_newstyle_;
-
-  /**
-  * True if we should generate dynamic style classes.
-  */
-  bool gen_dynamic_;
-
-  bool gen_dynbase_;
-  std::string gen_dynbaseclass_;
-  std::string gen_dynbaseclass_frozen_;
-  std::string gen_dynbaseclass_exc_;
-
-  std::string import_dynbase_;
-
-  bool gen_slots_;
-
-  std::string copy_options_;
-
-  /**
-   * True if we should generate Twisted-friendly RPC services.
-   */
-  bool gen_twisted_;
-
-  /**
-   * True if we should generate code for use with Tornado
-   */
-  bool gen_tornado_;
-
-  /**
-   * True if strings should be encoded using utf-8.
-   */
-  bool gen_utf8strings_;
-
-  /**
-   * specify generated file encoding
-   * eg. # -*- coding: utf-8 -*-
-   */
-  string coding_;
-
-  string package_prefix_;
-
-  /**
-   * File streams
-   */
-
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_service_;
-
-  std::string package_dir_;
-  std::string module_;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_py_generator::init_generator() {
-  // Make output directory
-  string module = get_real_py_module(program_, gen_twisted_);
-  package_dir_ = get_out_dir();
-  module_ = module;
-  while (true) {
-    // TODO: Do better error checking here.
-    MKDIR(package_dir_.c_str());
-    std::ofstream init_py((package_dir_ + "/__init__.py").c_str(), std::ios_base::app);
-    init_py.close();
-    if (module.empty()) {
-      break;
-    }
-    string::size_type pos = module.find('.');
-    if (pos == string::npos) {
-      package_dir_ += "/";
-      package_dir_ += module;
-      module.clear();
-    } else {
-      package_dir_ += "/";
-      package_dir_ += module.substr(0, pos);
-      module.erase(0, pos + 1);
-    }
-  }
-
-  // Make output file
-  string f_types_name = package_dir_ + "/" + "ttypes.py";
-  f_types_.open(f_types_name.c_str());
-
-  string f_consts_name = package_dir_ + "/" + "constants.py";
-  f_consts_.open(f_consts_name.c_str());
-
-  string f_init_name = package_dir_ + "/__init__.py";
-  ofstream f_init;
-  f_init.open(f_init_name.c_str());
-  f_init << "__all__ = ['ttypes', 'constants'";
-  vector<t_service*> services = program_->get_services();
-  vector<t_service*>::iterator sv_iter;
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    f_init << ", '" << (*sv_iter)->get_name() << "'";
-  }
-  f_init << "]" << endl;
-  f_init.close();
-
-  // Print header
-  f_types_ << py_autogen_comment() << endl
-           << py_imports() << endl
-           << render_includes() << endl
-           << "from thrift.transport import TTransport" << endl
-           << import_dynbase_;
-
-  f_consts_ <<
-    py_autogen_comment() << endl <<
-    py_imports() << endl <<
-    "from .ttypes import *" << endl;
-}
-
-/**
- * Renders all the imports necessary for including another Thrift program
- */
-string t_py_generator::render_includes() {
-  const vector<t_program*>& includes = program_->get_includes();
-  string result = "";
-  for (size_t i = 0; i < includes.size(); ++i) {
-    result += "import " + get_real_py_module(includes[i], gen_twisted_, package_prefix_) + ".ttypes\n";
-  }
-  return result;
-}
-
-/**
- * Autogen'd comment
- */
-string t_py_generator::py_autogen_comment() {
-  string coding;
-  if (!coding_.empty()) {
-      coding = "# -*- coding: " + coding_ + " -*-\n";
-  }
-  return coding + std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-         + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n"
-         + "#  options string: " + copy_options_ + "\n" + "#\n";
-}
-
-/**
- * Prints standard thrift imports
- */
-string t_py_generator::py_imports() {
-  ostringstream ss;
-  ss << "from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, "
-        "TApplicationException"
-     << endl
-     << "from thrift.protocol.TProtocol import TProtocolException";
-  if (gen_utf8strings_) {
-    ss << endl << "import sys";
-  }
-  return ss.str();
-}
-
-/**
- * Closes the type files
- */
-void t_py_generator::close_generator() {
-  // Close types file
-  f_types_.close();
-  f_consts_.close();
-}
-
-/**
- * Generates a typedef. This is not done in Python, types are all implicit.
- *
- * @param ttypedef The type definition
- */
-void t_py_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Generates code for an enumerated type. Done using a class to scope
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_py_generator::generate_enum(t_enum* tenum) {
-  std::ostringstream to_string_mapping, from_string_mapping;
-
-  f_types_ << endl << endl << "class " << tenum->get_name() << (gen_newstyle_ ? "(object)" : "")
-           << (gen_dynamic_ ? "(" + gen_dynbaseclass_ + ")" : "") << ":" << endl;
-  indent_up();
-  generate_python_docstring(f_types_, tenum);
-
-  to_string_mapping << indent() << "_VALUES_TO_NAMES = {" << endl;
-  from_string_mapping << indent() << "_NAMES_TO_VALUES = {" << endl;
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_types_) << (*c_iter)->get_name() << " = " << value << endl;
-
-    // Dictionaries to/from string names of enums
-    to_string_mapping << indent() << indent() << value << ": \""
-                      << escape_string((*c_iter)->get_name()) << "\"," << endl;
-    from_string_mapping << indent() << indent() << '"' << escape_string((*c_iter)->get_name())
-                        << "\": " << value << ',' << endl;
-  }
-  to_string_mapping << indent() << "}" << endl;
-  from_string_mapping << indent() << "}" << endl;
-
-  indent_down();
-  f_types_ << endl;
-  f_types_ << to_string_mapping.str() << endl << from_string_mapping.str();
-}
-
-/**
- * Generate a constant value
- */
-void t_py_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = tconst->get_name();
-  t_const_value* value = tconst->get_value();
-
-  indent(f_consts_) << name << " = " << render_const_value(type, value);
-  f_consts_ << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_py_generator::render_const_value(t_type* type, t_const_value* value) {
-  type = get_true_type(type);
-  std::ostringstream out;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "True" : "False");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    out << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << type_name(type) << "(**{" << endl;
-    indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      indent(out) << render_const_value(g_type_string, v_iter->first) << ": "
-          << render_const_value(field_type, v_iter->second) << "," << endl;
-    }
-    indent_down();
-    indent(out) << "})";
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    if (is_immutable(type)) {
-      out << "TFrozenDict(";
-    }
-    out << "{" << endl;
-    indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      indent(out) << render_const_value(ktype, v_iter->first) << ": "
-          << render_const_value(vtype, v_iter->second) << "," << endl;
-    }
-    indent_down();
-    indent(out) << "}";
-    if (is_immutable(type)) {
-      out << ")";
-    }
-  } else if (type->is_list() || type->is_set()) {
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    if (type->is_set()) {
-      if (is_immutable(type)) {
-        out << "frozen";
-      }
-      out << "set(";
-    }
-    if (is_immutable(type) || type->is_set()) {
-      out << "(" << endl;
-    } else {
-      out << "[" << endl;
-    }
-    indent_up();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      indent(out) << render_const_value(etype, *v_iter) << "," << endl;
-    }
-    indent_down();
-    if (is_immutable(type) || type->is_set()) {
-      indent(out) << ")";
-    } else {
-      indent(out) << "]";
-    }
-    if (type->is_set()) {
-      out << ")";
-    }
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-
-  return out.str();
-}
-
-/**
- * Generates a python struct
- */
-void t_py_generator::generate_struct(t_struct* tstruct) {
-  generate_py_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_py_generator::generate_xception(t_struct* txception) {
-  generate_py_struct(txception, true);
-}
-
-/**
- * Generates a python struct
- */
-void t_py_generator::generate_py_struct(t_struct* tstruct, bool is_exception) {
-  generate_py_struct_definition(f_types_, tstruct, is_exception);
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_py_generator::generate_py_struct_definition(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   bool is_exception) {
-  const vector<t_field*>& members = tstruct->get_members();
-  const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  out << endl << endl << "class " << tstruct->get_name();
-  if (is_exception) {
-    if (gen_dynamic_) {
-      out << "(" << gen_dynbaseclass_exc_ << ")";
-    } else {
-      out << "(TException)";
-    }
-  } else if (gen_dynamic_) {
-    if (is_immutable(tstruct)) {
-      out << "(" << gen_dynbaseclass_frozen_ << ")";
-    } else  {
-      out << "(" << gen_dynbaseclass_ << ")";
-    }
-  } else if (gen_newstyle_) {
-    out << "(object)";
-  }
-  out << ":" << endl;
-  indent_up();
-  generate_python_docstring(out, tstruct);
-
-  out << endl;
-
-  /*
-     Here we generate the structure specification for the fastbinary codec.
-     These specifications have the following structure:
-     thrift_spec -> tuple of item_spec
-     item_spec -> None | (tag, type_enum, name, spec_args, default)
-     tag -> integer
-     type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ...
-     name -> string_literal
-     default -> None  # Handled by __init__
-     spec_args -> None  # For simple types
-                | (type_enum, spec_args)  # Value type for list/set
-                | (type_enum, spec_args, type_enum, spec_args)
-                  # Key and value for map
-                | (class_name, spec_args_ptr) # For struct/exception
-     class_name -> identifier  # Basically a pointer to the class
-     spec_args_ptr -> expression  # just class_name.spec_args
-
-     TODO(dreiss): Consider making this work for structs with negative tags.
-  */
-
-  if (gen_slots_) {
-    indent(out) << "__slots__ = (" << endl;
-    indent_up();
-    for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
-      indent(out) << "'" << (*m_iter)->get_name() << "'," << endl;
-    }
-    indent_down();
-    indent(out) << ")" << endl << endl;
-  }
-
-  // TODO(dreiss): Look into generating an empty tuple instead of None
-  // for structures with no members.
-  // TODO(dreiss): Test encoding of structs where some inner structs
-  // don't have thrift_spec.
-  if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) {
-    indent(out) << "thrift_spec = (" << endl;
-    indent_up();
-
-    int sorted_keys_pos = 0;
-    for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
-
-      for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) {
-        indent(out) << "None,  # " << sorted_keys_pos << endl;
-      }
-
-      indent(out) << "(" << (*m_iter)->get_key() << ", " << type_to_enum((*m_iter)->get_type())
-                  << ", "
-                  << "'" << (*m_iter)->get_name() << "'"
-                  << ", " << type_to_spec_args((*m_iter)->get_type()) << ", "
-                  << render_field_default_value(*m_iter) << ", "
-                  << "),"
-                  << "  # " << sorted_keys_pos << endl;
-
-      sorted_keys_pos++;
-    }
-
-    indent_down();
-    indent(out) << ")" << endl;
-  } else {
-    indent(out) << "thrift_spec = None" << endl;
-  }
-
-  if (members.size() > 0) {
-    out << endl;
-    out << indent() << "def __init__(self,";
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      // This fills in default values, as opposed to nulls
-      out << " " << declare_argument(*m_iter) << ",";
-    }
-
-    out << "):" << endl;
-
-    indent_up();
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      // Initialize fields
-      t_type* type = (*m_iter)->get_type();
-      if (!type->is_base_type() && !type->is_enum() && (*m_iter)->get_value() != NULL) {
-        indent(out) << "if " << (*m_iter)->get_name() << " is "
-                    << "self.thrift_spec[" << (*m_iter)->get_key() << "][4]:" << endl;
-        indent_up();
-        indent(out) << (*m_iter)->get_name() << " = " << render_field_default_value(*m_iter)
-                    << endl;
-        indent_down();
-      }
-
-      if (is_immutable(tstruct)) {
-        if (gen_newstyle_ || gen_dynamic_) {
-          indent(out) << "super(" << tstruct->get_name() << ", self).__setattr__('"
-                      << (*m_iter)->get_name() << "', " << (*m_iter)->get_name() << ")" << endl;
-        } else {
-          indent(out) << "self.__dict__['" << (*m_iter)->get_name()
-                      << "'] = " << (*m_iter)->get_name() << endl;
-        }
-      } else {
-        indent(out) << "self." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << endl;
-      }
-    }
-
-    indent_down();
-  }
-
-  if (is_immutable(tstruct)) {
-    out << endl;
-    out << indent() << "def __setattr__(self, *args):" << endl
-        << indent() << indent_str() << "raise TypeError(\"can't modify immutable instance\")" << endl
-        << endl;
-    out << indent() << "def __delattr__(self, *args):" << endl
-        << indent() << indent_str() << "raise TypeError(\"can't modify immutable instance\")" << endl
-        << endl;
-
-    // Hash all of the members in order, and also hash in the class
-    // to avoid collisions for stuff like single-field structures.
-    out << indent() << "def __hash__(self):" << endl
-        << indent() << indent_str() << "return hash(self.__class__) ^ hash((";
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      out << "self." << (*m_iter)->get_name() << ", ";
-    }
-
-    out << "))" << endl;
-  }
-
-  if (!gen_dynamic_) {
-    out << endl;
-    generate_py_struct_reader(out, tstruct);
-    generate_py_struct_writer(out, tstruct);
-  }
-
-  // For exceptions only, generate a __str__ method. This is
-  // because when raised exceptions are printed to the console, __repr__
-  // isn't used. See python bug #5882
-  if (is_exception) {
-    out << endl;
-    out << indent() << "def __str__(self):" << endl
-        << indent() << indent_str() << "return repr(self)" << endl;
-  }
-
-  if (!gen_slots_) {
-    out << endl;
-    // Printing utilities so that on the command line thrift
-    // structs look pretty like dictionaries
-    indent(out) << "def __repr__(self):" << endl;
-    indent_up();
-    out << indent() << "L = ['%s=%r' % (key, value)" << endl
-        << indent() << "     for key, value in self.__dict__.items()]" << endl
-        << indent() << "return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl
-        << endl;
-    indent_down();
-
-    // Equality and inequality methods that compare by value
-    out << indent() << "def __eq__(self, other):" << endl;
-    indent_up();
-    out << indent() << "return isinstance(other, self.__class__) and "
-                       "self.__dict__ == other.__dict__" << endl;
-    indent_down();
-    out << endl;
-
-    out << indent() << "def __ne__(self, other):" << endl;
-    indent_up();
-
-    out << indent() << "return not (self == other)" << endl;
-    indent_down();
-  } else if (!gen_dynamic_) {
-    out << endl;
-    // no base class available to implement __eq__ and __repr__ and __ne__ for us
-    // so we must provide one that uses __slots__
-    indent(out) << "def __repr__(self):" << endl;
-    indent_up();
-    out << indent() << "L = ['%s=%r' % (key, getattr(self, key))" << endl
-        << indent() << "     for key in self.__slots__]" << endl
-        << indent() << "return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl
-        << endl;
-    indent_down();
-
-    // Equality method that compares each attribute by value and type, walking __slots__
-    out << indent() << "def __eq__(self, other):" << endl;
-    indent_up();
-    out << indent() << "if not isinstance(other, self.__class__):" << endl
-        << indent() << indent_str() << "return False" << endl
-        << indent() << "for attr in self.__slots__:" << endl
-        << indent() << indent_str() << "my_val = getattr(self, attr)" << endl
-        << indent() << indent_str() << "other_val = getattr(other, attr)" << endl
-        << indent() << indent_str() << "if my_val != other_val:" << endl
-        << indent() << indent_str() << indent_str() << "return False" << endl
-        << indent() << "return True" << endl
-        << endl;
-    indent_down();
-
-    out << indent() << "def __ne__(self, other):" << endl
-        << indent() << indent_str() << "return not (self == other)" << endl;
-  }
-  indent_down();
-}
-
-/**
- * Generates the read method for a struct
- */
-void t_py_generator::generate_py_struct_reader(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  if (is_immutable(tstruct)) {
-    out << indent() << "@classmethod" << endl << indent() << "def read(cls, iprot):" << endl;
-  } else {
-    indent(out) << "def read(self, iprot):" << endl;
-  }
-  indent_up();
-
-  const char* id = is_immutable(tstruct) ? "cls" : "self";
-
-  indent(out) << "if iprot._fast_decode is not None "
-                 "and isinstance(iprot.trans, TTransport.CReadableTransport) "
-                 "and "
-              << id << ".thrift_spec is not None:" << endl;
-  indent_up();
-
-  if (is_immutable(tstruct)) {
-    indent(out) << "return iprot._fast_decode(None, iprot, (cls, cls.thrift_spec))" << endl;
-  } else {
-    indent(out) << "iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))" << endl;
-    indent(out) << "return" << endl;
-  }
-  indent_down();
-
-  indent(out) << "iprot.readStructBegin()" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while True:" << endl;
-  indent_up();
-
-  // Read beginning field marker
-  indent(out) << "(fname, ftype, fid) = iprot.readFieldBegin()" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if ftype == TType.STOP:" << endl;
-  indent_up();
-  indent(out) << "break" << endl;
-  indent_down();
-
-  // Switch statement on the field we are reading
-  bool first = true;
-
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out << indent() << "if ";
-    } else {
-      out << indent() << "elif ";
-    }
-    out << "fid == " << (*f_iter)->get_key() << ":" << endl;
-    indent_up();
-    indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << ":" << endl;
-    indent_up();
-    if (is_immutable(tstruct)) {
-      generate_deserialize_field(out, *f_iter);
-    } else {
-      generate_deserialize_field(out, *f_iter, "self.");
-    }
-    indent_down();
-    out << indent() << "else:" << endl << indent() << indent_str() << "iprot.skip(ftype)" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  out << indent() << "else:" << endl << indent() << indent_str() << "iprot.skip(ftype)" << endl;
-
-  // Read field end marker
-  indent(out) << "iprot.readFieldEnd()" << endl;
-
-  indent_down();
-
-  indent(out) << "iprot.readStructEnd()" << endl;
-
-  if (is_immutable(tstruct)) {
-    indent(out) << "return cls(" << endl;
-    indent_up();
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      indent(out) << (*f_iter)->get_name() << "=" << (*f_iter)->get_name() << "," << endl;
-    }
-    indent_down();
-    indent(out) << ")" << endl;
-  }
-
-  indent_down();
-  out << endl;
-}
-
-void t_py_generator::generate_py_struct_writer(ofstream& out, t_struct* tstruct) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent(out) << "def write(self, oprot):" << endl;
-  indent_up();
-
-  indent(out) << "if oprot._fast_encode is not None and self.thrift_spec is not None:" << endl;
-  indent_up();
-
-  indent(out)
-      << "oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))"
-      << endl;
-  indent(out) << "return" << endl;
-  indent_down();
-
-  indent(out) << "oprot.writeStructBegin('" << name << "')" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    // Write field header
-    indent(out) << "if self." << (*f_iter)->get_name() << " is not None:" << endl;
-    indent_up();
-    indent(out) << "oprot.writeFieldBegin("
-                << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
-                << ", " << (*f_iter)->get_key() << ")" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "self.");
-
-    // Write field closer
-    indent(out) << "oprot.writeFieldEnd()" << endl;
-
-    indent_down();
-  }
-
-  // Write the struct map
-  out << indent() << "oprot.writeFieldStop()" << endl << indent() << "oprot.writeStructEnd()"
-      << endl;
-
-  out << endl;
-
-  indent_down();
-  generate_py_struct_required_validator(out, tstruct);
-}
-
-void t_py_generator::generate_py_struct_required_validator(ofstream& out, t_struct* tstruct) {
-  indent(out) << "def validate(self):" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-
-  if (fields.size() > 0) {
-    vector<t_field*>::const_iterator f_iter;
-
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* field = (*f_iter);
-      if (field->get_req() == t_field::T_REQUIRED) {
-        indent(out) << "if self." << field->get_name() << " is None:" << endl;
-        indent(out) << indent_str() << "raise TProtocolException(message='Required field "
-                    << field->get_name() << " is unset!')" << endl;
-      }
-    }
-  }
-
-  indent(out) << "return" << endl;
-  indent_down();
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_py_generator::generate_service(t_service* tservice) {
-  string f_service_name = package_dir_ + "/" + service_name_ + ".py";
-  f_service_.open(f_service_name.c_str());
-
-  f_service_ << py_autogen_comment() << endl << py_imports() << endl;
-
-  if (tservice->get_extends() != NULL) {
-    f_service_ << "import "
-               << get_real_py_module(tservice->get_extends()->get_program(), gen_twisted_, package_prefix_) << "."
-               << tservice->get_extends()->get_name() << endl;
-  }
-
-  f_service_ << "import logging" << endl
-             << "from .ttypes import *" << endl
-             << "from thrift.Thrift import TProcessor" << endl
-             << "from thrift.transport import TTransport" << endl
-             << import_dynbase_;
-
-  if (gen_twisted_) {
-    f_service_ << "from zope.interface import Interface, implements" << endl
-               << "from twisted.internet import defer" << endl
-               << "from thrift.transport import TTwisted" << endl;
-  } else if (gen_tornado_) {
-    f_service_ << "from tornado import gen" << endl;
-    f_service_ << "from tornado import concurrent" << endl;
-  }
-
-  // Generate the three main parts of the service
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-  generate_service_remote(tservice);
-
-  // Close service file
-  f_service_.close();
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_py_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  f_service_ << endl << "# HELPER FUNCTIONS AND STRUCTURES" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_py_struct_definition(f_service_, ts, false);
-    generate_py_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_py_generator::generate_py_function_helpers(t_function* tfunction) {
-  if (!tfunction->is_oneway()) {
-    t_struct result(program_, tfunction->get_name() + "_result");
-    t_field success(tfunction->get_returntype(), "success", 0);
-    if (!tfunction->get_returntype()->is_void()) {
-      result.append(&success);
-    }
-
-    t_struct* xs = tfunction->get_xceptions();
-    const vector<t_field*>& fields = xs->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      result.append(*f_iter);
-    }
-    generate_py_struct_definition(f_service_, &result, false);
-  }
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_py_generator::generate_service_interface(t_service* tservice) {
-  string extends = "";
-  string extends_if = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_if = "(" + extends + ".Iface)";
-  } else {
-    if (gen_twisted_) {
-      extends_if = "(Interface)";
-    } else if (gen_newstyle_ || gen_dynamic_ || gen_tornado_) {
-      extends_if = "(object)";
-    }
-  }
-
-  f_service_ << endl << endl << "class Iface" << extends_if << ":" << endl;
-  indent_up();
-  generate_python_docstring(f_service_, tservice);
-  vector<t_function*> functions = tservice->get_functions();
-  if (functions.empty()) {
-    f_service_ << indent() << "pass" << endl;
-  } else {
-    vector<t_function*>::iterator f_iter;
-    bool first = true;
-    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << endl;
-      }
-      f_service_ << indent() << "def " << function_signature(*f_iter, true) << ":" << endl;
-      indent_up();
-      generate_python_docstring(f_service_, (*f_iter));
-      f_service_ << indent() << "pass" << endl;
-      indent_down();
-    }
-  }
-
-  indent_down();
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_py_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    if (gen_twisted_) {
-      extends_client = "(" + extends + ".Client)";
-    } else {
-      extends_client = extends + ".Client, ";
-    }
-  } else {
-    if (gen_twisted_ && (gen_newstyle_ || gen_dynamic_)) {
-      extends_client = "(object)";
-    }
-  }
-
-  f_service_ << endl << endl;
-
-  if (gen_twisted_) {
-    f_service_ << "class Client" << extends_client << ":" << endl
-               << indent_str() << "implements(Iface)" << endl
-               << endl;
-  } else {
-    f_service_ << "class Client(" << extends_client << "Iface):" << endl;
-  }
-  indent_up();
-  generate_python_docstring(f_service_, tservice);
-
-  // Constructor function
-  if (gen_twisted_) {
-    f_service_ << indent() << "def __init__(self, transport, oprot_factory):" << endl;
-  } else if (gen_tornado_) {
-    f_service_ << indent()
-               << "def __init__(self, transport, iprot_factory, oprot_factory=None):" << endl;
-  } else {
-    f_service_ << indent() << "def __init__(self, iprot, oprot=None):" << endl;
-  }
-  indent_up();
-  if (extends.empty()) {
-    if (gen_twisted_) {
-      f_service_ << indent() << "self._transport = transport" << endl
-                 << indent() << "self._oprot_factory = oprot_factory" << endl
-                 << indent() << "self._seqid = 0" << endl
-                 << indent() << "self._reqs = {}" << endl;
-    } else if (gen_tornado_) {
-      f_service_ << indent() << "self._transport = transport" << endl
-                 << indent() << "self._iprot_factory = iprot_factory" << endl
-                 << indent() << "self._oprot_factory = (oprot_factory if oprot_factory is not None"
-                 << endl
-                 << indent() << "                       else iprot_factory)" << endl
-                 << indent() << "self._seqid = 0" << endl
-                 << indent() << "self._reqs = {}" << endl
-                 << indent() << "self._transport.io_loop.spawn_callback(self._start_receiving)"
-                 << endl;
-    } else {
-      f_service_ << indent() << "self._iprot = self._oprot = iprot" << endl
-                 << indent() << "if oprot is not None:" << endl
-                 << indent() << indent_str() << "self._oprot = oprot" << endl
-                 << indent() << "self._seqid = 0" << endl;
-    }
-  } else {
-    if (gen_twisted_) {
-      f_service_ << indent() << extends
-                 << ".Client.__init__(self, transport, oprot_factory)" << endl;
-    } else if (gen_tornado_) {
-      f_service_ << indent() << extends
-                 << ".Client.__init__(self, transport, iprot_factory, oprot_factory)" << endl;
-    } else {
-      f_service_ << indent() << extends << ".Client.__init__(self, iprot, oprot)" << endl;
-    }
-  }
-  indent_down();
-
-  if (gen_tornado_ && extends.empty()) {
-    f_service_ << endl <<
-      indent() << "@gen.engine" << endl <<
-      indent() << "def _start_receiving(self):" << endl;
-    indent_up();
-    indent(f_service_) << "while True:" << endl;
-    indent_up();
-    f_service_ << indent() << "try:" << endl
-               << indent() << indent_str() << "frame = yield self._transport.readFrame()" << endl
-               << indent() << "except TTransport.TTransportException as e:" << endl
-               << indent() << indent_str() << "for future in self._reqs.values():" << endl
-               << indent() << indent_str() << indent_str() << "future.set_exception(e)" << endl
-               << indent() << indent_str() << "self._reqs = {}" << endl
-               << indent() << indent_str() << "return" << endl
-               << indent() << "tr = TTransport.TMemoryBuffer(frame)" << endl
-               << indent() << "iprot = self._iprot_factory.getProtocol(tr)" << endl
-               << indent() << "(fname, mtype, rseqid) = iprot.readMessageBegin()" << endl
-               << indent() << "method = getattr(self, 'recv_' + fname)" << endl
-               << indent() << "future = self._reqs.pop(rseqid, None)" << endl
-               << indent() << "if not future:" << endl
-               << indent() << indent_str() << "# future has already been discarded" << endl
-               << indent() << indent_str() << "continue" << endl
-               << indent() << "try:" << endl
-               << indent() << indent_str() << "result = method(iprot, mtype, rseqid)" << endl
-               << indent() << "except Exception as e:" << endl
-               << indent() << indent_str() << "future.set_exception(e)" << endl
-               << indent() << "else:" << endl
-               << indent() << indent_str() << "future.set_result(result)" << endl;
-    indent_down();
-    indent_down();
-  }
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-
-    f_service_ << endl;
-    // Open function
-    indent(f_service_) << "def " << function_signature(*f_iter, false) << ":" << endl;
-    indent_up();
-    generate_python_docstring(f_service_, (*f_iter));
-    if (gen_twisted_) {
-      indent(f_service_) << "seqid = self._seqid = self._seqid + 1" << endl;
-      indent(f_service_) << "self._reqs[seqid] = defer.Deferred()" << endl << endl;
-      indent(f_service_) << "d = defer.maybeDeferred(self.send_" << funname;
-
-    } else if (gen_tornado_) {
-      indent(f_service_) << "self._seqid += 1" << endl;
-      if (!(*f_iter)->is_oneway()) {
-        indent(f_service_) << "future = self._reqs[self._seqid] = concurrent.Future()" << endl;
-      }
-      indent(f_service_) << "self.send_" << funname << "(";
-
-    } else {
-      indent(f_service_) << "self.send_" << funname << "(";
-    }
-
-    bool first = true;
-    if (gen_twisted_) {
-      // we need a leading comma if there are args, since it's called as maybeDeferred(funcname,
-      // arg)
-      first = false;
-    }
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << (*fld_iter)->get_name();
-    }
-
-    f_service_ << ")" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      if (gen_twisted_) {
-        // nothing. See the next block.
-      } else if (gen_tornado_) {
-        indent(f_service_) << "return future" << endl;
-      } else {
-        f_service_ << indent();
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          f_service_ << "return ";
-        }
-        f_service_ << "self.recv_" << funname << "()" << endl;
-      }
-    }
-    indent_down();
-
-    if (gen_twisted_) {
-      // This block injects the body of the send_<> method for twisted (and a cb/eb pair)
-      indent_up();
-      indent(f_service_) << "d.addCallbacks(" << endl;
-
-      indent_up();
-      f_service_ << indent() << "callback=self.cb_send_" << funname << "," << endl << indent()
-                 << "callbackArgs=(seqid,)," << endl << indent() << "errback=self.eb_send_"
-                 << funname << "," << endl << indent() << "errbackArgs=(seqid,))" << endl;
-      indent_down();
-
-      indent(f_service_) << "return d" << endl;
-      indent_down();
-      f_service_ << endl;
-
-      indent(f_service_) << "def cb_send_" << funname << "(self, _, seqid):" << endl;
-      indent_up();
-      if ((*f_iter)->is_oneway()) {
-        // if one-way, fire the deferred & remove it from _reqs
-        f_service_ << indent() << "d = self._reqs.pop(seqid)" << endl << indent()
-                   << "d.callback(None)" << endl << indent() << "return d" << endl;
-      } else {
-        f_service_ << indent() << "return self._reqs[seqid]" << endl;
-      }
-      indent_down();
-      f_service_ << endl;
-
-      // add an errback to fail the request if the call to send_<> raised an exception
-      indent(f_service_) << "def eb_send_" << funname << "(self, f, seqid):" << endl;
-      indent_up();
-      f_service_ << indent() << "d = self._reqs.pop(seqid)" << endl << indent() << "d.errback(f)"
-                 << endl << indent() << "return d" << endl;
-      indent_down();
-    }
-
-    f_service_ << endl;
-    indent(f_service_) << "def send_" << function_signature(*f_iter, false) << ":" << endl;
-    indent_up();
-
-    std::string argsname = (*f_iter)->get_name() + "_args";
-    std::string messageType = (*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL";
-
-    // Serialize the request header
-    if (gen_twisted_ || gen_tornado_) {
-      f_service_ << indent() << "oprot = self._oprot_factory.getProtocol(self._transport)" << endl
-                 << indent() << "oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', "
-                 << messageType << ", self._seqid)" << endl;
-    } else {
-      f_service_ << indent() << "self._oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', "
-                 << messageType << ", self._seqid)" << endl;
-    }
-
-    f_service_ << indent() << "args = " << argsname << "()" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
-                 << (*fld_iter)->get_name() << endl;
-    }
-
-    // Write to the stream
-    if (gen_twisted_ || gen_tornado_) {
-      f_service_ << indent() << "args.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()"
-                 << endl << indent() << "oprot.trans.flush()" << endl;
-    } else {
-      f_service_ << indent() << "args.write(self._oprot)" << endl << indent()
-                 << "self._oprot.writeMessageEnd()" << endl << indent()
-                 << "self._oprot.trans.flush()" << endl;
-    }
-
-    indent_down();
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = (*f_iter)->get_name() + "_result";
-      // Open function
-      f_service_ << endl;
-      if (gen_twisted_ || gen_tornado_) {
-        f_service_ << indent() << "def recv_" << (*f_iter)->get_name()
-                   << "(self, iprot, mtype, rseqid):" << endl;
-      } else {
-        t_struct noargs(program_);
-        t_function recv_function((*f_iter)->get_returntype(),
-                                 string("recv_") + (*f_iter)->get_name(),
-                                 &noargs);
-        f_service_ << indent() << "def " << function_signature(&recv_function) << ":" << endl;
-      }
-      indent_up();
-
-      // TODO(mcslee): Validate message reply here, seq ids etc.
-
-      if (gen_twisted_) {
-        f_service_ << indent() << "d = self._reqs.pop(rseqid)" << endl;
-      } else if (gen_tornado_) {
-      } else {
-        f_service_ << indent() << "iprot = self._iprot" << endl << indent()
-                   << "(fname, mtype, rseqid) = iprot.readMessageBegin()" << endl;
-      }
-
-      f_service_ << indent() << "if mtype == TMessageType.EXCEPTION:" << endl
-                 << indent() << indent_str() << "x = TApplicationException()" << endl;
-
-      if (gen_twisted_) {
-        f_service_ << indent() << indent_str() << "x.read(iprot)" << endl << indent()
-                   << indent_str() << "iprot.readMessageEnd()" << endl << indent() << indent_str() << "return d.errback(x)"
-                   << endl << indent() << "result = " << resultname << "()" << endl << indent()
-                   << "result.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl;
-      } else {
-        f_service_ << indent() << indent_str() << "x.read(iprot)" << endl << indent()
-                   << indent_str() << "iprot.readMessageEnd()" << endl << indent() << indent_str() << "raise x" << endl
-                   << indent() << "result = " << resultname << "()" << endl << indent()
-                   << "result.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl;
-      }
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "if result.success is not None:" << endl;
-        if (gen_twisted_) {
-          f_service_ << indent() << indent_str() << "return d.callback(result.success)" << endl;
-        } else {
-          f_service_ << indent() << indent_str() << "return result.success" << endl;
-        }
-      }
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "if result." << (*x_iter)->get_name() << " is not None:" << endl;
-        if (gen_twisted_) {
-          f_service_ << indent() << indent_str() << "return d.errback(result." << (*x_iter)->get_name() << ")"
-                     << endl;
-        } else {
-          f_service_ << indent() << indent_str() << "raise result." << (*x_iter)->get_name() << "" << endl;
-        }
-      }
-
-      // Careful, only return _result if not a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        if (gen_twisted_) {
-          f_service_ << indent() << "return d.callback(None)" << endl;
-        } else {
-          f_service_ << indent() << "return" << endl;
-        }
-      } else {
-        if (gen_twisted_) {
-          f_service_
-              << indent()
-              << "return d.errback(TApplicationException(TApplicationException.MISSING_RESULT, \""
-              << (*f_iter)->get_name() << " failed: unknown result\"))" << endl;
-        } else {
-          f_service_ << indent()
-                     << "raise TApplicationException(TApplicationException.MISSING_RESULT, \""
-                     << (*f_iter)->get_name() << " failed: unknown result\")" << endl;
-        }
-      }
-
-      // Close function
-      indent_down();
-    }
-  }
-
-  indent_down();
-}
-
-/**
- * Generates a command line tool for making remote requests
- *
- * @param tservice The service to generate a remote for.
- */
-void t_py_generator::generate_service_remote(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  // Get all function from parents
-  t_service* parent = tservice->get_extends();
-  while (parent != NULL) {
-    vector<t_function*> p_functions = parent->get_functions();
-    functions.insert(functions.end(), p_functions.begin(), p_functions.end());
-    parent = parent->get_extends();
-  }
-  vector<t_function*>::iterator f_iter;
-
-  string f_remote_name = package_dir_ + "/" + service_name_ + "-remote";
-  ofstream f_remote;
-  f_remote.open(f_remote_name.c_str());
-
-  f_remote <<
-    "#!/usr/bin/env python" << endl <<
-    py_autogen_comment() << endl <<
-    "import sys" << endl <<
-    "import pprint" << endl <<
-    "if sys.version_info[0] > 2:" << endl <<
-    indent_str() << "from urllib.parse import urlparse" << endl <<
-    "else:" << endl <<
-    indent_str() << "from urlparse import urlparse" << endl <<
-    "from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient" << endl <<
-    "from thrift.protocol.TBinaryProtocol import TBinaryProtocol" << endl <<
-    endl;
-
-  f_remote <<
-    "from " << module_ << " import " << service_name_ << endl <<
-    "from " << module_ << ".ttypes import *" << endl <<
-    endl;
-
-  f_remote <<
-    "if len(sys.argv) <= 1 or sys.argv[1] == '--help':" << endl <<
-    indent_str() << "print('')" << endl <<
-    indent_str() << "print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] function [arg1 [arg2...]]')" << endl <<
-    indent_str() << "print('')" << endl <<
-    indent_str() << "print('Functions:')" << endl;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_remote << indent_str() << "print('  " << (*f_iter)->get_returntype()->get_name() << " "
-             << (*f_iter)->get_name() << "(";
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
-    std::vector<t_field*>::size_type num_args = args.size();
-    bool first = true;
-    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
-      if (first) {
-        first = false;
-      } else {
-        f_remote << ", ";
-      }
-      f_remote << args[i]->get_type()->get_name() << " " << args[i]->get_name();
-    }
-    f_remote << ")')" << endl;
-  }
-  f_remote << indent_str() << "print('')" << endl << indent_str() << "sys.exit(0)" << endl << endl;
-
-  f_remote << "pp = pprint.PrettyPrinter(indent=2)" << endl
-           << "host = 'localhost'" << endl
-           << "port = 9090" << endl
-           << "uri = ''" << endl
-           << "framed = False" << endl
-           << "ssl = False" << endl
-           << "http = False" << endl
-           << "argi = 1" << endl
-           << endl
-           << "if sys.argv[argi] == '-h':" << endl
-           << indent_str() << "parts = sys.argv[argi + 1].split(':')" << endl
-           << indent_str() << "host = parts[0]" << endl
-           << indent_str() << "if len(parts) > 1:" << endl
-           << indent_str() << indent_str() << "port = int(parts[1])" << endl
-           << indent_str() << "argi += 2" << endl
-           << endl
-           << "if sys.argv[argi] == '-u':" << endl
-           << indent_str() << "url = urlparse(sys.argv[argi + 1])" << endl
-           << indent_str() << "parts = url[1].split(':')" << endl
-           << indent_str() << "host = parts[0]" << endl
-           << indent_str() << "if len(parts) > 1:" << endl
-           << indent_str() << indent_str() << "port = int(parts[1])" << endl
-           << indent_str() << "else:" << endl
-           << indent_str() << indent_str() << "port = 80" << endl
-           << indent_str() << "uri = url[2]" << endl
-           << indent_str() << "if url[4]:" << endl
-           << indent_str() << indent_str() << "uri += '?%s' % url[4]" << endl
-           << indent_str() << "http = True" << endl
-           << indent_str() << "argi += 2" << endl
-           << endl
-           << "if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':" << endl
-           << indent_str() << "framed = True" << endl
-           << indent_str() << "argi += 1" << endl
-           << endl
-           << "if sys.argv[argi] == '-s' or sys.argv[argi] == '-ssl':" << endl
-           << indent_str() << "ssl = True" << endl
-           << indent_str() << "argi += 1" << endl
-           << endl
-           << "cmd = sys.argv[argi]" << endl
-           << "args = sys.argv[argi + 1:]" << endl
-           << endl
-           << "if http:" << endl
-           << indent_str() << "transport = THttpClient.THttpClient(host, port, uri)" << endl
-           << "else:" << endl
-           << indent_str() << "socket = TSSLSocket.TSSLSocket(host, port, validate=False) if ssl else "
-              "TSocket.TSocket(host, port)"
-           << endl
-           << indent_str() << "if framed:" << endl
-           << indent_str() << indent_str() << "transport = TTransport.TFramedTransport(socket)" << endl
-           << indent_str() << "else:" << endl
-           << indent_str() << indent_str() << "transport = TTransport.TBufferedTransport(socket)" << endl
-           << "protocol = TBinaryProtocol(transport)" << endl
-           << "client = " << service_name_ << ".Client(protocol)" << endl
-           << "transport.open()" << endl
-           << endl;
-
-  // Generate the dispatch methods
-  bool first = true;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_remote << "el";
-    }
-
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
-    std::vector<t_field*>::size_type num_args = args.size();
-
-    f_remote << "if cmd == '" << (*f_iter)->get_name() << "':" << endl;
-    indent_up();
-    f_remote << indent() << "if len(args) != " << num_args << ":" << endl
-             << indent() << indent_str() << "print('" << (*f_iter)->get_name() << " requires " << num_args
-             << " args')" << endl
-             << indent() << indent_str() << "sys.exit(1)" << endl
-             << indent() << "pp.pprint(client." << (*f_iter)->get_name() << "(";
-    indent_down();
-    bool first_arg = true;
-    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
-      if (first_arg)
-        first_arg = false;
-      else
-        f_remote << " ";
-      if (args[i]->get_type()->is_string()) {
-        f_remote << "args[" << i << "],";
-      } else {
-        f_remote << "eval(args[" << i << "]),";
-      }
-    }
-    f_remote << "))" << endl;
-
-    f_remote << endl;
-  }
-
-  if (functions.size() > 0) {
-    f_remote << "else:" << endl;
-    f_remote << indent_str() << "print('Unrecognized method %s' % cmd)" << endl;
-    f_remote << indent_str() << "sys.exit(1)" << endl;
-    f_remote << endl;
-  }
-
-  f_remote << "transport.close()" << endl;
-
-  // Close service file
-  f_remote.close();
-
-#ifndef _MSC_VER
-
-  // Make file executable, love that bitwise OR action
-  chmod(f_remote_name.c_str(),
-        S_IRUSR | S_IWUSR | S_IXUSR
-#ifndef _WIN32
-        | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
-#endif
-        );
-
-#endif // _MSC_VER
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_py_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_processor = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_processor = extends + ".Processor, ";
-  }
-
-  f_service_ << endl << endl;
-
-  // Generate the header portion
-  if (gen_twisted_) {
-    f_service_ << "class Processor(" << extends_processor << "TProcessor):" << endl
-               << indent_str() << "implements(Iface)" << endl << endl;
-  } else {
-    f_service_ << "class Processor(" << extends_processor << "Iface, TProcessor):" << endl;
-  }
-
-  indent_up();
-
-  indent(f_service_) << "def __init__(self, handler):" << endl;
-  indent_up();
-  if (extends.empty()) {
-    if (gen_twisted_) {
-      f_service_ << indent() << "self._handler = Iface(handler)" << endl;
-    } else {
-      f_service_ << indent() << "self._handler = handler" << endl;
-    }
-
-    f_service_ << indent() << "self._processMap = {}" << endl;
-  } else {
-    if (gen_twisted_) {
-      f_service_ << indent() << extends << ".Processor.__init__(self, Iface(handler))" << endl;
-    } else {
-      f_service_ << indent() << extends << ".Processor.__init__(self, handler)" << endl;
-    }
-  }
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "self._processMap[\"" << (*f_iter)->get_name()
-               << "\"] = Processor.process_" << (*f_iter)->get_name() << endl;
-  }
-  indent_down();
-  f_service_ << endl;
-
-  // Generate the server implementation
-  f_service_ << indent() << "def process(self, iprot, oprot):" << endl;
-  indent_up();
-
-  f_service_ << indent() << "(name, type, seqid) = iprot.readMessageBegin()" << endl;
-
-  // TODO(mcslee): validate message
-
-  // HOT: dictionary function lookup
-  f_service_ << indent() << "if name not in self._processMap:" << endl;
-  indent_up();
-  f_service_ << indent() << "iprot.skip(TType.STRUCT)" << endl
-             << indent() << "iprot.readMessageEnd()" << endl
-             << indent()
-             << "x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown "
-                "function %s' % (name))"
-             << endl
-             << indent() << "oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)" << endl
-             << indent() << "x.write(oprot)" << endl
-             << indent() << "oprot.writeMessageEnd()" << endl
-             << indent() << "oprot.trans.flush()" << endl;
-
-  if (gen_twisted_) {
-    f_service_ << indent() << "return defer.succeed(None)" << endl;
-  } else {
-    f_service_ << indent() << "return" << endl;
-  }
-  indent_down();
-
-  f_service_ << indent() << "else:" << endl;
-
-  if (gen_twisted_ || gen_tornado_) {
-    f_service_ << indent() << indent_str()
-               << "return self._processMap[name](self, seqid, iprot, oprot)" << endl;
-  } else {
-    f_service_ << indent() << indent_str() << "self._processMap[name](self, seqid, iprot, oprot)"
-               << endl;
-
-    // Read end of args field, the T_STOP, and the struct close
-    f_service_ << indent() << "return True" << endl;
-  }
-
-  indent_down();
-
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << endl;
-    generate_process_function(tservice, *f_iter);
-  }
-
-  indent_down();
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_py_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open function
-  if (gen_tornado_) {
-    f_service_ << indent() << "@gen.coroutine" << endl << indent() << "def process_"
-               << tfunction->get_name() << "(self, seqid, iprot, oprot):" << endl;
-  } else {
-    f_service_ << indent() << "def process_" << tfunction->get_name()
-               << "(self, seqid, iprot, oprot):" << endl;
-  }
-
-  indent_up();
-
-  string argsname = tfunction->get_name() + "_args";
-  string resultname = tfunction->get_name() + "_result";
-
-  f_service_ << indent() << "args = " << argsname << "()" << endl << indent() << "args.read(iprot)"
-             << endl << indent() << "iprot.readMessageEnd()" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "result = " << resultname << "()" << endl;
-  }
-
-  if (gen_twisted_) {
-    // TODO: Propagate arbitrary exception raised by handler to client as does plain "py"
-
-    // Generate the function call
-    t_struct* arg_struct = tfunction->get_arglist();
-    const std::vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    f_service_ << indent() << "d = defer.maybeDeferred(self._handler." << tfunction->get_name()
-               << ", ";
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-    f_service_ << ")" << endl;
-
-    // Shortcut out here for oneway functions
-    if (tfunction->is_oneway()) {
-      f_service_ << indent() << "return d" << endl;
-      indent_down();
-      f_service_ << endl;
-      return;
-    }
-
-    f_service_ << indent() << "d.addCallback(self.write_results_success_" << tfunction->get_name()
-               << ", result, seqid, oprot)" << endl;
-
-    if (xceptions.size() > 0) {
-      f_service_ << indent() << "d.addErrback(self.write_results_exception_"
-                 << tfunction->get_name() << ", result, seqid, oprot)" << endl;
-    }
-
-    f_service_ << indent() << "return d" << endl;
-
-    indent_down();
-    f_service_ << endl;
-
-    indent(f_service_) << "def write_results_success_" << tfunction->get_name()
-                       << "(self, success, result, seqid, oprot):" << endl;
-    indent_up();
-    f_service_ << indent() << "result.success = success" << endl << indent()
-               << "oprot.writeMessageBegin(\"" << tfunction->get_name()
-               << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)"
-               << endl << indent() << "oprot.writeMessageEnd()" << endl << indent()
-               << "oprot.trans.flush()" << endl;
-    indent_down();
-
-    // Try block for a function with exceptions
-    if (!tfunction->is_oneway() && xceptions.size() > 0) {
-      f_service_ << endl;
-      indent(f_service_) << "def write_results_exception_" << tfunction->get_name()
-                         << "(self, error, result, seqid, oprot):" << endl;
-      indent_up();
-      f_service_ << indent() << "try:" << endl;
-
-      // Kinda absurd
-      f_service_ << indent() << indent_str() << "error.raiseException()" << endl;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ <<
-          indent() << "except " << type_name((*x_iter)->get_type()) << " as " << (*x_iter)->get_name() << ":" << endl;
-        if (!tfunction->is_oneway()) {
-          indent_up();
-          f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
-                     << (*x_iter)->get_name() << endl;
-          indent_down();
-        } else {
-          f_service_ << indent() << "pass" << endl;
-        }
-      }
-      f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
-                 << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)"
-                 << endl << indent() << "oprot.writeMessageEnd()" << endl << indent()
-                 << "oprot.trans.flush()" << endl;
-      indent_down();
-    }
-
-  } else if (gen_tornado_) {
-    // TODO: Propagate arbitrary exception raised by handler to client as does plain "py"
-
-    // Generate the function call
-    t_struct* arg_struct = tfunction->get_arglist();
-    const std::vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    if (xceptions.size() > 0) {
-      f_service_ << indent() << "try:" << endl;
-      indent_up();
-    }
-    f_service_ << indent();
-    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-      f_service_ << "result.success = ";
-    }
-    f_service_ << "yield gen.maybe_future(self._handler." << tfunction->get_name() << "(";
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-    f_service_ << "))" << endl;
-
-    if (!tfunction->is_oneway() && xceptions.size() > 0) {
-      indent_down();
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as "
-                   << (*x_iter)->get_name() << ":" << endl;
-        if (!tfunction->is_oneway()) {
-          indent_up();
-          f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
-                     << (*x_iter)->get_name() << endl;
-          indent_down();
-        } else {
-          f_service_ << indent() << "pass" << endl;
-        }
-      }
-    }
-
-    if (!tfunction->is_oneway()) {
-      f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
-                 << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)"
-                 << endl << indent() << "oprot.writeMessageEnd()" << endl << indent()
-                 << "oprot.trans.flush()" << endl;
-    }
-
-    // Close function
-    indent_down();
-
-  } else { // py
-    // Try block for a function with exceptions
-    // It also catches arbitrary exceptions raised by handler method to propagate them to the client
-    f_service_ << indent() << "try:" << endl;
-    indent_up();
-
-    // Generate the function call
-    t_struct* arg_struct = tfunction->get_arglist();
-    const std::vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    f_service_ << indent();
-    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-      f_service_ << "result.success = ";
-    }
-    f_service_ << "self._handler." << tfunction->get_name() << "(";
-    bool first = true;
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_service_ << ", ";
-      }
-      f_service_ << "args." << (*f_iter)->get_name();
-    }
-    f_service_ << ")" << endl;
-    if (!tfunction->is_oneway()) {
-      f_service_  << indent() << "msg_type = TMessageType.REPLY" << endl;
-    }
-
-    indent_down();
-    f_service_ << indent()
-               << "except (TTransport.TTransportException, KeyboardInterrupt, SystemExit):" << endl
-               << indent() << indent_str() << "raise" << endl;
-
-    if (!tfunction->is_oneway()) {
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as "
-                   << (*x_iter)->get_name() << ":" << endl;
-        if (!tfunction->is_oneway()) {
-          indent_up();
-          f_service_ << indent() << "msg_type = TMessageType.REPLY" << endl;
-          f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
-                     << (*x_iter)->get_name() << endl;
-          indent_down();
-        } else {
-          f_service_ << indent() << "pass" << endl;
-        }
-      }
-
-      f_service_ << indent() << "except Exception as ex:" << endl
-                 << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl
-                 << indent() << indent_str() << "logging.exception(ex)" << endl
-                 << indent()
-                 << indent_str() << "result = TApplicationException(TApplicationException.INTERNAL_ERROR, "
-                    "'Internal error')" << endl
-                 << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
-                 << "\", msg_type, seqid)" << endl
-                 << indent() << "result.write(oprot)" << endl
-                 << indent() << "oprot.writeMessageEnd()" << endl
-                 << indent() << "oprot.trans.flush()" << endl;
-    } else {
-      f_service_ << indent() << "except:" << endl
-                 << indent() << indent_str() << "pass" << endl;
-    }
-
-    // Close function
-    indent_down();
-  }
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_py_generator::generate_deserialize_field(ofstream& out,
-                                                t_field* tfield,
-                                                string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  string name = prefix + tfield->get_name();
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-    indent(out) << name << " = iprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "readBinary()";
-        } else if(!gen_utf8strings_) {
-          out << "readString()";
-        } else {
-          out << "readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "readBool()";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "readByte()";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "readI16()";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "readI32()";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "readI64()";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "readDouble()";
-        break;
-      default:
-        throw "compiler error: no Python name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "readI32()";
-    }
-    out << endl;
-
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a struct, calling read()
- */
-void t_py_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  if (is_immutable(tstruct)) {
-    out << indent() << prefix << " = " << type_name(tstruct) << ".read(iprot)" << endl;
-  } else {
-    out << indent() << prefix << " = " << type_name(tstruct) << "()" << endl
-        << indent() << prefix << ".read(iprot)" << endl;
-  }
-}
-
-/**
- * Serialize a container by writing out the header followed by
- * data and then a footer.
- */
-void t_py_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
-  string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
-
-  t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    out << indent() << prefix << " = {}" << endl << indent() << "(" << ktype << ", " << vtype
-        << ", " << size << ") = iprot.readMapBegin()" << endl;
-  } else if (ttype->is_set()) {
-    out << indent() << prefix << " = set()" << endl << indent() << "(" << etype << ", " << size
-        << ") = iprot.readSetBegin()" << endl;
-  } else if (ttype->is_list()) {
-    out << indent() << prefix << " = []" << endl << indent() << "(" << etype << ", " << size
-        << ") = iprot.readListBegin()" << endl;
-  }
-
-  // For loop iterates over elements
-  string i = tmp("_i");
-  indent(out) <<
-    "for " << i << " in range(" << size << "):" << endl;
-
-  indent_up();
-
-  if (ttype->is_map()) {
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
-  } else if (ttype->is_set()) {
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
-  } else if (ttype->is_list()) {
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
-  }
-
-  indent_down();
-
-  // Read container end
-  if (ttype->is_map()) {
-    indent(out) << "iprot.readMapEnd()" << endl;
-    if (is_immutable(ttype)) {
-      indent(out) << prefix << " = TFrozenDict(" << prefix << ")" << endl;
-    }
-  } else if (ttype->is_set()) {
-    indent(out) << "iprot.readSetEnd()" << endl;
-    if (is_immutable(ttype)) {
-      indent(out) << prefix << " = frozenset(" << prefix << ")" << endl;
-    }
-  } else if (ttype->is_list()) {
-    if (is_immutable(ttype)) {
-      indent(out) << prefix << " = tuple(" << prefix << ")" << endl;
-    }
-    indent(out) << "iprot.readListEnd()" << endl;
-  }
-}
-
-/**
- * Generates code to deserialize a map
- */
-void t_py_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
-  string key = tmp("_key");
-  string val = tmp("_val");
-  t_field fkey(tmap->get_key_type(), key);
-  t_field fval(tmap->get_val_type(), val);
-
-  generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
-  indent(out) << prefix << "[" << key << "] = " << val << endl;
-}
-
-/**
- * Write a set element
- */
-void t_py_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tset->get_elem_type(), elem);
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".add(" << elem << ")" << endl;
-}
-
-/**
- * Write a list element
- */
-void t_py_generator::generate_deserialize_list_element(ofstream& out,
-                                                       t_list* tlist,
-                                                       string prefix) {
-  string elem = tmp("_elem");
-  t_field felem(tlist->get_elem_type(), elem);
-
-  generate_deserialize_field(out, &felem);
-
-  indent(out) << prefix << ".append(" << elem << ")" << endl;
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_py_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, prefix + tfield->get_name());
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    string name = prefix + tfield->get_name();
-
-    indent(out) << "oprot.";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        if (((t_base_type*)type)->is_binary()) {
-          out << "writeBinary(" << name << ")";
-        } else if (!gen_utf8strings_) {
-          out << "writeString(" << name << ")";
-        } else {
-          out << "writeString(" << name << ".encode('utf-8') if sys.version_info[0] == 2 else " << name << ")";
-        }
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ")";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ")";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ")";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ")";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ")";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ")";
-        break;
-      default:
-        throw "compiler error: no Python name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      out << "writeI32(" << name << ")";
-    }
-    out << endl;
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
-           prefix.c_str(),
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_py_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << prefix << ".write(oprot)" << endl;
-}
-
-void t_py_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  if (ttype->is_map()) {
-    indent(out) << "oprot.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
-                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
-                << "len(" << prefix << "))" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
-                << "len(" << prefix << "))" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
-                << ", "
-                << "len(" << prefix << "))" << endl;
-  }
-
-  if (ttype->is_map()) {
-    string kiter = tmp("kiter");
-    string viter = tmp("viter");
-    indent(out) << "for " << kiter << ", " << viter << " in " << prefix << ".items():" << endl;
-    indent_up();
-    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
-    indent_down();
-  } else if (ttype->is_set()) {
-    string iter = tmp("iter");
-    indent(out) << "for " << iter << " in " << prefix << ":" << endl;
-    indent_up();
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-    indent_down();
-  } else if (ttype->is_list()) {
-    string iter = tmp("iter");
-    indent(out) << "for " << iter << " in " << prefix << ":" << endl;
-    indent_up();
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-    indent_down();
-  }
-
-  if (ttype->is_map()) {
-    indent(out) << "oprot.writeMapEnd()" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot.writeSetEnd()" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot.writeListEnd()" << endl;
-  }
-}
-
-/**
- * Serializes the members of a map.
- *
- */
-void t_py_generator::generate_serialize_map_element(ofstream& out,
-                                                    t_map* tmap,
-                                                    string kiter,
-                                                    string viter) {
-  t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(out, &kfield, "");
-
-  t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(out, &vfield, "");
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_py_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_py_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield, "");
-}
-
-/**
- * Generates the docstring for a given struct.
- */
-void t_py_generator::generate_python_docstring(ofstream& out, t_struct* tstruct) {
-  generate_python_docstring(out, tstruct, tstruct, "Attributes");
-}
-
-/**
- * Generates the docstring for a given function.
- */
-void t_py_generator::generate_python_docstring(ofstream& out, t_function* tfunction) {
-  generate_python_docstring(out, tfunction, tfunction->get_arglist(), "Parameters");
-}
-
-/**
- * Generates the docstring for a struct or function.
- */
-void t_py_generator::generate_python_docstring(ofstream& out,
-                                               t_doc* tdoc,
-                                               t_struct* tstruct,
-                                               const char* subheader) {
-  bool has_doc = false;
-  stringstream ss;
-  if (tdoc->has_doc()) {
-    has_doc = true;
-    ss << tdoc->get_doc();
-  }
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  if (fields.size() > 0) {
-    if (has_doc) {
-      ss << endl;
-    }
-    has_doc = true;
-    ss << subheader << ":\n";
-    vector<t_field*>::const_iterator p_iter;
-    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
-      t_field* p = *p_iter;
-      ss << " - " << p->get_name();
-      if (p->has_doc()) {
-        ss << ": " << p->get_doc();
-      } else {
-        ss << endl;
-      }
-    }
-  }
-
-  if (has_doc) {
-    generate_docstring_comment(out, "\"\"\"\n", "", ss.str(), "\"\"\"\n");
-  }
-}
-
-/**
- * Generates the docstring for a generic object.
- */
-void t_py_generator::generate_python_docstring(ofstream& out, t_doc* tdoc) {
-  if (tdoc->has_doc()) {
-    generate_docstring_comment(out, "\"\"\"\n", "", tdoc->get_doc(), "\"\"\"\n");
-  }
-}
-
-/**
- * Declares an argument, which may include initialization as necessary.
- *
- * @param tfield The field
- */
-string t_py_generator::declare_argument(t_field* tfield) {
-  std::ostringstream result;
-  result << tfield->get_name() << "=";
-  if (tfield->get_value() != NULL) {
-    result << "thrift_spec[" << tfield->get_key() << "][4]";
-  } else {
-    result << "None";
-  }
-  return result.str();
-}
-
-/**
- * Renders a field default value, returns None otherwise.
- *
- * @param tfield The field
- */
-string t_py_generator::render_field_default_value(t_field* tfield) {
-  t_type* type = get_true_type(tfield->get_type());
-  if (tfield->get_value() != NULL) {
-    return render_const_value(type, tfield->get_value());
-  } else {
-    return "None";
-  }
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_py_generator::function_signature(t_function* tfunction, bool interface) {
-  vector<string> pre;
-  vector<string> post;
-  string signature = tfunction->get_name() + "(";
-
-  if (!(gen_twisted_ && interface)) {
-    pre.push_back("self");
-  }
-
-  signature += argument_list(tfunction->get_arglist(), &pre, &post) + ")";
-  return signature;
-}
-
-/**
- * Renders a field list
- */
-string t_py_

<TRUNCATED>

[41/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_go_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_go_generator.cc b/compiler/cpp/src/generate/t_go_generator.cc
deleted file mode 100644
index b9429c1..0000000
--- a/compiler/cpp/src/generate/t_go_generator.cc
+++ /dev/null
@@ -1,3685 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-/*
- * This file is programmatically sanitized for style:
- * astyle --style=1tbs -f -p -H -j -U t_go_generator.cc
- *
- * The output of astyle should not be taken unquestioningly, but it is a good
- * guide for ensuring uniformity and readability.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-#include <algorithm>
-#include <clocale>
-#include "t_generator.h"
-#include "platform.h"
-#include "version.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * A helper for automatically formatting the emitted Go code from the Thrift
- * IDL per the Go style guide.
- *
- * Returns:
- *  - true, if the formatting process succeeded.
- *  - false, if the formatting process failed, which means the basic output was
- *           still generated.
- */
-bool format_go_output(const string& file_path);
-
-const string DEFAULT_THRIFT_IMPORT = "git.apache.org/thrift.git/lib/go/thrift";
-static std::string package_flag;
-
-/**
- * Go code generator.
- */
-class t_go_generator : public t_generator {
-public:
-  t_go_generator(t_program* program,
-                 const std::map<std::string, std::string>& parsed_options,
-                 const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-
-    gen_thrift_import_ = DEFAULT_THRIFT_IMPORT;
-    gen_package_prefix_ = "";
-    package_flag = "";
-    read_write_private_ = false;
-    ignore_initialisms_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("package_prefix") == 0) {
-        gen_package_prefix_ = (iter->second);
-      } else if( iter->first.compare("thrift_import") == 0) {
-        gen_thrift_import_ = (iter->second);
-      } else if( iter->first.compare("package") == 0) {
-        package_flag = (iter->second);
-      } else if( iter->first.compare("read_write_private") == 0) {
-        read_write_private_ = true;
-      } else if( iter->first.compare("ignore_initialisms") == 0) {
-        ignore_initialisms_ =  true;
-      } else {
-        throw "unknown option go:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-go";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_const_value(t_type* type, t_const_value* value, const string& name);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_go_struct(t_struct* tstruct, bool is_exception);
-  void generate_go_struct_definition(std::ofstream& out,
-                                     t_struct* tstruct,
-                                     bool is_xception = false,
-                                     bool is_result = false,
-                                     bool is_args = false);
-  void generate_go_struct_initializer(std::ofstream& out,
-                                      t_struct* tstruct,
-                                      bool is_args_or_result = false);
-  void generate_isset_helpers(std::ofstream& out,
-                              t_struct* tstruct,
-                              const string& tstruct_name,
-                              bool is_result = false);
-  void generate_countsetfields_helper(std::ofstream& out,
-                                      t_struct* tstruct,
-                                      const string& tstruct_name,
-                                      bool is_result = false);
-  void generate_go_struct_reader(std::ofstream& out,
-                                 t_struct* tstruct,
-                                 const string& tstruct_name,
-                                 bool is_result = false);
-  void generate_go_struct_writer(std::ofstream& out,
-                                 t_struct* tstruct,
-                                 const string& tstruct_name,
-                                 bool is_result = false,
-                                 bool uses_countsetfields = false);
-  void generate_go_function_helpers(t_function* tfunction);
-  void get_publicized_name_and_def_value(t_field* tfield,
-                                         string* OUT_pub_name,
-                                         t_const_value** OUT_def_value) const;
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_remote(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  bool declare,
-                                  std::string prefix = "",
-                                  bool inclass = false,
-                                  bool coerceData = false,
-                                  bool inkey = false,
-                                  bool in_container = false,
-                                  bool use_true_type = false);
-
-  void generate_deserialize_struct(std::ofstream& out,
-                                   t_struct* tstruct,
-                                   bool is_pointer_field,
-                                   bool declare,
-                                   std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out,
-                                      t_type* ttype,
-                                      bool pointer_field,
-                                      bool declare,
-                                      std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out,
-                                        t_set* tset,
-                                        bool declare,
-                                        std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out,
-                                        t_map* tmap,
-                                        bool declare,
-                                        std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         bool declare,
-                                         std::string prefix = "");
-
-  void generate_serialize_field(std::ofstream& out,
-                                t_field* tfield,
-                                std::string prefix = "",
-                                bool inkey = false);
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out,
-                                    t_type* ttype,
-                                    bool pointer_field,
-                                    std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_go_docstring(std::ofstream& out, t_struct* tstruct);
-
-  void generate_go_docstring(std::ofstream& out, t_function* tfunction);
-
-  void generate_go_docstring(std::ofstream& out,
-                             t_doc* tdoc,
-                             t_struct* tstruct,
-                             const char* subheader);
-
-  void generate_go_docstring(std::ofstream& out, t_doc* tdoc);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string go_autogen_comment();
-  std::string go_package();
-  std::string go_imports_begin(bool consts);
-  std::string go_imports_end();
-  std::string render_includes(bool consts);
-  std::string render_included_programs(string& unused_protection);
-  std::string render_import_protection();
-  std::string render_fastbinary_includes();
-  std::string declare_argument(t_field* tfield);
-  std::string render_field_initial_value(t_field* tfield, const string& name, bool optional_field);
-  std::string type_name(t_type* ttype);
-  std::string module_name(t_type* ttype);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string function_signature_if(t_function* tfunction,
-                                    std::string prefix = "",
-                                    bool addError = false);
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string type_to_go_type(t_type* ttype);
-  std::string type_to_go_type_with_opt(t_type* ttype,
-                                       bool optional_field);
-  std::string type_to_go_key_type(t_type* ttype);
-  std::string type_to_spec_args(t_type* ttype);
-
-  static std::string get_real_go_module(const t_program* program) {
-
-    if (!package_flag.empty()) {
-      return package_flag;
-    }
-    std::string real_module = program->get_namespace("go");
-    if (!real_module.empty()) {
-      return real_module;
-    }
-
-    return lowercase(program->get_name());
-  }
-
-private:
-  std::string gen_package_prefix_;
-  std::string gen_thrift_import_;
-  bool read_write_private_;
-  bool ignore_initialisms_;
-
-  /**
-   * File streams
-   */
-
-  std::ofstream f_types_;
-  std::string f_types_name_;
-  std::ofstream f_consts_;
-  std::string f_consts_name_;
-  std::stringstream f_const_values_;
-
-  std::string package_name_;
-  std::string package_dir_;
-  std::string read_method_name_;
-  std::string write_method_name_;
-
-  std::set<std::string> commonInitialisms;
-
-  std::string camelcase(const std::string& value) const;
-  void fix_common_initialism(std::string& value, int i) const;
-  std::string publicize(const std::string& value, bool is_args_or_result = false) const;
-  std::string privatize(const std::string& value) const;
-  std::string new_prefix(const std::string& value) const;
-  static std::string variable_name_to_go_name(const std::string& value);
-  static bool is_pointer_field(t_field* tfield, bool in_container = false);
-  static bool omit_initialization(t_field* tfield);
-};
-
-// returns true if field initialization can be omitted since it has corresponding go type zero value
-// or default value is not set
-bool t_go_generator::omit_initialization(t_field* tfield) {
-  t_const_value* value = tfield->get_value();
-  if (!value) {
-    return true;
-  }
-  t_type* type = tfield->get_type()->get_true_type();
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "";
-
-    case t_base_type::TYPE_STRING:
-      if (((t_base_type*)type)->is_binary()) {
-        //[]byte are always inline
-        return false;
-      }
-      // strings are pointers if has no default
-      return value->get_string().empty();
-
-    case t_base_type::TYPE_BOOL:
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      return value->get_integer() == 0;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        return value->get_integer() == 0;
-      } else {
-        return value->get_double() == 0.;
-      }
-    }
-  }
-  return false;
-}
-
-// Returns true if the type need a reference if used as optional without default
-static bool type_need_reference(t_type* type) {
-  type = type->get_true_type();
-  if (type->is_map() || type->is_set() || type->is_list() || type->is_struct()
-      || type->is_xception() || (type->is_string() && ((t_base_type*)type)->is_binary())) {
-    return false;
-  }
-  return true;
-}
-
-// returns false if field could not use comparison to default value as !IsSet*
-bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value) {
-  (void)in_container_value;
-  if (tfield->annotations_.count("cpp.ref") != 0) {
-    return true;
-  }
-  t_type* type = tfield->get_type()->get_true_type();
-  // Structs in containers are pointers
-  if (type->is_struct() || type->is_xception()) {
-    return true;
-  }
-  if (!(tfield->get_req() == t_field::T_OPTIONAL)) {
-    return false;
-  }
-
-  bool has_default = tfield->get_value();
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "";
-
-    case t_base_type::TYPE_STRING:
-      if (((t_base_type*)type)->is_binary()) {
-        //[]byte are always inline
-        return false;
-      }
-      // strings are pointers if has no default
-      return !has_default;
-
-    case t_base_type::TYPE_BOOL:
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-    case t_base_type::TYPE_DOUBLE:
-      return !has_default;
-    }
-  } else if (type->is_enum()) {
-    return !has_default;
-  } else if (type->is_struct() || type->is_xception()) {
-    return true;
-  } else if (type->is_map()) {
-    return has_default;
-  } else if (type->is_set()) {
-    return has_default;
-  } else if (type->is_list()) {
-    return has_default;
-  } else if (type->is_typedef()) {
-    return has_default;
-  }
-
-  throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
-}
-
-std::string t_go_generator::camelcase(const std::string& value) const {
-  std::string value2(value);
-  std::setlocale(LC_ALL, "C"); // set locale to classic
-
-  // Fix common initialism in first word
-  fix_common_initialism(value2, 0);
-
-  // as long as we are changing things, let's change _ followed by lowercase to
-  // capital and fix common initialisms
-  for (std::string::size_type i = 1; i < value2.size() - 1; ++i) {
-    if (value2[i] == '_') {
-      if (islower(value2[i + 1])) {
-        value2.replace(i, 2, 1, toupper(value2[i + 1]));
-      }
-      fix_common_initialism(value2, i);
-    }
-  }
-
-  return value2;
-}
-
-// Checks to see if the word starting at i in value contains a common initialism
-// and if so replaces it with the upper case version of the word.
-void t_go_generator::fix_common_initialism(std::string& value, int i) const {
-  if (!ignore_initialisms_) {
-    size_t wordLen = value.find('_', i);
-    if (wordLen != std::string::npos) {
-      wordLen -= i;
-    }
-    std::string word = value.substr(i, wordLen);
-    std::transform(word.begin(), word.end(), word.begin(), ::toupper);
-    if (commonInitialisms.find(word) != commonInitialisms.end()) {
-      value.replace(i, word.length(), word);
-    }
-  }
-}
-
-std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result) const {
-  if (value.size() <= 0) {
-    return value;
-  }
-
-  std::string value2(value), prefix;
-
-  string::size_type dot_pos = value.rfind('.');
-  if (dot_pos != string::npos) {
-    prefix = value.substr(0, dot_pos + 1) + prefix;
-    value2 = value.substr(dot_pos + 1);
-  }
-
-  if (!isupper(value2[0])) {
-    value2[0] = toupper(value2[0]);
-  }
-
-  value2 = camelcase(value2);
-
-  // final length before further checks, the string may become longer
-  size_t len_before = value2.length();
-
-  // IDL identifiers may start with "New" which interferes with the CTOR pattern
-  // Adding an extra underscore to all those identifiers solves this
-  if ((len_before >= 3) && (value2.substr(0, 3) == "New")) {
-    value2 += '_';
-  }
-
-  // IDL identifiers may end with "Args"/"Result" which interferes with the implicit service
-  // function structs
-  // Adding another extra underscore to all those identifiers solves this
-  // Suppress this check for the actual helper struct names
-  if (!is_args_or_result) {
-    bool ends_with_args = (len_before >= 4) && (value2.substr(len_before - 4, 4) == "Args");
-    bool ends_with_rslt = (len_before >= 6) && (value2.substr(len_before - 6, 6) == "Result");
-    if (ends_with_args || ends_with_rslt) {
-      value2 += '_';
-    }
-  }
-
-  // Avoid naming collisions with other services
-  if (is_args_or_result) {
-    prefix += publicize(service_name_);
-  }
-
-  return prefix + value2;
-}
-
-std::string t_go_generator::new_prefix(const std::string& value) const {
-  if (value.size() <= 0) {
-    return value;
-  }
-
-  string::size_type dot_pos = value.rfind('.');
-  if (dot_pos != string::npos) {
-    return value.substr(0, dot_pos + 1) + "New" + publicize(value.substr(dot_pos + 1));
-  }
-  return "New" + publicize(value);
-}
-
-std::string t_go_generator::privatize(const std::string& value) const {
-  if (value.size() <= 0) {
-    return value;
-  }
-
-  std::string value2(value);
-
-  if (!islower(value2[0])) {
-    value2[0] = tolower(value2[0]);
-  }
-
-  value2 = camelcase(value2);
-
-  return value2;
-}
-
-std::string t_go_generator::variable_name_to_go_name(const std::string& value) {
-  if (value.size() <= 0) {
-    return value;
-  }
-
-  std::string value2(value);
-  std::transform(value2.begin(), value2.end(), value2.begin(), ::tolower);
-
-  switch (value[0]) {
-  case 'b':
-  case 'B':
-    if (value2 != "break") {
-      return value;
-    }
-
-    break;
-
-  case 'c':
-  case 'C':
-    if (value2 != "case" && value2 != "chan" && value2 != "const" && value2 != "continue") {
-      return value;
-    }
-
-    break;
-
-  case 'd':
-  case 'D':
-    if (value2 != "default" && value2 != "defer") {
-      return value;
-    }
-
-    break;
-
-  case 'e':
-  case 'E':
-    if (value2 != "else" && value2 != "error") {
-      return value;
-    }
-
-    break;
-
-  case 'f':
-  case 'F':
-    if (value2 != "fallthrough" && value2 != "for" && value2 != "func") {
-      return value;
-    }
-
-    break;
-
-  case 'g':
-  case 'G':
-    if (value2 != "go" && value2 != "goto") {
-      return value;
-    }
-
-    break;
-
-  case 'i':
-  case 'I':
-    if (value2 != "if" && value2 != "import" && value2 != "interface") {
-      return value;
-    }
-
-    break;
-
-  case 'm':
-  case 'M':
-    if (value2 != "map") {
-      return value;
-    }
-
-    break;
-
-  case 'p':
-  case 'P':
-    if (value2 != "package") {
-      return value;
-    }
-
-    break;
-
-  case 'r':
-  case 'R':
-    if (value2 != "range" && value2 != "return") {
-      return value;
-    }
-
-    break;
-
-  case 's':
-  case 'S':
-    if (value2 != "select" && value2 != "struct" && value2 != "switch") {
-      return value;
-    }
-
-    break;
-
-  case 't':
-  case 'T':
-    if (value2 != "type") {
-      return value;
-    }
-
-    break;
-
-  case 'v':
-  case 'V':
-    if (value2 != "var") {
-      return value;
-    }
-
-    break;
-
-  default:
-    return value;
-  }
-
-  return value2 + "_a1";
-}
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_go_generator::init_generator() {
-  // Make output directory
-  string module = get_real_go_module(program_);
-  string target = module;
-  package_dir_ = get_out_dir();
-
-  // This set is taken from https://github.com/golang/lint/blob/master/lint.go#L692
-  commonInitialisms.insert("API");
-  commonInitialisms.insert("ASCII");
-  commonInitialisms.insert("CPU");
-  commonInitialisms.insert("CSS");
-  commonInitialisms.insert("DNS");
-  commonInitialisms.insert("EOF");
-  commonInitialisms.insert("GUID");
-  commonInitialisms.insert("HTML");
-  commonInitialisms.insert("HTTP");
-  commonInitialisms.insert("HTTPS");
-  commonInitialisms.insert("ID");
-  commonInitialisms.insert("IP");
-  commonInitialisms.insert("JSON");
-  commonInitialisms.insert("LHS");
-  commonInitialisms.insert("QPS");
-  commonInitialisms.insert("RAM");
-  commonInitialisms.insert("RHS");
-  commonInitialisms.insert("RPC");
-  commonInitialisms.insert("SLA");
-  commonInitialisms.insert("SMTP");
-  commonInitialisms.insert("SSH");
-  commonInitialisms.insert("TCP");
-  commonInitialisms.insert("TLS");
-  commonInitialisms.insert("TTL");
-  commonInitialisms.insert("UDP");
-  commonInitialisms.insert("UI");
-  commonInitialisms.insert("UID");
-  commonInitialisms.insert("UUID");
-  commonInitialisms.insert("URI");
-  commonInitialisms.insert("URL");
-  commonInitialisms.insert("UTF8");
-  commonInitialisms.insert("VM");
-  commonInitialisms.insert("XML");
-  commonInitialisms.insert("XSRF");
-  commonInitialisms.insert("XSS");
-
-  // names of read and write methods
-  if (read_write_private_) {
-    read_method_name_ = "read";
-    write_method_name_ = "write";
-  } else {
-    read_method_name_ = "Read";
-    write_method_name_ = "Write";
-  }
-
-  while (true) {
-    // TODO: Do better error checking here.
-    MKDIR(package_dir_.c_str());
-
-    if (module.empty()) {
-      break;
-    }
-
-    string::size_type pos = module.find('.');
-
-    if (pos == string::npos) {
-      package_dir_ += "/";
-      package_dir_ += module;
-      package_name_ = module;
-      module.clear();
-    } else {
-      package_dir_ += "/";
-      package_dir_ += module.substr(0, pos);
-      module.erase(0, pos + 1);
-    }
-  }
-
-  string::size_type loc;
-
-  while ((loc = target.find(".")) != string::npos) {
-    target.replace(loc, 1, 1, '/');
-  }
-
-  // Make output files
-  f_types_name_ = package_dir_ + "/" + program_name_ + ".go";
-  f_types_.open(f_types_name_.c_str());
-
-  f_consts_name_ = package_dir_ + "/" + program_name_ + "-consts.go";
-  f_consts_.open(f_consts_name_.c_str());
-
-  vector<t_service*> services = program_->get_services();
-  vector<t_service*>::iterator sv_iter;
-
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    string service_dir = package_dir_ + "/" + underscore((*sv_iter)->get_name()) + "-remote";
-    MKDIR(service_dir.c_str());
-  }
-
-  // Print header
-  f_types_ << go_autogen_comment() << go_package() << render_includes(false);
-
-  f_consts_ << go_autogen_comment() << go_package() << render_includes(true);
-
-  f_const_values_ << endl << "func init() {" << endl;
-
-  // Create file for the GoUnusedProtection__ variable
-  string f_unused_prot_name_ = package_dir_ + "/" + "GoUnusedProtection__.go";
-  ofstream f_unused_prot_;
-  f_unused_prot_.open(f_unused_prot_name_.c_str());
-  f_unused_prot_ << go_autogen_comment() << go_package() << render_import_protection();
-  f_unused_prot_.close();
-}
-
-
-string t_go_generator::render_included_programs(string& unused_protection) {
-  const vector<t_program*>& includes = program_->get_includes();
-  string result = "";
-
-  unused_protection = "";
-
-  string local_namespace = program_->get_namespace("go");
-  for (size_t i = 0; i < includes.size(); ++i) {
-    if (!local_namespace.empty() && local_namespace == includes[i]->get_namespace("go")) {
-      continue;
-    }
-
-    string go_module = get_real_go_module(includes[i]);
-    size_t found = 0;
-    for (size_t j = 0; j < go_module.size(); j++) {
-      // Import statement uses slashes ('/') in namespace
-      if (go_module[j] == '.') {
-        go_module[j] = '/';
-        found = j + 1;
-      }
-    }
-
-    result += "\t\"" + gen_package_prefix_ + go_module + "\"\n";
-    unused_protection += "var _ = " + go_module.substr(found) + ".GoUnusedProtection__\n";
-  }
-
-  return result;
-}
-
-/**
- * Renders all the imports necessary for including another Thrift program.
- * If consts include the additional imports.
- */
-string t_go_generator::render_includes(bool consts) {
-  const vector<t_program*>& includes = program_->get_includes();
-  string result = "";
-  string unused_prot = "";
-
-  string local_namespace = program_->get_namespace("go");
-  for (size_t i = 0; i < includes.size(); ++i) {
-    if (!local_namespace.empty() && local_namespace == includes[i]->get_namespace("go")) {
-      continue;
-    }
-
-    string go_module = get_real_go_module(includes[i]);
-    size_t found = 0;
-    for (size_t j = 0; j < go_module.size(); j++) {
-      // Import statement uses slashes ('/') in namespace
-      if (go_module[j] == '.') {
-        go_module[j] = '/';
-        found = j + 1;
-      }
-    }
-
-    result += "\t\"" + gen_package_prefix_ + go_module + "\"\n";
-    unused_prot += "var _ = " + go_module.substr(found) + ".GoUnusedProtection__\n";
-  }
-
-  if (includes.size() > 0) {
-    result += "\n";
-  }
-
-  return go_imports_begin(consts) + result + go_imports_end() + unused_prot;
-}
-
-string t_go_generator::render_import_protection() {
-  return string("var GoUnusedProtection__ int;\n\n");
-}
-
-/**
- * Renders all the imports necessary to use the accelerated TBinaryProtocol
- */
-string t_go_generator::render_fastbinary_includes() {
-  return "";
-}
-
-/**
- * Autogen'd comment
- */
-string t_go_generator::go_autogen_comment() {
-  return
-        std::string() +
-        "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
-        "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\n";
-}
-
-/**
- * Prints standard thrift package
- */
-string t_go_generator::go_package() {
-  return string("package ") + package_name_ + "\n\n";
-}
-
-/**
- * Render the beginning of the import statement.
- * If consts include the additional imports.
- */
-string t_go_generator::go_imports_begin(bool consts) {
-  string extra;
-  // If not writing constants, and there are enums, need extra imports.
-  if (!consts && get_program()->get_enums().size() > 0) {
-    extra =
-      "\t\"database/sql/driver\"\n"
-      "\t\"errors\"\n";
-  }
-  return string(
-      "import (\n"
-      "\t\"bytes\"\n"
-      + extra +
-      "\t\"fmt\"\n"
-      "\t\"" + gen_thrift_import_ + "\"\n");
-}
-
-/**
- * End the import statement, include undscore-assignments
- *
- * These "_ =" prevent the go compiler complaining about used imports.
- * This will have to do in lieu of more intelligent import statement construction
- */
-string t_go_generator::go_imports_end() {
-  return string(
-      ")\n\n"
-      "// (needed to ensure safety because of naive import list construction.)\n"
-      "var _ = thrift.ZERO\n"
-      "var _ = fmt.Printf\n"
-      "var _ = bytes.Equal\n\n");
-}
-
-/**
- * Closes the type files
- */
-void t_go_generator::close_generator() {
-  f_const_values_ << "}" << endl << endl;
-  f_consts_ << f_const_values_.str();
-
-  // Close types and constants files
-  f_consts_.close();
-  f_types_.close();
-  format_go_output(f_types_name_);
-  format_go_output(f_consts_name_);
-}
-
-/**
- * Generates a typedef.
- *
- * @param ttypedef The type definition
- */
-void t_go_generator::generate_typedef(t_typedef* ttypedef) {
-  generate_go_docstring(f_types_, ttypedef);
-  string new_type_name(publicize(ttypedef->get_symbolic()));
-  string base_type(type_to_go_type(ttypedef->get_type()));
-
-  if (base_type == new_type_name) {
-    return;
-  }
-
-  f_types_ << "type " << new_type_name << " " << base_type << endl << endl;
-  // Generate a convenience function that converts an instance of a type
-  // (which may be a constant) into a pointer to an instance of a type.
-  f_types_ << "func " << new_type_name << "Ptr(v " << new_type_name << ") *" << new_type_name
-           << " { return &v }" << endl << endl;
-}
-
-/**
- * Generates code for an enumerated type. Done using a class to scope
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_go_generator::generate_enum(t_enum* tenum) {
-  std::ostringstream to_string_mapping, from_string_mapping;
-  std::string tenum_name(publicize(tenum->get_name()));
-  generate_go_docstring(f_types_, tenum);
-  f_types_ << "type " << tenum_name << " int64" << endl << "const (" << endl;
-
-  to_string_mapping << indent() << "func (p " << tenum_name << ") String() string {" << endl;
-  to_string_mapping << indent() << "  switch p {" << endl;
-
-  from_string_mapping << indent() << "func " << tenum_name << "FromString(s string) (" << tenum_name
-                      << ", error) {" << endl;
-  from_string_mapping << indent() << "  switch s {" << endl;
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  int value = -1;
-
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    value = (*c_iter)->get_value();
-
-    string iter_std_name(escape_string((*c_iter)->get_name()));
-    string iter_name((*c_iter)->get_name());
-    f_types_ << indent() << "  " << tenum_name << "_" << iter_name << ' ' << tenum_name << " = "
-             << value << endl;
-    // Dictionaries to/from string names of enums
-    to_string_mapping << indent() << "  case " << tenum_name << "_" << iter_name << ": return \""
-                      << iter_std_name << "\"" << endl;
-
-    if (iter_std_name != escape_string(iter_name)) {
-      from_string_mapping << indent() << "  case \"" << iter_std_name << "\", \""
-                          << escape_string(iter_name) << "\": return " << tenum_name << "_"
-                          << iter_name << ", nil " << endl;
-    } else {
-      from_string_mapping << indent() << "  case \"" << iter_std_name << "\": return " << tenum_name
-                          << "_" << iter_name << ", nil " << endl;
-    }
-  }
-
-  to_string_mapping << indent() << "  }" << endl;
-  to_string_mapping << indent() << "  return \"<UNSET>\"" << endl;
-  to_string_mapping << indent() << "}" << endl;
-  from_string_mapping << indent() << "  }" << endl;
-  from_string_mapping << indent() << "  return " << tenum_name << "(0),"
-                      << " fmt.Errorf(\"not a valid " << tenum_name << " string\")" << endl;
-  from_string_mapping << indent() << "}" << endl;
-
-  f_types_ << ")" << endl << endl << to_string_mapping.str() << endl << from_string_mapping.str()
-           << endl << endl;
-
-  // Generate a convenience function that converts an instance of an enum
-  // (which may be a constant) into a pointer to an instance of that enum
-  // type.
-  f_types_ << "func " << tenum_name << "Ptr(v " << tenum_name << ") *" << tenum_name
-           << " { return &v }" << endl << endl;
-
-  // Generate MarshalText
-  f_types_ << "func (p " << tenum_name << ") MarshalText() ([]byte, error) {" << endl;
-  f_types_ << "return []byte(p.String()), nil" << endl;
-  f_types_ << "}" << endl << endl;
-
-  // Generate UnmarshalText
-  f_types_ << "func (p *" << tenum_name << ") UnmarshalText(text []byte) error {" << endl;
-  f_types_ << "q, err := " << tenum_name << "FromString(string(text))" << endl;
-  f_types_ << "if (err != nil) {" << endl << "return err" << endl << "}" << endl;
-  f_types_ << "*p = q" << endl;
-  f_types_ << "return nil" << endl;
-  f_types_ << "}" << endl << endl;
-
-  // Generate Scan for sql.Scanner interface
-  f_types_ << "func (p *" << tenum_name << ") Scan(value interface{}) error {" <<endl;
-  f_types_ << "v, ok := value.(int64)" <<endl;
-  f_types_ << "if !ok {" <<endl;
-  f_types_ << "return errors.New(\"Scan value is not int64\")" <<endl;
-  f_types_ << "}" <<endl;
-  f_types_ << "*p = " << tenum_name << "(v)" << endl;
-  f_types_ << "return nil" << endl;
-  f_types_ << "}" << endl << endl;
-
-  // Generate Value for driver.Valuer interface
-  f_types_ << "func (p * " << tenum_name << ") Value() (driver.Value, error) {" <<endl;
-  f_types_ << "  if p == nil {" << endl;
-  f_types_ << "    return nil, nil" << endl;
-  f_types_ << "  }" << endl;
-  f_types_ << "return int64(*p), nil" << endl;
-  f_types_ << "}" << endl;
-
-}
-
-/**
- * Generate a constant value
- */
-void t_go_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = publicize(tconst->get_name());
-  t_const_value* value = tconst->get_value();
-
-  if (type->is_base_type() || type->is_enum()) {
-    indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl;
-  } else {
-    f_const_values_ << indent() << name << " = " << render_const_value(type, value, name) << endl
-                    << endl;
-
-    f_consts_ << indent() << "var " << name << " " << type_to_go_type(type) << endl;
-  }
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name) {
-  type = get_true_type(type);
-  std::ostringstream out;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      if (((t_base_type*)type)->is_binary()) {
-        out << "[]byte(\"" << get_escaped_string(value) << "\")";
-      } else {
-        out << '"' << get_escaped_string(value) << '"';
-      }
-
-      break;
-
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
-
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
-      }
-
-      break;
-
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    indent(out) << value->get_integer();
-  } else if (type->is_struct() || type->is_xception()) {
-    out << "&" << publicize(type_name(type)) << "{";
-    indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-
-      out << endl << indent() << publicize(v_iter->first->get_string()) << ": "
-          << render_const_value(field_type, v_iter->second, name) << "," << endl;
-    }
-
-    indent_down();
-    out << "}";
-
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    out << "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl;
-    indent_up();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent() << render_const_value(ktype, v_iter->first, name) << ": "
-          << render_const_value(vtype, v_iter->second, name) << "," << endl;
-    }
-
-    indent_down();
-    out << indent() << "}";
-  } else if (type->is_list()) {
-    t_type* etype = ((t_list*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    out << "[]" << type_to_go_type(etype) << "{" << endl;
-    indent_up();
-    vector<t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent() << render_const_value(etype, *v_iter, name) << ", ";
-    }
-
-    indent_down();
-    out << indent() << "}";
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    out << "map[" << type_to_go_key_type(etype) << "]struct{}{" << endl;
-    indent_up();
-    vector<t_const_value*>::const_iterator v_iter;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent() << render_const_value(etype, *v_iter, name) << ": struct{}{}," << endl;
-    }
-
-    indent_down();
-    out << indent() << "}";
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-
-  return out.str();
-}
-
-/**
- * Generates a go struct
- */
-void t_go_generator::generate_struct(t_struct* tstruct) {
-  generate_go_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct but extends the Exception class.
- *
- * @param txception The struct definition
- */
-void t_go_generator::generate_xception(t_struct* txception) {
-  generate_go_struct(txception, true);
-}
-
-/**
- * Generates a go struct
- */
-void t_go_generator::generate_go_struct(t_struct* tstruct, bool is_exception) {
-  generate_go_struct_definition(f_types_, tstruct, is_exception);
-}
-
-void t_go_generator::get_publicized_name_and_def_value(t_field* tfield,
-                                                       string* OUT_pub_name,
-                                                       t_const_value** OUT_def_value) const {
-  const string base_field_name = tfield->get_name();
-  const string escaped_field_name = escape_string(base_field_name);
-  *OUT_pub_name = publicize(escaped_field_name);
-  *OUT_def_value = tfield->get_value();
-}
-
-void t_go_generator::generate_go_struct_initializer(ofstream& out,
-                                                    t_struct* tstruct,
-                                                    bool is_args_or_result) {
-  out << publicize(type_name(tstruct), is_args_or_result) << "{";
-  const vector<t_field*>& members = tstruct->get_members();
-  for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
-       ++m_iter) {
-    bool pointer_field = is_pointer_field(*m_iter);
-    string publicized_name;
-    t_const_value* def_value;
-    get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
-    if (!pointer_field && def_value != NULL && !omit_initialization(*m_iter)) {
-      out << endl << indent() << publicized_name << ": "
-          << render_field_initial_value(*m_iter, (*m_iter)->get_name(), pointer_field) << ","
-          << endl;
-    }
-  }
-
-  out << "}" << endl;
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_go_generator::generate_go_struct_definition(ofstream& out,
-                                                   t_struct* tstruct,
-                                                   bool is_exception,
-                                                   bool is_result,
-                                                   bool is_args) {
-  const vector<t_field*>& members = tstruct->get_members();
-  const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  std::string tstruct_name(publicize(tstruct->get_name(), is_args || is_result));
-  generate_go_docstring(out, tstruct);
-  out << indent() << "type " << tstruct_name << " struct {" << endl;
-  /*
-     Here we generate the structure specification for the fastbinary codec.
-     These specifications have the following structure:
-     thrift_spec -> tuple of item_spec
-     item_spec -> nil | (tag, type_enum, name, spec_args, default)
-     tag -> integer
-     type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ...
-     name -> string_literal
-     default -> nil  # Handled by __init__
-     spec_args -> nil  # For simple types
-                | (type_enum, spec_args)  # Value type for list/set
-                | (type_enum, spec_args, type_enum, spec_args)
-                  # Key and value for map
-                | (class_name, spec_args_ptr) # For struct/exception
-     class_name -> identifier  # Basically a pointer to the class
-     spec_args_ptr -> expression  # just class_name.spec_args
-
-     TODO(dreiss): Consider making this work for structs with negative tags.
-  */
-  // TODO(dreiss): Look into generating an empty tuple instead of nil
-  // for structures with no members.
-  // TODO(dreiss): Test encoding of structs where some inner structs
-  // don't have thrift_spec.
-  indent_up();
-
-  int num_setable = 0;
-  if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) {
-    int sorted_keys_pos = 0;
-
-    for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
-      // Set field to optional if field is union, this is so we can get a
-      // pointer to the field.
-      if (tstruct->is_union())
-        (*m_iter)->set_req(t_field::T_OPTIONAL);
-      if (sorted_keys_pos != (*m_iter)->get_key()) {
-        int first_unused = std::max(1, sorted_keys_pos++);
-        while (sorted_keys_pos != (*m_iter)->get_key()) {
-          ++sorted_keys_pos;
-        }
-        int last_unused = sorted_keys_pos - 1;
-        if (first_unused < last_unused) {
-          indent(out) << "// unused fields # " << first_unused << " to " << last_unused << endl;
-        } else if (first_unused == last_unused) {
-          indent(out) << "// unused field # " << first_unused << endl;
-        }
-      }
-
-      t_type* fieldType = (*m_iter)->get_type();
-      string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter));
-      string gotag = "db:\"" + escape_string((*m_iter)->get_name())  + "\" ";
-      if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
-        gotag += "json:\"" + escape_string((*m_iter)->get_name()) + ",omitempty\"";
-      } else {
-        gotag += "json:\"" + escape_string((*m_iter)->get_name()) + "\"";
-      }
-
-      // Check for user override of db and json tags using "go.tag"
-      std::map<string, string>::iterator it = (*m_iter)->annotations_.find("go.tag");
-      if (it != (*m_iter)->annotations_.end()) {
-        gotag = it->second;
-      }
-      indent(out) << publicize((*m_iter)->get_name()) << " " << goType << " `thrift:\""
-                  << escape_string((*m_iter)->get_name()) << "," << sorted_keys_pos;
-      if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
-        out << ",required";
-      }
-
-      out << "\" " << gotag << "`" << endl;
-      sorted_keys_pos++;
-    }
-  } else {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      // This fills in default values, as opposed to nulls
-      out << indent() << publicize((*m_iter)->get_name()) << " "
-          << type_to_go_type((*m_iter)->get_type()) << endl;
-    }
-  }
-
-  indent_down();
-  out << indent() << "}" << endl << endl;
-  out << indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl;
-  out << indent() << "  return &";
-  generate_go_struct_initializer(out, tstruct, is_result || is_args);
-  out << indent() << "}" << endl << endl;
-  // Default values for optional fields
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    string publicized_name;
-    t_const_value* def_value;
-    get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
-    t_type* fieldType = (*m_iter)->get_type();
-    string goType = type_to_go_type_with_opt(fieldType, false);
-    string def_var_name = tstruct_name + "_" + publicized_name + "_DEFAULT";
-    if ((*m_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*m_iter)) {
-      out << indent() << "var " << def_var_name << " " << goType;
-      if (def_value != NULL) {
-        out << " = " << render_const_value(fieldType, def_value, (*m_iter)->get_name());
-      }
-      out << endl;
-    }
-    if (is_pointer_field(*m_iter)) {
-      string goOptType = type_to_go_type_with_opt(fieldType, true);
-      string maybepointer = goOptType != goType ? "*" : "";
-      out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "
-          << goType << " {" << endl;
-      out << indent() << "  if !p.IsSet" << publicized_name << "() {" << endl;
-      out << indent() << "    return " << def_var_name << endl;
-      out << indent() << "  }" << endl;
-      out << indent() << "return " << maybepointer << "p." << publicized_name << endl;
-      out << indent() << "}" << endl;
-      num_setable += 1;
-    } else {
-      out << endl;
-      out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "
-          << goType << " {" << endl;
-      out << indent() << "  return p." << publicized_name << endl;
-      out << indent() << "}" << endl;
-    }
-  }
-
-  if (tstruct->is_union() && num_setable > 0) {
-    generate_countsetfields_helper(out, tstruct, tstruct_name, is_result);
-  }
-
-  generate_isset_helpers(out, tstruct, tstruct_name, is_result);
-  generate_go_struct_reader(out, tstruct, tstruct_name, is_result);
-  generate_go_struct_writer(out, tstruct, tstruct_name, is_result, num_setable > 0);
-
-  out << indent() << "func (p *" << tstruct_name << ") String() string {" << endl;
-  out << indent() << "  if p == nil {" << endl;
-  out << indent() << "    return \"<nil>\"" << endl;
-  out << indent() << "  }" << endl;
-  out << indent() << "  return fmt.Sprintf(\"" << escape_string(tstruct_name) << "(%+v)\", *p)"
-      << endl;
-  out << indent() << "}" << endl << endl;
-
-  if (is_exception) {
-    out << indent() << "func (p *" << tstruct_name << ") Error() string {" << endl;
-    out << indent() << "  return p.String()" << endl;
-    out << indent() << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates the IsSet helper methods for a struct
- */
-void t_go_generator::generate_isset_helpers(ofstream& out,
-                                            t_struct* tstruct,
-                                            const string& tstruct_name,
-                                            bool is_result) {
-  (void)is_result;
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  const string escaped_tstruct_name(escape_string(tstruct->get_name()));
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    const string field_name(publicize(escape_string((*f_iter)->get_name())));
-    if ((*f_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*f_iter)) {
-      out << indent() << "func (p *" << tstruct_name << ") IsSet" << field_name << "() bool {"
-          << endl;
-      indent_up();
-      t_type* ttype = (*f_iter)->get_type()->get_true_type();
-      bool is_byteslice = ttype->is_base_type() && ((t_base_type*)ttype)->is_binary();
-      bool compare_to_nil_only = ttype->is_set() || ttype->is_list() || ttype->is_map()
-                                 || (is_byteslice && !(*f_iter)->get_value());
-      if (is_pointer_field(*f_iter) || compare_to_nil_only) {
-        out << indent() << "return p." << field_name << " != nil" << endl;
-      } else {
-        string def_var_name = tstruct_name + "_" + field_name + "_DEFAULT";
-        if (is_byteslice) {
-          out << indent() << "return !bytes.Equal(p." << field_name << ", " << def_var_name << ")"
-              << endl;
-        } else {
-          out << indent() << "return p." << field_name << " != " << def_var_name << endl;
-        }
-      }
-      indent_down();
-      out << indent() << "}" << endl << endl;
-    }
-  }
-}
-
-/**
- * Generates the CountSetFields helper method for a struct
- */
-void t_go_generator::generate_countsetfields_helper(ofstream& out,
-                                                    t_struct* tstruct,
-                                                    const string& tstruct_name,
-                                                    bool is_result) {
-  (void)is_result;
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  const string escaped_tstruct_name(escape_string(tstruct->get_name()));
-
-  out << indent() << "func (p *" << tstruct_name << ") CountSetFields" << tstruct_name << "() int {"
-      << endl;
-  indent_up();
-  out << indent() << "count := 0" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
-      continue;
-
-    if (!is_pointer_field(*f_iter))
-      continue;
-
-    const string field_name(publicize(escape_string((*f_iter)->get_name())));
-
-    out << indent() << "if (p.IsSet" << field_name << "()) {" << endl;
-    indent_up();
-    out << indent() << "count++" << endl;
-    indent_down();
-    out << indent() << "}" << endl;
-  }
-
-  out << indent() << "return count" << endl << endl;
-  indent_down();
-  out << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates the read method for a struct
- */
-void t_go_generator::generate_go_struct_reader(ofstream& out,
-                                               t_struct* tstruct,
-                                               const string& tstruct_name,
-                                               bool is_result) {
-  (void)is_result;
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  string escaped_tstruct_name(escape_string(tstruct->get_name()));
-  out << indent() << "func (p *" << tstruct_name << ") " << read_method_name_ << "(iprot thrift.TProtocol) error {"
-      << endl;
-  indent_up();
-  out << indent() << "if _, err := iprot.ReadStructBegin(); err != nil {" << endl;
-  out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T read error: \", p), err)"
-      << endl;
-  out << indent() << "}" << endl << endl;
-
-  // Required variables does not have IsSet functions, so we need tmp vars to check them.
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      const string field_name(publicize(escape_string((*f_iter)->get_name())));
-      indent(out) << "var isset" << field_name << " bool = false;" << endl;
-    }
-  }
-  out << endl;
-
-  // Loop over reading in fields
-  indent(out) << "for {" << endl;
-  indent_up();
-  // Read beginning field marker
-  out << indent() << "_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()" << endl;
-  out << indent() << "if err != nil {" << endl;
-  out << indent() << "  return thrift.PrependError(fmt.Sprintf("
-                     "\"%T field %d read error: \", p, fieldId), err)" << endl;
-  out << indent() << "}" << endl;
-  // Check for field STOP marker and break
-  out << indent() << "if fieldTypeId == thrift.STOP { break; }" << endl;
-
-  string thriftFieldTypeId;
-  // Generate deserialization code for known cases
-  int32_t field_id = -1;
-
-  // Switch statement on the field we are reading, false if no fields present
-  bool have_switch = !fields.empty();
-  if (have_switch) {
-    indent(out) << "switch fieldId {" << endl;
-  }
-
-  // All the fields we know
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    field_id = (*f_iter)->get_key();
-
-    // if negative id, ensure we generate a valid method name
-    string field_method_prefix("ReadField");
-    int32_t field_method_suffix = field_id;
-
-    if (field_method_suffix < 0) {
-      field_method_prefix += "_";
-      field_method_suffix *= -1;
-    }
-
-    out << indent() << "case " << field_id << ":" << endl;
-    indent_up();
-    thriftFieldTypeId = type_to_enum((*f_iter)->get_type());
-
-    if (thriftFieldTypeId == "thrift.BINARY") {
-      thriftFieldTypeId = "thrift.STRING";
-    }
-
-    out << indent() << "if err := p." << field_method_prefix << field_method_suffix << "(iprot); err != nil {"
-        << endl;
-    out << indent() << "  return err" << endl;
-    out << indent() << "}" << endl;
-
-    // Mark required field as read
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      const string field_name(publicize(escape_string((*f_iter)->get_name())));
-      out << indent() << "isset" << field_name << " = true" << endl;
-    }
-
-    indent_down();
-  }
-
-  // Begin switch default case
-  if (have_switch) {
-    out << indent() << "default:" << endl;
-    indent_up();
-  }
-
-  // Skip unknown fields in either case
-  out << indent() << "if err := iprot.Skip(fieldTypeId); err != nil {" << endl;
-  out << indent() << "  return err" << endl;
-  out << indent() << "}" << endl;
-
-  // End switch default case
-  if (have_switch) {
-    indent_down();
-    out << indent() << "}" << endl;
-  }
-
-  // Read field end marker
-  out << indent() << "if err := iprot.ReadFieldEnd(); err != nil {" << endl;
-  out << indent() << "  return err" << endl;
-  out << indent() << "}" << endl;
-  indent_down();
-  out << indent() << "}" << endl;
-  out << indent() << "if err := iprot.ReadStructEnd(); err != nil {" << endl;
-  out << indent() << "  return thrift.PrependError(fmt.Sprintf("
-                     "\"%T read struct end error: \", p), err)" << endl;
-  out << indent() << "}" << endl;
-
-  // Return error if any required fields are missing.
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      const string field_name(publicize(escape_string((*f_iter)->get_name())));
-      out << indent() << "if !isset" << field_name << "{" << endl;
-      out << indent() << "  return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, "
-                         "fmt.Errorf(\"Required field " << field_name << " is not set\"));" << endl;
-      out << indent() << "}" << endl;
-    }
-  }
-
-  out << indent() << "return nil" << endl;
-  indent_down();
-  out << indent() << "}" << endl << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    string field_type_name(publicize((*f_iter)->get_type()->get_name()));
-    string field_name(publicize((*f_iter)->get_name()));
-    string field_method_prefix("ReadField");
-    int32_t field_id = (*f_iter)->get_key();
-    int32_t field_method_suffix = field_id;
-
-    if (field_method_suffix < 0) {
-      field_method_prefix += "_";
-      field_method_suffix *= -1;
-    }
-
-    out << indent() << "func (p *" << tstruct_name << ")  " << field_method_prefix << field_method_suffix
-        << "(iprot thrift.TProtocol) error {" << endl;
-    indent_up();
-    generate_deserialize_field(out, *f_iter, false, "p.");
-    indent_down();
-    out << indent() << "  return nil" << endl;
-    out << indent() << "}" << endl << endl;
-  }
-}
-
-void t_go_generator::generate_go_struct_writer(ofstream& out,
-                                               t_struct* tstruct,
-                                               const string& tstruct_name,
-                                               bool is_result,
-                                               bool uses_countsetfields) {
-  (void)is_result;
-  string name(tstruct->get_name());
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-  indent(out) << "func (p *" << tstruct_name << ") " << write_method_name_ << "(oprot thrift.TProtocol) error {" << endl;
-  indent_up();
-  if (tstruct->is_union() && uses_countsetfields) {
-    std::string tstruct_name(publicize(tstruct->get_name()));
-    out << indent() << "if c := p.CountSetFields" << tstruct_name << "(); c != 1 {" << endl
-        << indent()
-        << "  return fmt.Errorf(\"%T write union: exactly one field must be set (%d set).\", p, c)"
-        << endl << indent() << "}" << endl;
-  }
-  out << indent() << "if err := oprot.WriteStructBegin(\"" << name << "\"); err != nil {" << endl;
-  out << indent() << "  return thrift.PrependError(fmt.Sprintf("
-                     "\"%T write struct begin error: \", p), err) }" << endl;
-
-  string field_name;
-  string escape_field_name;
-  // t_const_value* field_default_value;
-  t_field::e_req field_required;
-  int32_t field_id = -1;
-
-  out << indent() << "if p != nil {" << endl;
-  indent_up();
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    string field_method_prefix("writeField");
-    field_name = (*f_iter)->get_name();
-    escape_field_name = escape_string(field_name);
-    field_id = (*f_iter)->get_key();
-    int32_t field_method_suffix = field_id;
-
-    if (field_method_suffix < 0) {
-      field_method_prefix += "_";
-      field_method_suffix *= -1;
-    }
-
-    out << indent() << "if err := p." << field_method_prefix << field_method_suffix
-        << "(oprot); err != nil { return err }" << endl;
-  }
-
-  indent_down();
-  out << indent() << "}" << endl;
-
-  // Write the struct map
-  out << indent() << "if err := oprot.WriteFieldStop(); err != nil {" << endl;
-  out << indent() << "  return thrift.PrependError(\"write field stop error: \", err) }" << endl;
-  out << indent() << "if err := oprot.WriteStructEnd(); err != nil {" << endl;
-  out << indent() << "  return thrift.PrependError(\"write struct stop error: \", err) }" << endl;
-  out << indent() << "return nil" << endl;
-  indent_down();
-  out << indent() << "}" << endl << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    string field_method_prefix("writeField");
-    field_id = (*f_iter)->get_key();
-    field_name = (*f_iter)->get_name();
-    escape_field_name = escape_string(field_name);
-    // field_default_value = (*f_iter)->get_value();
-    field_required = (*f_iter)->get_req();
-    int32_t field_method_suffix = field_id;
-
-    if (field_method_suffix < 0) {
-      field_method_prefix += "_";
-      field_method_suffix *= -1;
-    }
-
-    out << indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_method_suffix
-        << "(oprot thrift.TProtocol) (err error) {" << endl;
-    indent_up();
-
-    if (field_required == t_field::T_OPTIONAL) {
-      out << indent() << "if p.IsSet" << publicize(field_name) << "() {" << endl;
-      indent_up();
-    }
-
-    out << indent() << "if err := oprot.WriteFieldBegin(\"" << escape_field_name << "\", "
-        << type_to_enum((*f_iter)->get_type()) << ", " << field_id << "); err != nil {" << endl;
-    out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T write field begin error "
-        << field_id << ":" << escape_field_name << ": \", p), err) }" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, *f_iter, "p.");
-
-    // Write field closer
-    out << indent() << "if err := oprot.WriteFieldEnd(); err != nil {" << endl;
-    out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T write field end error "
-        << field_id << ":" << escape_field_name << ": \", p), err) }" << endl;
-
-    if (field_required == t_field::T_OPTIONAL) {
-      indent_down();
-      out << indent() << "}" << endl;
-    }
-
-    indent_down();
-    out << indent() << "  return err" << endl;
-    out << indent() << "}" << endl << endl;
-  }
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_go_generator::generate_service(t_service* tservice) {
-  string test_suffix("_test");
-  string filename = lowercase(service_name_);
-  string f_service_name;
-
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-  generate_service_helpers(tservice);
-  generate_service_remote(tservice);
-  f_types_ << endl;
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_go_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  f_types_ << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_go_struct_definition(f_types_, ts, false, false, true);
-    generate_go_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_go_generator::generate_go_function_helpers(t_function* tfunction) {
-  if (!tfunction->is_oneway()) {
-    t_struct result(program_, tfunction->get_name() + "_result");
-    t_field success(tfunction->get_returntype(), "success", 0);
-    success.set_req(t_field::T_OPTIONAL);
-
-    if (!tfunction->get_returntype()->is_void()) {
-      result.append(&success);
-    }
-
-    t_struct* xs = tfunction->get_xceptions();
-    const vector<t_field*>& fields = xs->get_members();
-    vector<t_field*>::const_iterator f_iter;
-
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      t_field* f = *f_iter;
-      f->set_req(t_field::T_OPTIONAL);
-      result.append(f);
-    }
-
-    generate_go_struct_definition(f_types_, &result, false, true);
-  }
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_go_generator::generate_service_interface(t_service* tservice) {
-  string extends = "";
-  string extends_if = "";
-  string serviceName(publicize(tservice->get_name()));
-  string interfaceName = serviceName;
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    size_t index = extends.rfind(".");
-
-    if (index != string::npos) {
-      extends_if = "\n" + indent() + "  " + extends.substr(0, index + 1)
-                   + publicize(extends.substr(index + 1)) + "\n";
-    } else {
-      extends_if = "\n" + indent() + publicize(extends) + "\n";
-    }
-  }
-
-  f_types_ << indent() << "type " << interfaceName << " interface {" << extends_if;
-  indent_up();
-  generate_go_docstring(f_types_, tservice);
-  vector<t_function*> functions = tservice->get_functions();
-
-  if (!functions.empty()) {
-    f_types_ << endl;
-    vector<t_function*>::iterator f_iter;
-
-    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-      generate_go_docstring(f_types_, (*f_iter));
-      f_types_ << indent() << function_signature_if(*f_iter, "", true) << endl;
-    }
-  }
-
-  indent_down();
-  f_types_ << indent() << "}" << endl << endl;
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_go_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  string extends_field = "";
-  string extends_client = "";
-  string extends_client_new = "";
-  string serviceName(publicize(tservice->get_name()));
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    size_t index = extends.rfind(".");
-
-    if (index != string::npos) {
-      extends_client = extends.substr(0, index + 1) + publicize(extends.substr(index + 1))
-                       + "Client";
-      extends_client_new = extends.substr(0, index + 1) + "New"
-                           + publicize(extends.substr(index + 1)) + "Client";
-    } else {
-      extends_client = publicize(extends) + "Client";
-      extends_client_new = "New" + extends_client;
-    }
-  }
-
-  extends_field = extends_client.substr(extends_client.find(".") + 1);
-
-  generate_go_docstring(f_types_, tservice);
-  f_types_ << indent() << "type " << serviceName << "Client struct {" << endl;
-  indent_up();
-
-  if (!extends_client.empty()) {
-    f_types_ << indent() << "*" << extends_client << endl;
-  } else {
-    f_types_ << indent() << "Transport thrift.TTransport" << endl;
-    f_types_ << indent() << "ProtocolFactory thrift.TProtocolFactory" << endl;
-    f_types_ << indent() << "InputProtocol thrift.TProtocol" << endl;
-    f_types_ << indent() << "OutputProtocol thrift.TProtocol" << endl;
-    f_types_ << indent() << "SeqId int32" << endl;
-    /*f_types_ << indent() << "reqs map[int32]Deferred" << endl*/;
-  }
-
-  indent_down();
-  f_types_ << indent() << "}" << endl << endl;
-  // Constructor function
-  f_types_ << indent() << "func New" << serviceName
-             << "ClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *" << serviceName
-             << "Client {" << endl;
-  indent_up();
-  f_types_ << indent() << "return &" << serviceName << "Client";
-
-  if (!extends.empty()) {
-    f_types_ << "{" << extends_field << ": " << extends_client_new << "Factory(t, f)}";
-  } else {
-    indent_up();
-    f_types_ << "{Transport: t," << endl;
-    f_types_ << indent() << "ProtocolFactory: f," << endl;
-    f_types_ << indent() << "InputProtocol: f.GetProtocol(t)," << endl;
-    f_types_ << indent() << "OutputProtocol: f.GetProtocol(t)," << endl;
-    f_types_ << indent() << "SeqId: 0," << endl;
-    /*f_types_ << indent() << "Reqs: make(map[int32]Deferred)" << endl*/;
-    indent_down();
-    f_types_ << indent() << "}" << endl;
-  }
-
-  indent_down();
-  f_types_ << indent() << "}" << endl << endl;
-  // Constructor function
-  f_types_
-      << indent() << "func New" << serviceName
-      << "ClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *"
-      << serviceName << "Client {" << endl;
-  indent_up();
-  f_types_ << indent() << "return &" << serviceName << "Client";
-
-  if (!extends.empty()) {
-    f_types_ << "{" << extends_field << ": " << extends_client_new << "Protocol(t, iprot, oprot)}"
-               << endl;
-  } else {
-    indent_up();
-    f_types_ << "{Transport: t," << endl;
-    f_types_ << indent() << "ProtocolFactory: nil," << endl;
-    f_types_ << indent() << "InputProtocol: iprot," << endl;
-    f_types_ << indent() << "OutputProtocol: oprot," << endl;
-    f_types_ << indent() << "SeqId: 0," << endl;
-    /*f_types_ << indent() << "Reqs: make(map[int32]interface{})" << endl*/;
-    indent_down();
-    f_types_ << indent() << "}" << endl;
-  }
-
-  indent_down();
-  f_types_ << indent() << "}" << endl << endl;
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = publicize((*f_iter)->get_name());
-    // Open function
-    generate_go_docstring(f_types_, (*f_iter));
-    f_types_ << indent() << "func (p *" << serviceName << "Client) "
-               << function_signature_if(*f_iter, "", true) << " {" << endl;
-    indent_up();
-    /*
-    f_types_ <<
-      indent() << "p.SeqId += 1" << endl;
-    if (!(*f_iter)->is_oneway()) {
-      f_types_ <<
-        indent() << "d := defer.Deferred()" << endl <<
-        indent() << "p.Reqs[p.SeqId] = d" << endl;
-    }
-    */
-    f_types_ << indent() << "if err = p.send" << funname << "(";
-    bool first = true;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        f_types_ << ", ";
-      }
-
-      f_types_ << variable_name_to_go_name((*fld_iter)->get_name());
-    }
-
-    f_types_ << "); err != nil { return }" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_types_ << indent() << "return p.recv" << funname << "()" << endl;
-    } else {
-      f_types_ << indent() << "return" << endl;
-    }
-
-    indent_down();
-    f_types_ << indent() << "}" << endl << endl;
-    f_types_ << indent() << "func (p *" << serviceName << "Client) send"
-               << function_signature(*f_iter) << "(err error) {" << endl;
-    indent_up();
-    std::string argsname = publicize((*f_iter)->get_name() + "_args", true);
-    // Serialize the request header
-    f_types_ << indent() << "oprot := p.OutputProtocol" << endl;
-    f_types_ << indent() << "if oprot == nil {" << endl;
-    f_types_ << indent() << "  oprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl;
-    f_types_ << indent() << "  p.OutputProtocol = oprot" << endl;
-    f_types_ << indent() << "}" << endl;
-    f_types_ << indent() << "p.SeqId++" << endl;
-    f_types_ << indent() << "if err = oprot.WriteMessageBegin(\"" << (*f_iter)->get_name()
-               << "\", " << ((*f_iter)->is_oneway() ? "thrift.ONEWAY" : "thrift.CALL")
-               << ", p.SeqId); err != nil {" << endl;
-    indent_up();
-    f_types_ << indent() << "  return" << endl;
-    indent_down();
-    f_types_ << indent() << "}" << endl;
-    f_types_ << indent() << "args := " << argsname << "{" << endl;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_types_ << indent() << publicize((*fld_iter)->get_name()) << " : "
-                 << variable_name_to_go_name((*fld_iter)->get_name()) << "," << endl;
-    }
-    f_types_ << indent() << "}" << endl;
-
-    // Write to the stream
-    f_types_ << indent() << "if err = args." << write_method_name_ << "(oprot); err != nil {" << endl;
-    indent_up();
-    f_types_ << indent() << "  return" << endl;
-    indent_down();
-    f_types_ << indent() << "}" << endl;
-    f_types_ << indent() << "if err = oprot.WriteMessageEnd(); err != nil {" << endl;
-    indent_up();
-    f_types_ << indent() << "  return" << endl;
-    indent_down();
-    f_types_ << indent() << "}" << endl;
-    f_types_ << indent() << "return oprot.Flush()" << endl;
-    indent_down();
-    f_types_ << indent() << "}" << endl << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = publicize((*f_iter)->get_name() + "_result", true);
-      // Open function
-      f_types_ << endl << indent() << "func (p *" << serviceName << "Client) recv"
-                 << publicize((*f_iter)->get_name()) << "() (";
-
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_types_ << "value " << type_to_go_type((*f_iter)->get_returntype()) << ", ";
-      }
-
-      f_types_ << "err error) {" << endl;
-      indent_up();
-      // TODO(mcslee): Validate message reply here, seq ids etc.
-      string error(tmp("error"));
-      string error2(tmp("error"));
-      f_types_ << indent() << "iprot := p.InputProtocol" << endl;
-      f_types_ << indent() << "if iprot == nil {" << endl;
-      f_types_ << indent() << "  iprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl;
-      f_types_ << indent() << "  p.InputProtocol = iprot" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "method, mTypeId, seqId, err := iprot.ReadMessageBegin()" << endl;
-      f_types_ << indent() << "if err != nil {" << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "if method != \"" << (*f_iter)->get_name() << "\" {" << endl;
-      f_types_ << indent() << "  err = thrift.NewTApplicationException("
-                 << "thrift.WRONG_METHOD_NAME, \"" << (*f_iter)->get_name()
-                 << " failed: wrong method name\")" << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "if p.SeqId != seqId {" << endl;
-      f_types_ << indent() << "  err = thrift.NewTApplicationException("
-                 << "thrift.BAD_SEQUENCE_ID, \"" << (*f_iter)->get_name()
-                 << " failed: out of sequence response\")" << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "if mTypeId == thrift.EXCEPTION {" << endl;
-      f_types_ << indent() << "  " << error
-                 << " := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "
-                    "\"Unknown Exception\")" << endl;
-      f_types_ << indent() << "  var " << error2 << " error" << endl;
-      f_types_ << indent() << "  " << error2 << ", err = " << error << ".Read(iprot)" << endl;
-      f_types_ << indent() << "  if err != nil {" << endl;
-      f_types_ << indent() << "    return" << endl;
-      f_types_ << indent() << "  }" << endl;
-      f_types_ << indent() << "  if err = iprot.ReadMessageEnd(); err != nil {" << endl;
-      f_types_ << indent() << "    return" << endl;
-      f_types_ << indent() << "  }" << endl;
-      f_types_ << indent() << "  err = " << error2 << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "if mTypeId != thrift.REPLY {" << endl;
-      f_types_ << indent() << "  err = thrift.NewTApplicationException("
-                 << "thrift.INVALID_MESSAGE_TYPE_EXCEPTION, \"" << (*f_iter)->get_name()
-                 << " failed: invalid message type\")" << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "result := " << resultname << "{}" << endl;
-      f_types_ << indent() << "if err = result." << read_method_name_ << "(iprot); err != nil {" << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-      f_types_ << indent() << "if err = iprot.ReadMessageEnd(); err != nil {" << endl;
-      f_types_ << indent() << "  return" << endl;
-      f_types_ << indent() << "}" << endl;
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        const std::string pubname = publicize((*x_iter)->get_name());
-
-        f_types_ << indent() << "if result." << pubname << " != nil {" << endl;
-        f_types_ << indent() << "  err = result." << pubname << endl;
-        f_types_ << indent() << "  return " << endl;
-        f_types_ << indent() << "}";
-
-        if ((x_iter + 1) != xceptions.end()) {
-          f_types_ << " else ";
-        } else {
-          f_types_ << endl;
-        }
-      }
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_types_ << indent() << "value = result.GetSuccess()" << endl;
-      }
-
-      f_types_ << indent() << "return" << endl;
-      // Close function
-      indent_down();
-      f_types_ << indent() << "}" << endl << endl;
-    }
-  }
-
-  // indent_down();
-  f_types_ << endl;
-}
-
-/**
- * Generates a command line tool for making remote requests
- *
- * @param tservice The service to generate a remote for.
- */
-void t_go_generator::generate_service_remote(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  t_service* parent = tservice->get_extends();
-
-  // collect inherited functions
-  while (parent != NULL) {
-    vector<t_function*> p_functions = parent->get_functions();
-    functions.insert(functions.end(), p_functions.begin(), p_functions.end());
-    parent = parent->get_extends();
-  }
-
-  vector<t_function*>::iterator f_iter;
-  string f_remote_name = package_dir_ + "/" + underscore(service_name_) + "-remote/"
-                         + underscore(service_name_) + "-remote.go";
-  ofstream f_remote;
-  f_remote.open(f_remote_name.c_str());
-  string service_module = get_real_go_module(program_);
-  string::size_type loc;
-
-  while ((loc = service_module.find(".")) != string::npos) {
-    service_module.replace(loc, 1, 1, '/');
-  }
-  if (!gen_package_prefix_.empty()) {
-    service_module = gen_package_prefix_ + service_module;
-  }
-
-  string unused_protection;
-
-  f_remote << go_autogen_comment();
-  f_remote << indent() << "package main" << endl << endl;
-  f_remote << indent() << "import (" << endl;
-  f_remote << indent() << "        \"flag\"" << endl;
-  f_remote << indent() << "        \"fmt\"" << endl;
-  f_remote << indent() << "        \"math\"" << endl;
-  f_remote << indent() << "        \"net\"" << endl;
-  f_remote << indent() << "        \"net/url\"" << endl;
-  f_remote << indent() << "        \"os\"" << endl;
-  f_remote << indent() << "        \"strconv\"" << endl;
-  f_remote << indent() << "        \"strings\"" << endl;
-  f_remote << indent() << "        \"" + gen_thrift_import_ + "\"" << endl;
-  f_remote << indent() << render_included_programs(unused_protection);
-  f_remote << indent() << "        \"" << service_module << "\"" << endl;
-  f_remote << indent() << ")" << endl;
-  f_remote << indent() << endl;
-  f_remote << indent() << unused_protection; // filled in render_included_programs()
-  f_remote << indent() << endl;
-  f_remote << indent() << "func Usage() {" << endl;
-  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Usage of \", os.Args[0], \" "
-                          "[-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:\")"
-           << endl;
-  f_remote << indent() << "  flag.PrintDefaults()" << endl;
-  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"\\nFunctions:\")" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_remote << "  fmt.Fprintln(os.Stderr, \"  " << (*f_iter)->get_returntype()->get_name() << " "
-             << (*f_iter)->get_name() << "(";
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
-    std::vector<t_field*>::size_type num_args = args.size();
-    bool first = true;
-
-    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
-      if (first) {
-        first = false;
-      } else {
-        f_remote << ", ";
-      }
-
-      f_remote << args[i]->get_type()->get_name() << " " << args[i]->get_name();
-    }
-
-    f_remote << ")\")" << endl;
-  }
-
-  f_remote << indent() << "  fmt.Fprintln(os.Stderr)" << endl;
-  f_remote << indent() << "  os.Exit(0)" << endl;
-  f_remote << indent() << "}" << endl;
-  f_remote << indent() << endl;
-  f_remote << indent() << "func main() {" << endl;
-  indent_up();
-  f_remote << indent() << "flag.Usage = Usage" << endl;
-  f_remote << indent() << "var host string" << endl;
-  f_remote << indent() << "var port int" << endl;
-  f_remote << indent() << "var protocol string" << endl;
-  f_remote << indent() << "var urlString string" << endl;
-  f_remote << indent() << "var framed bool" << endl;
-  f_remote << indent() << "var useHttp bool" << endl;
-  f_remote << indent() << "var parsedUrl url.URL" << endl;
-  f_remote << indent() << "var trans thrift.TTransport" << endl;
-  f_remote << indent() << "_ = strconv.Atoi" << endl;
-  f_remote << indent() << "_ = math.Abs" << endl;
-  f_remote << indent() << "flag.Usage = Usage" << endl;
-  f_remote << indent() << "flag.StringVar(&host, \"h\", \"localhost\", \"Specify host and port\")"
-           << endl;
-  f_remote << indent() << "flag.IntVar(&port, \"p\", 9090, \"Specify port\")" << endl;
-  f_remote << indent() << "flag.StringVar(&protocol, \"P\", \"binary\", \""
-                          "Specify the protocol (binary, compact, simplejson, json)\")" << endl;
-  f_remote << indent() << "flag.StringVar(&urlString, \"u\", \"\", \"Specify the url\")" << endl;
-  f_remote << indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")"
-           << endl;
-  f_remote << indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl;
-  f_remote << indent() << "flag.Parse()" << endl;
-  f_remote << indent() << endl;
-  f_remote << indent() << "if len(urlString) > 0 {" << endl;
-  f_remote << indent() << "  parsedUrl, err := url.Parse(urlString)" << endl;
-  f_remote << indent() << "  if err != nil {" << endl;
-  f_remote << indent() << "    fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl;
-  f_remote << indent() << "    flag.Usage()" << endl;
-  f_remote << indent() << "  }" << endl;
-  f_remote << indent() << "  host = parsedUrl.Host" << endl;
-  f_remote << indent() << "  useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\""
-           << endl;
-  f_remote << indent() << "} else if useHttp {" << endl;
-  f_remote << indent() << "  _, err := url.Parse(fmt.Sprint(\"http://\", host, \":\", port))"
-           << endl;
-  f_remote << indent() << "  if err != nil {" << endl;
-  f_remote << indent() << "    fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl;
-  f_remote << indent() << "    flag.Usage()" << endl;
-  f_remote << indent() << "  }" << endl;
-  f_remote << indent() << "}" << endl;
-  f_remote << indent() << endl;
-  f_remote << indent() << "cmd := flag.Arg(0)" << endl;
-  f_remote << indent() << "var err error" << endl;
-  f_remote << indent() << "if useHttp {" << endl;
-  f_remote << indent() << "  trans, err = thrift.NewTHttpClient(parsedUrl.String())" << endl;
-  f_remote << indent() << "} else {" << endl;
-  f_remote << indent() << "  portStr := fmt.Sprint(port)" << endl;
-  f_remote << indent() << "  if strings.Contains(host, \":\") {" << endl;
-  f_remote << indent() << "         host, portStr, err = net.SplitHostPort(host)" << endl;
-  f_remote << indent() << "         if err != nil {" << endl;
-  f_remote << indent() << "                 fmt.Fprintln(os.Stderr, \"error with host:\", err)"
-           << endl;
-  f_remote << indent() << "                 os.Exit(1)" << endl;
-  f_remote << indent() << "         }" << endl;
-  f_remote << indent() << "  }" << endl;
-  f_remote << indent() << "  trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr))"
-           << endl;
-  f_remote << indent() << "  if err != nil {" << endl;
-  f_remote << indent() << "    fmt.Fprintln(os.Stderr, \"error resolving address:\", err)" << endl;
-  f_remote << indent() << "    os.Exit(1)" << endl;
-  f_remote << indent() << "  }" << endl;
-  f_remote << indent() << "  if framed {" << endl;
-  f_remote << indent() << "    trans = thrift.NewTFramedTransport(trans)" << endl;
-  f_remote << indent() << "  }" << endl;
-  f_remote << indent() << "}" << endl;
-  f_remote << indent() << "if err != nil {" << endl;
-  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Error creating transport\", err)" << endl;
-  f_remote << indent() << "  os.Exit(1)" << endl;
-  f_remote << indent() << "}" << endl;
-  f_remote << indent() << "defer trans.Close()" << endl;
-  f_remote << indent() << "var protocolFactory thrift.TProtocolFactory" << endl;
-  f_remote << indent() << "switch protocol {" << endl;
-  f_remote << indent() << "case \"compact\":" << endl;
-  f_remote << indent() << "  protocolFactory = thrift.NewTCompactProtocolFactory()" << endl;
-  f_remote << indent() << "  break" << endl;
-  f_remote << indent() << "case \"simplejson\":" << endl;
-  f_remote << indent() << "  protocolFactory = thrift.NewTSimpleJSONProtocolFactory()" << endl;
-  f_remote << indent() << "  break" << endl;
-  f_remote << indent() << "case \"json\":" << endl;
-  f_remote << indent() << "  protocolFactory = thrift.NewTJSONProtocolFactory()" << endl;
-  f_remote << indent() << "  break" << endl;
-  f_remote << indent() << "case \"binary\", \"\":" << endl;
-  f_remote << indent() << "  protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()" << endl;
-  f_remote << indent() << "  break" << endl;
-  f_remote << indent() << "default:" << endl;
-  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Invalid protocol specified: \", protocol)"
-           << endl;
-  f_remote << indent() << "  Usage()" << endl;
-  f_remote << indent() << "  os.Exit(1)" << endl;
-  f_remote << indent() << "}" << endl;
-  f_remote << indent() << "client := " << package_name_ << ".New" << publicize(service_name_)
-           << "ClientFactory(trans, protocolFactory)" << endl;
-  f_remote << indent() << "if err := trans.Open(); err != nil {" << endl;
-  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Error opening socket to \", "
-                          "host, \":\", port, \" \", err)" << endl;
-  f_remote << indent() << "  os.Exit(1)" << endl;
-  f_remote << indent() << "}" << endl;
-  f_remote << indent() << endl;
-  f_remote << indent() << "switch cmd {" << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
-    std::vector<t_field*>::size_type num_args = args.size();
-    string funcName((*f_iter)->get_name());
-    string pubName(publicize(funcName));
-    string argumentsName(publicize(funcName + "_args", true));
-    f_remote << indent() << "case \"" << escape_string(funcName) << "\":" << endl;
-    indent_up();
-    f_remote << indent() << "if flag.NArg() - 1 != " << num_args << " {" << endl;
-    f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"" << escape_string(pubName) << " requires "
-             << num_args << " args\")" << endl;
-    f_remote << indent() << "  flag.Usage()" << endl;
-    f_remote << indent() << "}" << endl;
-
-    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
-      int flagArg = i + 1;
-      t_type* the_type(args[i]->get_type());
-      t_type* the_type2(get_true_type(the_type));
-
-      if (the_type2->is_enum()) {
-        f_remote << indent() << "tmp" << i << ", err := (strconv.Atoi(flag.Arg(" << flagArg << ")))"
-                 << endl;
-        f_remote << indent() << "if err != nil {" << endl;
-        f_remote << indent() << "  Usage()" << endl;
-        f_remote << indent() << " return" << endl;
-        f_remote << indent() << "}" << endl;
-        f_remote << indent() << "argvalue" << i << " := " << package_name_ << "."
-                 << publicize(the_type->get_name()) << "(tmp" << i << ")" << endl;
-      } else if (the_type2->is_base_type()) {
-        t_base_type::t_base e = ((t_base_type*)the_type2)->get_base();
-        string err(tmp("err"));
-
-        switch (e) {
-        case t_base_type::TYPE_VOID:
-          break;
-
-        case t_base_type::TYPE_STRING:
-          if (((t_base_type*)the_type2)->is_binary()) {
-            f_remote << indent() << "argvalue" << i << " := []byte(flag.Arg(" << flagArg << "))"
-                     << endl;
-          } else {
-            f_remote << indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ")" << endl;
-          }
-          break;
-
-        case t_base_type::TYPE_BOOL:
-          f_remote << indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ") == \"true\""
-                   << endl;
-          break;
-
-        case t_base_type::TYPE_I8:
-          f_remote << indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg("
-                   << flagArg << ")))" << endl;
-          f_remote << indent() << "if " << err << " != nil {" << endl;
-          f_remote << indent() << "  Usage()" << endl;
-          f_remote << indent() << "  return" << endl;
-          f_remote << indent() << "}" << endl;
-          f_remote << indent() << "argvalue" << i << " := int8(tmp" << i << ")" << endl;
-          break;
-
-        case t_base_type::TYPE_I16:
-          f_remote << indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg("
-                   << flagArg << ")

<TRUNCATED>

[17/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_dart_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_dart_generator.cc b/compiler/cpp/src/thrift/generate/t_dart_generator.cc
new file mode 100644
index 0000000..19bbb7b
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_dart_generator.cc
@@ -0,0 +1,2516 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <sstream>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <stdexcept>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+static const string endl2 = "\n\n";
+
+/**
+ * Use the current Thrift version for static libraries.  When releasing, update
+ * the version in these files.
+ * - lib/dart/pubspec.yaml
+ * - test/dart/test_client/pubspec.yaml
+ * - tutorial/dart/client/pubspec.yaml
+ * - tutorial/dart/console_client/pubspec.yaml
+ * - tutorial/dart/server/pubspec.yaml
+ * See https://thrift.apache.org/docs/committers/HowToVersion
+ */
+static const string dart_thrift_version = THRIFT_VERSION;
+
+/* forward declarations */
+string initial_caps_to_underscores(string name);
+
+/**
+ * Dart code generator
+ *
+ */
+class t_dart_generator : public t_oop_generator {
+public:
+  t_dart_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    library_name_ = "";
+    library_prefix_ = "";
+    package_prefix_ = "";
+    pubspec_lib_ = "";
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("library_name") == 0) {
+        library_name_ = (iter->second);
+      } else if( iter->first.compare("library_prefix") == 0) {
+        library_prefix_ = (iter->second) + ".";
+        package_prefix_ = replace_all(library_prefix_, ".", "/");
+      } else if( iter->first.compare("pubspec_lib") == 0) {
+        pubspec_lib_ = (iter->second);
+      } else {
+        throw "unknown option dart:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-dart";
+  }
+
+  void scope_up(std::ostream& out, std::string prefix=" ") {
+    out << prefix << "{" << endl;
+    indent_up();
+  }
+
+  void scope_down(std::ostream& out, std::string postfix=endl) {
+    indent_down();
+    indent(out) << "}" << postfix;
+  }
+
+  string replace_all(string contents, string search, string repl) {
+    string str(contents);
+
+    size_t slen = search.length();
+    size_t rlen = repl.length();
+    size_t incr = (rlen > 0) ? rlen : 1;
+
+    if (slen > 0) {
+      size_t found = str.find(search);
+      while ((found != string::npos) && (found < str.length())) {
+        str.replace(found, slen, repl);
+        found = str.find(search, found + incr);
+      }
+    }
+
+    return str;
+  }
+
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void export_class_to_library(string file_name, string class_name);
+
+  void generate_dart_library();
+  void generate_dart_pubspec();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ofstream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false);
+  std::string render_const_value(ofstream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_dart_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_dart_struct_definition(std::ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false,
+                                       bool is_result = false,
+                                       string export_file_name = "");
+  void generate_dart_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_dart_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_dart_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_dart_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_dart_struct_tostring(std::ofstream& out, t_struct* tstruct);
+  std::string get_dart_type_string(t_type* type);
+  void generate_generic_field_getters(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_field_setters(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
+  void generate_dart_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
+
+  void generate_function_helpers(t_function* tfunction);
+  std::string init_value(t_field* tfield);
+  std::string get_cap_name(std::string name);
+  std::string get_member_name(std::string name);
+  std::string get_args_class_name(std::string name);
+  std::string get_result_class_name(std::string name);
+  std::string get_file_name(std::string name);
+  std::string get_constants_class_name(std::string name);
+  std::string generate_isset_check(t_field* field);
+  std::string generate_isset_check(std::string field);
+  void generate_isset_set(ofstream& out, t_field* field);
+
+  void generate_service_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_dart_doc(std::ofstream& out, t_doc* tdoc);
+
+  void generate_dart_doc(std::ofstream& out, t_function* tdoc);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string find_library_name(t_program* program);
+  std::string dart_library(string file_name);
+  std::string service_imports();
+  std::string dart_thrift_imports();
+  std::string type_name(t_type* ttype);
+  std::string base_type_name(t_base_type* tbase);
+  std::string declare_field(t_field* tfield, bool init = false);
+  std::string function_signature(t_function* tfunction);
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string get_ttype_class_name(t_type* ttype);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+  vector<std::string> split(const string& s, char delim) {
+    vector<std::string> elems;
+    stringstream ss(s);
+    string item;
+    while (getline(ss, item, delim)) {
+      elems.push_back(item);
+    }
+    return elems;
+  }
+
+  std::string constant_name(std::string name);
+
+private:
+  std::ofstream f_service_;
+
+  std::string library_name_;
+  std::string library_prefix_;
+  std::string package_prefix_;
+  std::string pubspec_lib_;
+
+  std::string base_dir_;
+  std::string src_dir_;
+  std::string library_exports_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_dart_generator::init_generator() {
+  MKDIR(get_out_dir().c_str());
+
+  if (library_name_.empty()) {
+    library_name_ = find_library_name(program_);
+  }
+
+  string subdir = get_out_dir() + "/" + library_name_;
+  MKDIR(subdir.c_str());
+  base_dir_ = subdir;
+
+  if (library_prefix_.empty()) {
+    subdir += "/lib";
+    MKDIR(subdir.c_str());
+    subdir += "/src";
+    MKDIR(subdir.c_str());
+    src_dir_ = subdir;
+  } else {
+    src_dir_ = base_dir_;
+  }
+}
+
+string t_dart_generator::find_library_name(t_program* program) {
+  string name = program->get_namespace("dart");
+  if (name.empty()) {
+    name = program->get_name();
+  }
+  name = replace_all(name, ".", "_");
+  name = replace_all(name, "-", "_");
+  return name;
+}
+
+/**
+ * The Dart library
+ *
+ * @return String of the library, e.g. "library myservice;"
+ */
+string t_dart_generator::dart_library(string file_name) {
+  string out = "library " + library_prefix_ + library_name_;
+  if (!file_name.empty()) {
+    if (library_prefix_.empty()) {
+      out += ".src." + file_name;
+    } else {
+      out += "." + file_name;
+    }
+  }
+  return out + ";\n";
+}
+
+/**
+ * Prints imports for services
+ *
+ * @return List of imports for services
+ */
+string t_dart_generator::service_imports() {
+  return "import 'dart:async';" + endl;
+}
+
+/**
+ * Prints standard dart imports
+ *
+ * @return List of imports necessary for thrift
+ */
+string t_dart_generator::dart_thrift_imports() {
+  string imports = "import 'dart:typed_data' show Uint8List;" + endl +
+                   "import 'package:thrift/thrift.dart';" + endl;
+
+  // add import for this library
+  if (package_prefix_.empty()) {
+    imports += "import 'package:" + library_name_ + "/" + library_name_ + ".dart';" + endl;
+  } else {
+    imports += "import 'package:" + package_prefix_ + library_name_ + ".dart';" + endl;
+  }
+
+  // add imports for included thrift files
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    string include_name = find_library_name(includes[i]);
+    string named_import = "t_" + include_name;
+    if (package_prefix_.empty()) {
+      imports += "import 'package:" + include_name + "/" + include_name + ".dart' as " + named_import + ";" + endl;
+    } else {
+      imports += "import 'package:" + package_prefix_ + include_name + ".dart' as " + named_import + ";" + endl;
+    }
+  }
+
+  return imports;
+}
+
+/**
+ * Not used
+ */
+void t_dart_generator::close_generator() {
+  generate_dart_library();
+
+  if (library_prefix_.empty()) {
+    generate_dart_pubspec();
+  }
+}
+
+void t_dart_generator::generate_dart_library() {
+  string f_library_name;
+  if (library_prefix_.empty()) {
+    f_library_name = base_dir_ + "/lib/" + library_name_ + ".dart";
+  } else {
+    f_library_name = get_out_dir() + "/" + library_name_ + ".dart";
+  }
+
+  ofstream f_library;
+  f_library.open(f_library_name.c_str());
+
+  f_library << autogen_comment() << endl;
+  f_library << "library " << library_prefix_ << library_name_ << ";" << endl2;
+  f_library << library_exports_;
+
+  f_library.close();
+}
+
+void t_dart_generator::export_class_to_library(string file_name, string class_name) {
+  string subdir;
+  if (library_prefix_.empty()) {
+    subdir = "src";
+  } else {
+    subdir = library_name_;
+  }
+  library_exports_ += "export '" + subdir + "/" + file_name + ".dart' show " + class_name + ";" + endl;
+}
+
+void t_dart_generator::generate_dart_pubspec() {
+  string f_pubspec_name = base_dir_ + "/pubspec.yaml";
+  ofstream f_pubspec;
+  f_pubspec.open(f_pubspec_name.c_str());
+
+  indent(f_pubspec) << "name: " << library_name_ << endl;
+  indent(f_pubspec) << "version: 0.0.1" << endl;
+  indent(f_pubspec) << "description: Autogenerated by Thrift Compiler" << endl;
+  f_pubspec << endl;
+
+  indent(f_pubspec) << "environment:" << endl;
+  indent_up();
+  indent(f_pubspec) << "sdk: ^1.12.0" << endl;
+  indent_down();
+  f_pubspec << endl;
+
+  indent(f_pubspec) << "dependencies:" << endl;
+  indent_up();
+
+  if (pubspec_lib_.empty()) {
+    // default to relative path within working directory, which works for tests
+    indent(f_pubspec) << "thrift:  # ^" << dart_thrift_version << endl;
+    indent_up();
+    indent(f_pubspec) << "path: ../../../../lib/dart" << endl;
+    indent_down();
+  } else {
+    const vector<std::string> lines = split(pubspec_lib_, '|');
+    for (size_t line_index = 0; line_index < lines.size(); line_index++) {
+      indent(f_pubspec) << lines[line_index] << endl;
+    }
+  }
+
+  // add included thrift files as dependencies
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    string include_name = find_library_name(includes[i]);
+    indent(f_pubspec) << include_name << ":" << endl;
+    indent_up();
+    indent(f_pubspec) << "path: ../" << include_name << endl;
+    indent_down();
+  }
+
+  indent_down();
+  f_pubspec << endl;
+
+  f_pubspec.close();
+}
+
+/**
+ * Not used
+ *
+ * @param ttypedef The type definition
+ */
+void t_dart_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Enums are a class with a set of static constants.
+ *
+ * @param tenum The enumeration
+ */
+void t_dart_generator::generate_enum(t_enum* tenum) {
+  // Make output file
+  string file_name = get_file_name(tenum->get_name());
+
+  string f_enum_name = src_dir_ + "/" + file_name + ".dart";
+  ofstream f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  // Comment and add library
+  f_enum << autogen_comment() << dart_library(file_name) << endl;
+
+  string class_name = tenum->get_name();
+  export_class_to_library(file_name, class_name);
+  f_enum << "class " << class_name;
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "static const int " << (*c_iter)->get_name() << " = " << value << ";"
+                   << endl;
+  }
+
+  // Create a static Set with all valid values for this enum
+  f_enum << endl;
+
+  indent(f_enum) << "static final Set<int> VALID_VALUES = new Set.from([" << endl;
+  indent_up();
+  bool firstValue = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    // populate set
+    indent(f_enum) << (firstValue ? "" : ", ");
+    f_enum << (*c_iter)->get_name() << endl;
+    firstValue = false;
+  }
+  indent_down();
+  indent(f_enum) << "]);" << endl;
+
+  indent(f_enum) << "static final Map<int, String> VALUES_TO_NAMES = {" << endl;
+  indent_up();
+  firstValue = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    indent(f_enum) << (firstValue ? "" : ", ");
+    f_enum  << (*c_iter)->get_name() << ": '" << (*c_iter)->get_name() << "'" << endl;
+    firstValue = false;
+  }
+  indent_down();
+  indent(f_enum) << "};" << endl;
+
+  scope_down(f_enum); // end class
+
+  f_enum.close();
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_dart_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  string class_name = get_constants_class_name(program_name_);
+  string file_name = get_file_name(class_name);
+
+  string f_consts_name = src_dir_ + "/" + file_name + ".dart";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  // Print header
+  f_consts << autogen_comment() << dart_library(file_name) << endl;
+  f_consts << dart_thrift_imports() << endl;
+
+  export_class_to_library(file_name, class_name);
+  indent(f_consts) << "class " << class_name;
+  scope_up(f_consts);
+
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value(),
+                      false);
+    f_consts << endl;
+  }
+
+  scope_down(f_consts);
+
+  f_consts.close();
+}
+
+void t_dart_generator::print_const_value(std::ofstream& out,
+                                        string name,
+                                        t_type* type,
+                                        t_const_value* value,
+                                        bool in_static,
+                                        bool defval) {
+  type = get_true_type(type);
+
+  indent(out);
+  if (!defval) {
+    out << (in_static ? "var " : "static final ");
+  }
+  if (type->is_base_type()) {
+    if (!defval) {
+      out << type_name(type) << " ";
+    }
+    string v2 = render_const_value(out, name, type, value);
+    out << name;
+    out << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    if (!defval) {
+      out << type_name(type) << " ";
+    }
+    out << name;
+    out << " = " << value->get_integer() << ";" << endl << endl;
+  } else if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    out << type_name(type) << " " << name << " = new " << type_name(type) << "()";
+    indent_up();
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      out << endl;
+      indent(out) << ".." << v_iter->first->get_string() << " = " << val;
+    }
+    indent_down();
+    out << ";" << endl;
+  } else if (type->is_map()) {
+    if (!defval) {
+      out << type_name(type) << " ";
+    }
+    out << name << " =";
+    scope_up(out);
+
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << key << ": " << val << "," << endl;
+    }
+    scope_down(out, ";" + endl);
+
+    out << endl;
+  } else if (type->is_list() || type->is_set()) {
+    if (!defval) {
+      out << type_name(type) << " ";
+    }
+    out << name << " = ";
+    t_type* etype;
+    if (type->is_list()) {
+      out << "[" << endl;
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      out << "new " << type_name(type) << ".from([" << endl;
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+
+    indent_up();
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << val << "," << endl;
+    }
+    indent_down();
+
+    if (type->is_list()) {
+      indent(out) << "];" << endl;
+    } else {
+      indent(out) << "]);" << endl;
+    }
+
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_dart_generator::render_const_value(ofstream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value) {
+  (void)name;
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << "'" << get_escaped_string(value) << "'";
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    out << endl;
+    render << t;
+  }
+
+  return render.str();
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with data members, read(), write(), and an inner Isset class.
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_struct(t_struct* tstruct) {
+  generate_dart_struct(tstruct, false);
+}
+
+/**
+ * Exceptions are structs, but they inherit from Exception
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_xception(t_struct* txception) {
+  generate_dart_struct(txception, true);
+}
+
+/**
+ * Dart struct definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_dart_struct(t_struct* tstruct, bool is_exception) {
+  string file_name = get_file_name(tstruct->get_name());
+  string f_struct_name = src_dir_ + "/" + file_name + ".dart";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << dart_library(file_name) << endl;
+
+  string imports;
+
+  f_struct << dart_thrift_imports() << endl;
+
+  generate_dart_struct_definition(f_struct, tstruct, is_exception, false, file_name);
+
+  f_struct.close();
+}
+
+/**
+ * Dart struct definition. This has various parameters, as it could be
+ * generated standalone or inside another class as a helper. If it
+ * is a helper than it is a static class.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param in_class     If inside a class, needs to be static class
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_dart_generator::generate_dart_struct_definition(ofstream& out,
+                                                       t_struct* tstruct,
+                                                       bool is_exception,
+                                                       bool is_result,
+                                                       string export_file_name) {
+  generate_dart_doc(out, tstruct);
+
+  string class_name = tstruct->get_name();
+  if (!export_file_name.empty()) {
+    export_class_to_library(export_file_name, class_name);
+  }
+  indent(out) << "class " << class_name << " ";
+
+  if (is_exception) {
+    out << "extends Error ";
+  }
+  out << "implements TBase";
+  scope_up(out);
+
+  indent(out) << "static final TStruct _STRUCT_DESC = new TStruct(\"" << class_name
+              << "\");" << endl;
+
+  // Members are public for -dart, private for -dartbean
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "static final TField _" << constant_name((*m_iter)->get_name())
+                << "_FIELD_DESC = new TField(\"" << (*m_iter)->get_name() << "\", "
+                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");"
+                << endl;
+  }
+
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_dart_doc(out, *m_iter);
+    indent(out) << type_name((*m_iter)->get_type()) + " _"
+                << get_member_name((*m_iter)->get_name()) << init_value(*m_iter) << ";" << endl;
+
+    indent(out) << "static const int " << upcase_string((*m_iter)->get_name())
+                << " = " << (*m_iter)->get_key() << ";" << endl;
+  }
+
+  out << endl;
+
+  // Inner Isset class
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (!type_can_be_null((*m_iter)->get_type())) {
+        string field_name = get_member_name((*m_iter)->get_name());
+        indent(out) << "bool __isset_" << field_name << " = false;" << endl;
+      }
+    }
+  }
+
+  out << endl;
+
+  // Default constructor
+  indent(out) << tstruct->get_name() << "()";
+  scope_up(out);
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL) {
+      print_const_value(out,
+                        "this." + get_member_name((*m_iter)->get_name()),
+                        t,
+                        (*m_iter)->get_value(),
+                        true,
+                        true);
+    }
+  }
+  scope_down(out);
+  out << endl;
+
+  generate_dart_bean_boilerplate(out, tstruct);
+  generate_generic_field_getters(out, tstruct);
+  generate_generic_field_setters(out, tstruct);
+  generate_generic_isset_method(out, tstruct);
+
+  generate_dart_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_dart_struct_result_writer(out, tstruct);
+  } else {
+    generate_dart_struct_writer(out, tstruct);
+  }
+  generate_dart_struct_tostring(out, tstruct);
+  generate_dart_validator(out, tstruct);
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_dart_struct_reader(ofstream& out, t_struct* tstruct) {
+  indent(out) << "read(TProtocol iprot)";
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables and read struct header
+  indent(out) << "TField field;" << endl;
+  indent(out) << "iprot.readStructBegin();" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)";
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "field = iprot.readFieldBegin();" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (field.type == TType.STOP)";
+  scope_up(out);
+  indent(out) << "break;" << endl;
+  scope_down(out);
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (field.id)";
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl;
+    indent_up();
+
+    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ")";
+    scope_up(out);
+
+    generate_deserialize_field(out, *f_iter, "this.");
+    generate_isset_set(out, *f_iter);
+
+    scope_down(out, " else");
+    scope_up(out);
+    indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl;
+    scope_down(out);
+
+    indent(out) << "break;" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  indent(out) << "default:" << endl;
+  indent_up();
+  indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl;
+  indent(out) << "break;" << endl;
+  indent_down();
+
+  scope_down(out);
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  indent(out) << "iprot.readStructEnd();" << endl2;
+
+  // in non-beans style, check for required fields of primitive type
+  // (which can be checked here but not in the general validate method)
+  indent(out) << "// check for required fields of primitive type, which can't be "
+                 "checked in the validate method" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
+      string field_name = get_member_name((*f_iter)->get_name());
+      indent(out) << "if (!__isset_" << field_name << ")";
+      scope_up(out);
+      indent(out) << "  throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '"
+          << field_name
+          << "' was not found in serialized data! Struct: \" + toString());" << endl;
+      scope_down(out, endl2);
+    }
+  }
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl;
+
+  scope_down(out, endl2);
+}
+
+// generates dart method to perform various checks
+// (e.g. check that all required fields are set)
+void t_dart_generator::generate_dart_validator(ofstream& out, t_struct* tstruct) {
+  indent(out) << "validate()";
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      string field_name = get_member_name((*f_iter)->get_name());
+      if (type_can_be_null((*f_iter)->get_type())) {
+        indent(out) << "if (" << field_name << " == null)";
+        scope_up(out);
+        indent(out) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '"
+                    << field_name << "' was not present! Struct: \" + toString());"
+                    << endl;
+        scope_down(out);
+      } else {
+        indent(out) << "// alas, we cannot check '" << field_name
+                    << "' because it's a primitive and you chose the non-beans generator." << endl;
+      }
+    }
+  }
+
+  // check that fields of type enum have valid values
+  indent(out) << "// check that fields of type enum have valid values" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    t_type* type = field->get_type();
+    // if field is an enum, check that its value is valid
+    if (type->is_enum()) {
+      string field_name = get_member_name(field->get_name());
+      indent(out) << "if (" << generate_isset_check(field) << " && !" << get_ttype_class_name(type)
+                  << ".VALID_VALUES.contains(" << field_name << "))";
+      scope_up(out);
+      indent(out) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"The field '"
+                  << field_name << "' has been assigned the invalid value "
+                  << "$" << field_name << "\");" << endl;
+      scope_down(out);
+    }
+  }
+
+  scope_down(out, endl2);
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_dart_struct_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "write(TProtocol oprot)";
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl2;
+
+  indent(out) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string field_name = get_member_name((*f_iter)->get_name());
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ")";
+      scope_up(out);
+    }
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      indent(out) << "if (this." << field_name << " != null)";
+      scope_up(out);
+    }
+
+    indent(out) << "oprot.writeFieldBegin(_" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    if (null_allowed) {
+      scope_down(out);
+    }
+    if (could_be_unset) {
+      scope_down(out);
+    }
+  }
+  // Write the struct map
+  indent(out) << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
+      << endl;
+
+  scope_down(out, endl2);
+}
+
+/**
+ * Generates a function to write all the fields of the struct,
+ * which is a function result. These fields are only written
+ * if they are set in the Isset array, and only one of them
+ * can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_dart_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  indent(out) << "write(TProtocol oprot)";
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl2;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      indent(out) << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this." << generate_isset_check(*f_iter) << ")";
+    scope_up(out);
+
+    indent(out) << "oprot.writeFieldBegin(_" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    scope_down(out, "");
+  }
+  out << endl;
+
+  // Write the struct map
+  indent(out) << "oprot.writeFieldStop();" << endl << indent()
+      << "oprot.writeStructEnd();" << endl;
+
+  scope_down(out, endl2);
+}
+
+void t_dart_generator::generate_generic_field_getters(std::ofstream& out,
+                                                      t_struct* tstruct) {
+  // create the getter
+  indent(out) << "getFieldValue(int fieldID)";
+  scope_up(out);
+
+  indent(out) << "switch (fieldID)";
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    std::string field_name = get_member_name(field->get_name());
+
+    indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+    indent_up();
+    indent(out) << "return this." << field_name << ";" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent_up();
+  indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl;
+  indent_down();
+
+  scope_down(out);  // switch
+  scope_down(out, endl2);  // method
+}
+
+void t_dart_generator::generate_generic_field_setters(std::ofstream& out,
+                                                      t_struct* tstruct) {
+
+  // create the setter
+  indent(out) << "setFieldValue(int fieldID, Object value)";
+  scope_up(out);
+
+  indent(out) << "switch (fieldID)";
+  scope_up(out);
+
+  // build up the bodies of both the getter and setter at once
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    std::string field_name = get_member_name(field->get_name());
+
+    indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+    indent_up();
+
+    indent(out) << "if (value == null)";
+    scope_up(out);
+    indent(out) << "unset" << get_cap_name(field_name) << "();" << endl;
+
+    scope_down(out, " else");
+    scope_up(out);
+    indent(out) << "this." << field_name << " = value;" << endl;
+    scope_down(out);
+
+    indent(out) << "break;" << endl;
+
+    indent_down();
+    out << endl;
+  }
+
+  indent(out) << "default:" << endl;
+  indent_up();
+  indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl;
+  indent_down();
+
+  scope_down(out);  // switch
+  scope_down(out, endl2);  // method
+}
+
+// Creates a generic isSet method that takes the field number as argument
+void t_dart_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // create the isSet method
+  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
+                 "value) and false otherwise" << endl;
+  indent(out) << "bool isSet(int fieldID)";
+  scope_up(out);
+
+  indent(out) << "switch (fieldID)";
+  scope_up(out);
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent_up();
+  indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl;
+  indent_down();
+
+  scope_down(out);  // switch
+  scope_down(out, endl2);  // method
+}
+
+/**
+ * Generates a set of Dart Bean boilerplate functions (setters, getters, etc.)
+ * for the given struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_dart_bean_boilerplate(ofstream& out,
+                                                    t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = get_member_name(field->get_name());
+    std::string cap_name = get_cap_name(field_name);
+
+    indent(out) << "// " << field_name << endl;
+
+    // Simple getter
+    generate_dart_doc(out, field);
+    indent(out) << type_name(type) << " get " << field_name << " => this._" << field_name << ";" << endl2;
+
+    // Simple setter
+    generate_dart_doc(out, field);
+    indent(out) << "set " << field_name << "(" << type_name(type) << " " << field_name << ")";
+    scope_up(out);
+    indent(out) << "this._" << field_name << " = " << field_name << ";" << endl;
+    generate_isset_set(out, field);
+    scope_down(out, endl2);
+
+    // isSet method
+    indent(out) << "bool is" << get_cap_name("set") << cap_name << "()";
+    if (type_can_be_null(type)) {
+      out << " => this." << field_name << " != null;" << endl2;
+    } else {
+      out << " => this.__isset_" << field_name << ";" << endl2;
+    }
+
+    // Unsetter
+    indent(out) << "unset" << cap_name << "()";
+    scope_up(out);
+    if (type_can_be_null(type)) {
+      indent(out) << "this." << field_name << " = null;" << endl;
+    } else {
+      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
+    }
+    scope_down(out, endl2);
+  }
+}
+
+/**
+ * Generates a toString() method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_dart_generator::generate_dart_struct_tostring(ofstream& out,
+                                                   t_struct* tstruct) {
+  indent(out) << "String toString()";
+  scope_up(out);
+
+  indent(out) << "StringBuffer ret = new StringBuffer(\""
+              << tstruct->get_name() << "(\");" << endl2;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ")";
+      scope_up(out);
+    }
+
+    t_field* field = (*f_iter);
+    std::string field_name = get_member_name(field->get_name());
+
+    if (!first) {
+      indent(out) << "ret.write(\", \");" << endl;
+    }
+    indent(out) << "ret.write(\"" << field_name << ":\");" << endl;
+    bool can_be_null = type_can_be_null(field->get_type());
+    if (can_be_null) {
+      indent(out) << "if (this." << field_name << " == null)";
+      scope_up(out);
+      indent(out) << "ret.write(\"null\");" << endl;
+      scope_down(out, " else");
+      scope_up(out);
+    }
+
+    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
+      indent(out) << "ret.write(\"BINARY\");" << endl;
+    } else if (field->get_type()->is_enum()) {
+      indent(out) << "String " << field_name << "_name = "
+                  << get_ttype_class_name(field->get_type())
+                  << ".VALUES_TO_NAMES[this." << field_name << "];" << endl;
+      indent(out) << "if (" << field_name << "_name != null)";
+      scope_up(out);
+      indent(out) << "ret.write(" << field_name << "_name);" << endl;
+      indent(out) << "ret.write(\" (\");" << endl;
+      scope_down(out);
+      indent(out) << "ret.write(this." << field_name << ");" << endl;
+      indent(out) << "if (" << field_name << "_name != null)";
+      scope_up(out);
+      indent(out) << "ret.write(\")\");" << endl;
+      scope_down(out);
+    } else {
+      indent(out) << "ret.write(this." << field_name << ");" << endl;
+    }
+
+    if (can_be_null) {
+      scope_down(out);
+    }
+    if (could_be_unset) {
+      scope_down(out);
+    }
+
+    out << endl;
+    first = false;
+  }
+
+  indent(out) << "ret.write(\")\");" << endl2;
+
+  indent(out) << "return ret.toString();" << endl;
+
+  scope_down(out, endl2);
+}
+
+/**
+ * Returns a string with the dart representation of the given thrift type
+ * (e.g. for the type struct it returns "TType.STRUCT")
+ */
+std::string t_dart_generator::get_dart_type_string(t_type* type) {
+  if (type->is_list()) {
+    return "TType.LIST";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_typedef()) {
+    return get_dart_type_string(((t_typedef*)type)->get_type());
+  } else if (type->is_base_type()) {
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_VOID:
+      return "TType.VOID";
+      break;
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+      break;
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+      break;
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+      break;
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+      break;
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+      break;
+    default:
+      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
+                               + "\" passed to t_dart_generator::get_dart_type_string!");
+      break; // This should never happen!
+    }
+  } else {
+    throw std::runtime_error(
+        "Unknown thrift type \"" + type->get_name()
+        + "\" passed to t_dart_generator::get_dart_type_string!"); // This should never happen!
+  }
+}
+
+void t_dart_generator::generate_service(t_service* tservice) {
+  string file_name = get_file_name(service_name_);
+  string f_service_name = src_dir_ + "/" + file_name + ".dart";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << dart_library(file_name) << endl;
+  f_service_ << service_imports() << dart_thrift_imports() << endl;
+  f_service_ << endl;
+
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+
+  f_service_.close();
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_dart_generator::generate_service_interface(t_service* tservice) {
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends_iface = " extends " + get_ttype_class_name(tservice->get_extends());
+  }
+
+  generate_dart_doc(f_service_, tservice);
+
+  string class_name = service_name_;
+  export_class_to_library(get_file_name(service_name_), class_name);
+  indent(f_service_) << "abstract class " << class_name << extends_iface;
+  scope_up(f_service_);
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << endl;
+    generate_dart_doc(f_service_, *f_iter);
+    indent(f_service_) << function_signature(*f_iter) << ";" << endl;
+  }
+
+  scope_down(f_service_, endl2);
+}
+
+/**
+ * Generates structs for all the service args and return types
+ *
+ * @param tservice The service
+ */
+void t_dart_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_dart_struct_definition(f_service_, ts, false, false);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_dart_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = get_ttype_class_name(tservice->get_extends());
+    extends_client = " extends " + extends + "Client";
+  }
+
+  string class_name = service_name_ + "Client";
+  export_class_to_library(get_file_name(service_name_), class_name);
+  indent(f_service_) << "class " << class_name << extends_client
+                     << " implements " << service_name_;
+  scope_up(f_service_);
+  f_service_ << endl;
+
+  indent(f_service_) << class_name << "(TProtocol iprot, [TProtocol oprot = null])";
+
+  if (!extends.empty()) {
+    indent_up();
+    f_service_ << endl;
+    indent(f_service_) << ": super(iprot, oprot);" << endl;
+    indent_down();
+  } else {
+    scope_up(f_service_);
+    indent(f_service_) << "_iprot = iprot;" << endl;
+    indent(f_service_) << "_oprot = (oprot == null) ? iprot : oprot;" << endl;
+    scope_down(f_service_);
+  }
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    indent(f_service_) << "TProtocol _iprot;" << endl2;
+    indent(f_service_) << "TProtocol get iprot => _iprot;" << endl2;
+    indent(f_service_) << "TProtocol _oprot;" << endl2;
+    indent(f_service_) << "TProtocol get oprot => _oprot;" << endl2;
+    indent(f_service_) << "int _seqid = 0;" << endl2;
+    indent(f_service_) << "int get seqid => _seqid;" << endl2;
+    indent(f_service_) << "int nextSeqid() => ++_seqid;" << endl2;
+  }
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    // Open function
+    indent(f_service_) << function_signature(*f_iter) << " async";
+    scope_up(f_service_);
+
+    // Get the struct of function call params
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    string argsname = get_args_class_name((*f_iter)->get_name());
+    vector<t_field*>::const_iterator fld_iter;
+    const vector<t_field*>& fields = arg_struct->get_members();
+
+    // Serialize the request
+    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << (*f_iter)->get_name() << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
+               << ", nextSeqid()));" << endl;
+    indent(f_service_) << argsname << " args = new " << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      string arg_field_name = get_member_name((*fld_iter)->get_name());
+      indent(f_service_) << "args." << arg_field_name << " = "
+                 << arg_field_name << ";" << endl;
+    }
+
+    indent(f_service_) << "args.write(oprot);" << endl;
+    indent(f_service_) << "oprot.writeMessageEnd();" << endl2;
+
+    indent(f_service_) << "await oprot.transport.flush();" << endl2;
+
+    if (!(*f_iter)->is_oneway()) {
+      indent(f_service_) << "TMessage msg = iprot.readMessageBegin();" << endl;
+      indent(f_service_) << "if (msg.type == TMessageType.EXCEPTION)";
+      scope_up(f_service_);
+      indent(f_service_) << "TApplicationError error = TApplicationError.read(iprot);" << endl;
+      indent(f_service_) << "iprot.readMessageEnd();" << endl;
+      indent(f_service_) << "throw error;" << endl;
+      scope_down(f_service_, endl2);
+
+      string result_class = get_result_class_name((*f_iter)->get_name());
+      indent(f_service_) << result_class << " result = new " << result_class << "();" << endl;
+      indent(f_service_) << "result.read(iprot);" << endl;
+      indent(f_service_) << "iprot.readMessageEnd();" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "if (result." << generate_isset_check("success") << ")";
+        scope_up(f_service_);
+        indent(f_service_) << "return result.success;" << endl;
+        scope_down(f_service_, endl2);
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        string result_field_name = get_member_name((*x_iter)->get_name());
+        indent(f_service_) << "if (result." << result_field_name << " != null)";
+        scope_up(f_service_);
+        indent(f_service_) << "throw result." << result_field_name << ";" << endl;
+        scope_down(f_service_);
+      }
+
+      // If you get here it's an exception, unless a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return;" << endl;
+      } else {
+        indent(f_service_) << "throw new TApplicationError(TApplicationErrorType.MISSING_RESULT, \""
+                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
+      }
+    }
+
+    scope_down(f_service_, endl2);
+  }
+
+  scope_down(f_service_, endl2);
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_dart_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // typedef
+  indent(f_service_) << "typedef void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" << endl2;
+
+  // Extends stuff
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = get_ttype_class_name(tservice->get_extends());
+    extends_processor = " extends " + extends + "Processor";
+  }
+
+  // Generate the header portion
+  string class_name =  service_name_ + "Processor";
+  export_class_to_library(get_file_name(service_name_), class_name);
+  indent(f_service_) << "class " << class_name << extends_processor << " implements TProcessor";
+  scope_up(f_service_);
+
+  indent(f_service_) << class_name << "(" << service_name_ << " iface)";
+  if (!extends.empty()) {
+    indent_up();
+    f_service_ << endl;
+    indent(f_service_) << ": super(iface)";
+    indent_down();
+  }
+  scope_up(f_service_);
+
+  if (extends.empty()) {
+    indent(f_service_) << "iface_ = iface;" << endl;
+  }
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent(f_service_) << "PROCESS_MAP[\"" << (*f_iter)->get_name()
+               << "\"] = " << get_member_name((*f_iter)->get_name()) << ";" << endl;
+  }
+  scope_down(f_service_, endl2);
+
+  indent(f_service_) << service_name_ << " iface_;" << endl;
+
+  if (extends.empty()) {
+    indent(f_service_) << "final Map<String, ProcessFunction> PROCESS_MAP = {};" << endl;
+  }
+
+  f_service_ << endl;
+
+  // Generate the server implementation
+  indent(f_service_) << "bool process(TProtocol iprot, TProtocol oprot)";
+  scope_up(f_service_);
+  indent(f_service_) << "TMessage msg = iprot.readMessageBegin();" << endl;
+  indent(f_service_) << "ProcessFunction fn = PROCESS_MAP[msg.name];" << endl;
+  indent(f_service_) << "if (fn == null)";
+  scope_up(f_service_);
+  indent(f_service_) << "TProtocolUtil.skip(iprot, TType.STRUCT);" << endl;
+  indent(f_service_) << "iprot.readMessageEnd();" << endl;
+  indent(f_service_) << "TApplicationError x = new TApplicationError(TApplicationErrorType.UNKNOWN_METHOD, "
+         "\"Invalid method name: '\"+msg.name+\"'\");" << endl;
+  indent(f_service_) << "oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl;
+  indent(f_service_) << "x.write(oprot);" << endl;
+  indent(f_service_) << "oprot.writeMessageEnd();" << endl;
+  indent(f_service_) << "oprot.transport.flush();" << endl;
+  indent(f_service_) << "return true;" << endl;
+  scope_down(f_service_);
+  indent(f_service_) << "fn(msg.seqid, iprot, oprot);" << endl;
+  indent(f_service_) << "return true;" << endl;
+  scope_down(f_service_, endl2); // process function
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  scope_down(f_service_, endl2); // class
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_dart_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  t_struct result(program_, get_result_class_name(tfunction->get_name()));
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_dart_struct_definition(f_service_, &result, false, true);
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_dart_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+
+  bool await_result = (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void());
+
+  indent(f_service_) << get_member_name(tfunction->get_name()) << "(int seqid, TProtocol iprot, TProtocol oprot)";
+  if (await_result) {
+    f_service_ << " async";
+  }
+  scope_up(f_service_);
+
+  string argsname = get_args_class_name(tfunction->get_name());
+  string resultname = get_result_class_name(tfunction->get_name());
+
+  indent(f_service_) << argsname << " args = new " << argsname << "();" << endl;
+  indent(f_service_) << "args.read(iprot);" << endl;
+  indent(f_service_) << "iprot.readMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  if (!tfunction->is_oneway()) {
+    indent(f_service_) << resultname << " result = new " << resultname << "();" << endl;
+  }
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    indent(f_service_) << "try";
+    scope_up(f_service_);
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (await_result) {
+    f_service_ << "result.success = await ";
+  }
+  f_service_ << "iface_." << get_member_name(tfunction->get_name()) << "(";
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << get_member_name((*f_iter)->get_name());
+  }
+  f_service_ << ");" << endl;
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      string result_field_name = get_member_name((*x_iter)->get_name());
+      scope_down(f_service_, "");
+      f_service_ << " on " << type_name((*x_iter)->get_type())
+              << " catch(" << result_field_name << ")";
+      scope_up(f_service_);
+      if (!tfunction->is_oneway()) {
+        indent(f_service_) << "result." << result_field_name << " = "
+                   << result_field_name << ";" << endl;
+      }
+    }
+    scope_down(f_service_, " ");
+    f_service_ << "catch (th)";
+    scope_up(f_service_);
+    indent(f_service_) << "// Internal error" << endl;
+    indent(f_service_) << "TApplicationError x = new "
+               "TApplicationError(TApplicationErrorType.INTERNAL_ERROR, \"Internal error processing "
+               << tfunction->get_name() << "\");" << endl;
+    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.EXCEPTION, seqid));" << endl;
+    indent(f_service_) << "x.write(oprot);" << endl;
+    indent(f_service_) << "oprot.writeMessageEnd();" << endl;
+    indent(f_service_) << "oprot.transport.flush();" << endl;
+    indent(f_service_) << "return;" << endl;
+    scope_down(f_service_);
+  }
+
+  if (tfunction->is_oneway()) {
+    indent(f_service_) << "return;" << endl;
+  } else {
+    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.REPLY, seqid));" << endl;
+    indent(f_service_) << "result.write(oprot);" << endl;
+    indent(f_service_) << "oprot.writeMessageEnd();" << endl;
+    indent(f_service_) << "oprot.transport.flush();" << endl;
+  }
+
+  scope_down(f_service_, endl2);
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param prefix The variable name or container for this field
+ */
+void t_dart_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+  string field_name = get_member_name(tfield->get_name());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + field_name;
+  }
+
+  string name = prefix + field_name;
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    indent(out) << name << " = iprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "readBinary();";
+        } else {
+          out << "readString();";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool();";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte();";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16();";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32();";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64();";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble();";
+        break;
+      default:
+        throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32();";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           field_name.c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, invokes read()
+ */
+void t_dart_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  indent(out) << prefix << " = new " << type_name(tstruct) << "();" << endl;
+  indent(out) << prefix << ".read(iprot);" << endl;
+}
+
+/**
+ * Deserializes a container by reading its size and then iterating
+ */
+void t_dart_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  indent(out);
+  scope_up(out, "");
+
+  string obj;
+
+  if (ttype->is_map()) {
+    obj = tmp("_map");
+  } else if (ttype->is_set()) {
+    obj = tmp("_set");
+  } else if (ttype->is_list()) {
+    obj = tmp("_list");
+  }
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "TMap " << obj << " = iprot.readMapBegin();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "TSet " << obj << " = iprot.readSetBegin();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "TList " << obj << " = iprot.readListBegin();" << endl;
+  }
+
+  indent(out) << prefix << " = new " << type_name(ttype) << "();" << endl;
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".length"
+              << "; "
+              << "++" << i << ")";
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "iprot.readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot.readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "iprot.readListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_dart_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey) << endl;
+  indent(out) << declare_field(&fval) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
+}
+
+/**
+ * Deserializes a set element
+ */
+void t_dart_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
+}
+
+/**
+ * Deserializes a list element
+ */
+void t_dart_generator::generate_deserialize_list_element(ofstream& out,
+                                                        t_list* tlist,
+                                                        string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_dart_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+  string field_name = get_member_name(tfield->get_name());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + field_name;
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + field_name);
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + field_name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = prefix + field_name;
+    indent(out) << "oprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "writeBinary(" << name << ");";
+        } else {
+          out << "writeString(" << name << ");";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ");";
+        break;
+      default:
+        throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ");";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           field_name.c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_dart_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << prefix << ".write(oprot);" << endl;
+}
+
+/**
+ * Serializes a container by writing its size then the elements.
+ *
+ * @param ttype  The type of container
+ * @param prefix String prefix for fields
+ */
+void t_dart_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  indent(out);
+  scope_up(out, "");
+
+  if (ttype->is_map()) {
+    string iter = tmp("_key");
+    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix << ".length));"
+                << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                << ", " << prefix << ".length));" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListBegin(new TList("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
+                << endl;
+  }
+
+  string iter = tmp("elem");
+  if (ttype->is_map()) {
+    indent(out) << "for (var " << iter << " in " << prefix << ".keys)";
+  } else if (ttype->is_set() || ttype->is_list()) {
+    indent(out) << "for (var " << iter << " in " << prefix << ")";
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ */
+void t_dart_generator::generate_serialize_map_element(ofstream& out,
+                                                     t_map* tmap,
+                                                     string iter,
+                                                     string map) {
+  t_field kfield(tmap->get_key_type(), iter);
+  generate_serialize_field(out, &kfield, "");
+  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
+  generate_serialize_field(out, &vfield, "");
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_dart_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_dart_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Returns a Dart type name
+ *
+ * @param ttype The type
+ * @return Dart type name, i.e. Map<Key, Value>
+ */
+string t_dart_generator::type_name(t_type* ttype) {
+  ttype = get_true_type(ttype);
+
+  if (ttype->is_base_type()) {
+    return base_type_name((t_base_type*)ttype);
+  } else if (ttype->is_enum()) {
+    return "int";
+  } else if (ttype->is_map()) {
+    t_map* tmap = (t_map*)ttype;
+    return "Map<" + type_name(tmap->get_key_type()) + ", "
+                  + type_name(tmap->get_val_type()) + ">";
+  } else if (ttype->is_set()) {
+    t_set* tset = (t_set*)ttype;
+    return "Set<" + type_name(tset->get_elem_type()) + ">";
+  } else if (ttype->is_list()) {
+    t_list* tlist = (t_list*)ttype;
+    return "List<" + type_name(tlist->get_elem_type()) + ">";
+  }
+
+  return get_ttype_class_name(ttype);
+}
+
+/**
+ * Returns the Dart type that corresponds to the thrift type.
+ *
+ * @param tbase The base type
+ */
+string t_dart_generator::base_type_name(t_base_type* type) {
+  t_base_type::t_base tbase = type->get_base();
+
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (type->is_binary()) {
+      return "Uint8List";
+    } else {
+      return "String";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "bool";
+  case t_base_type::TYPE_I8:
+  case t_base_type::TYPE_I16:
+  case t_base_type::TYPE_I32:
+  case t_base_type::TYPE_I64:
+    return "int";
+  case t_base_type::TYPE_DOUBLE:
+    return "double";
+  default:
+    throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase);
+  }
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ */
+string t_dart_generator::declare_field(t_field* tfield, bool init) {
+  string field_name = get_member_name(tfield->get_name());
+  string result = type_name(tfield->get_type()) + " " + field_name;
+  if (init) {
+    t_type* ttype = get_true_type(tfield->get_type());
+    if (ttype->is_base_type() && tfield->get_value() != NULL) {
+      ofstream dummy;
+      result += " = " + render_const_value(dummy, field_name, ttype, tfield->get_value());
+    } else if (ttype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "NO T_VOID CONSTRUCT";
+      case t_base_type::TYPE_STRING:
+        result += " = null";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+        result += " = 0";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = 0.0";
+        break;
+      }
+
+    } else if (ttype->is_enum()) {
+      result += " = 0";
+    } else if (ttype->is_container()) {
+      result += " = new " + type_name(ttype) + "()";
+    } else {
+      result += " = new " + type_name(ttype) + "()";
+      ;
+    }
+  }
+  return result + ";";
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_dart_generator::function_signature(t_function* tfunction) {
+  std::string arguments = argument_list(tfunction->get_arglist());
+
+  std::string returntype;
+  if (tfunction->get_returntype()->is_void()) {
+    returntype = "Future";
+  } else {
+    returntype = "Future<" + type_name(tfunction->get_returntype()) + ">";
+  }
+
+  std::string result = returntype + " " + get_member_name(tfunction->get_name()) +
+                       "(" + arguments + ")";
+  return result;
+}
+
+/**
+ * Renders a comma separated field list, with type names
+ */
+string t_dart_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    string field_name = get_member_name((*f_iter)->get_name());
+    result += type_name((*f_iter)->get_type()) + " " + field_name;
+  }
+  return result;
+}
+
+/**
+ * Converts the parse type to a C++ enum string for the given type.
+ */
+string t_dart_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_list()) {
+    return "TType.LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+std::string t_dart_generator::init_value(t_field* field) {
+  // Do not initialize optional fields
+  if (field->get_req() == t_field::T_OPTIONAL) {
+    return "";
+  }
+
+  t_type* ttype = field->get_type();
+
+  // Get the actual type for a typedef
+  if (ttype->is_typedef()) {
+    ttype = ((t_typedef*)ttype)->get_type();
+  }
+
+  // Only consider base types for default initialization
+  if (!ttype->is_base_type()) {
+    return "";
+  }
+  t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
+
+  // Initialize bools, ints, and doubles with sane defaults
+  string result;
+  switch (tbase) {
+  case t_base_type::TYPE_BOOL:
+    result = " = false";
+    break;
+  case t_base_type::TYPE_I8:
+  case t_base_type::TYPE_I16:
+  case t_base_type::TYPE_I32:
+  case t_base_type::TYPE_I64:
+    result = " = 0";
+    break;
+  case t_base_type::TYPE_DOUBLE:
+    result = " = 0.0";
+    break;
+  case t_base_type::TYPE_VOID:
+  case t_base_type::TYPE_STRING:
+    result = "";
+    break;
+  }
+
+  return result;
+}
+
+std::string t_dart_generator::get_cap_name(std::string name) {
+  name[0] = toupper(name[0]);
+  return name;
+}
+
+std::string t_dart_generator::get_member_name(std::string name) {
+  name[0] = tolower(name[0]);
+  return name;
+}
+
+std::string t_dart_generator::get_args_class_name(std::string name) {
+  return name + "_args";
+}
+
+std::string t_dart_generator::get_result_class_name(std::string name) {
+  return name + "_result";
+}
+
+std::string t_dart_generator::get_file_name(std::string name) {
+  // e.g. change APIForFileIO to api_for_file_io
+
+  string ret;
+  const char* tmp = name.c_str();
+  bool is_prev_lc = true;
+  bool is_current_lc = tmp[0] == tolower(tmp[0]);
+  bool is_next_lc = false;
+
+  for (unsigned int i = 0; i < name.length(); i++) {
+    char lc = tolower(tmp[i]);
+
+    if (i == name.length() - 1) {
+      is_next_lc = false;
+    } else {
+      is_next_lc = (tmp[i+1] == tolower(tmp[i+1]));
+    }
+
+    if (i != 0 && !is_current_lc && (is_prev_lc || is_next_lc)) {
+      ret += "_";
+    }
+    ret += lc;
+
+    is_prev_lc = is_current_lc;
+    is_current_lc = is_next_lc;
+  }
+
+  return ret;
+}
+
+std::string t_dart_generator::get_constants_class_name(std::string name) {
+  // e.g. change my_great_model to MyGreatModelConstants
+  string ret;
+  const char* tmp = name.c_str();
+  bool is_prev_underscore = true;
+
+  for (unsigned int i = 0; i < name.length(); i++) {
+    if (tmp[i] == '_') {
+      is_prev_underscore = true;
+    } else {
+      if (is_prev_underscore) {
+        ret += toupper(tmp[i]);
+      } else {
+        ret += tmp[i];
+      }
+
+      is_prev_underscore = false;
+    }
+  }
+
+  return ret + "Constants";
+}
+
+string t_dart_generator::constant_name(string name) {
+  string constant_name;
+
+  bool is_first = true;
+  bool was_previous_char_upper = false;
+  for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
+    string::value_type character = (*iter);
+
+    bool is_upper = isupper(character);
+
+    if (is_upper && !is_first && !was_previous_char_upper) {
+      constant_name += '_';
+    }
+    constant_name += toupper(character);
+
+    is_first = false;
+    was_previous_char_upper = is_upper;
+  }
+
+  return constant_name;
+}
+
+/**
+ * Emits a doc comment if the provided object has a doc in Thrift
+ */
+void t_dart_generator::generate_dart_doc(ofstream& out, t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    generate_docstring_comment(out, "", "/// ", tdoc->get_doc(), "");
+  }
+}
+
+/**
+ * Emits a doc comment if the provided function object has a doc in Thrift
+ */
+void t_dart_generator::generate_dart_doc(ofstream& out, t_function* tfunction) {
+  if (tfunction->has_doc()) {
+    stringstream ss;
+    ss << tfunction->get_doc();
+    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+    vector<t_field*>::const_iterator p_iter;
+    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
+      t_field* p = *p_iter;
+      string field_name = get_member_name(p->get_name());
+      ss << "\n@param " << field_name;
+      if (p->has_doc()) {
+        ss << " " << p->get_doc();
+      }
+    }
+    generate_docstring_comment(out, "", "/// ", ss.str(), "");
+  }
+}
+
+std::string t_dart_generator::generate_isset_check(t_field* field) {
+  string field_name = get_member_name(field->get_name());
+  return generate_isset_check(field_name);
+}
+
+std::string t_dart_generator::generate_isset_check(std::string field_name) {
+  return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
+}
+
+void t_dart_generator::generate_isset_set(ofstream& out, t_field* field) {
+  if (!type_can_be_null(field->get_type())) {
+    string field_name = get_member_name(field->get_name());
+    indent(out) << "this.__isset_" << field_name << " = true;" << endl;
+  }
+}
+
+std::string t_dart_generator::get_ttype_class_name(t_type* ttype) {
+  if (program_ == ttype->get_program()) {
+    return ttype->get_name();
+  } else {
+    string named_import = "t_" + find_library_name(ttype->get_program());
+    return named_import + "." + ttype->get_name();
+  }
+}
+
+THRIFT_REGISTER_GENERATOR(
+    dart,
+    "Dart",
+    "    library_name:    Optional override for library name.\n"
+    "    library_prefix:  Generate code that can be used within an existing library.\n"
+    "                     Use a dot-separated string, e.g. \"my_parent_lib.src.gen\"\n"
+    "    pubspec_lib:     Optional override for thrift lib dependency in pubspec.yaml,\n"
+    "                     e.g. \"thrift: 0.x.x\".  Use a pipe delimiter to separate lines,\n"
+    "                     e.g. \"thrift:|  git:|    url: git@foo.com\"\n"
+)


[55/55] [abbrv] thrift git commit: THRIFT-3929 php namespace remove tail "\\"

Posted by ns...@apache.org.
THRIFT-3929 php namespace remove tail "\\"

This closes #1089


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/346e2314
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/346e2314
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/346e2314

Branch: refs/heads/master
Commit: 346e23149573dc00da5eb7f415057b0266230010
Parents: 22ec64f
Author: Robert Lu <ro...@gmail.com>
Authored: Thu Sep 15 10:48:16 2016 +0800
Committer: Nobuaki Sukegawa <ns...@apache.org>
Committed: Mon Sep 26 01:42:03 2016 +0900

----------------------------------------------------------------------
 compiler/cpp/src/thrift/generate/t_php_generator.cc | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/346e2314/compiler/cpp/src/thrift/generate/t_php_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_php_generator.cc b/compiler/cpp/src/thrift/generate/t_php_generator.cc
index ba52781..515e165 100644
--- a/compiler/cpp/src/thrift/generate/t_php_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_php_generator.cc
@@ -227,11 +227,14 @@ public:
     return (nsglobal_.size() ? NSGLOBAL_AB : NSGLOBAL_B) + (ns.size() ? (ns + "\\") : "");
   }
 
-  // setting the namespace of a file: my\namespace
+  // return the namespace of a file:
+  // global\ns\sub\ns or global\ns or sub\ns
   string php_namespace_suffix(const t_program* p) {
     string ns = php_namespace_base(p);
 
-    return (nsglobal_.size() ? NSGLOBAL_B : NSGLOBAL) + ns;
+    return NSGLOBAL
+      + (ns.size() && NSGLOBAL.size() ? "\\" : "")
+      + ns;
   }
 
   // add a directory to already existing namespace


[47/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_cpp_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
deleted file mode 100644
index 6c04899..0000000
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ /dev/null
@@ -1,4374 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <cassert>
-
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <sys/stat.h>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostream;
-using std::string;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * C++ code generator. This is legitimacy incarnate.
- *
- */
-class t_cpp_generator : public t_oop_generator {
-public:
-  t_cpp_generator(t_program* program,
-                  const std::map<std::string, std::string>& parsed_options,
-                  const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-
-    gen_pure_enums_ = false;
-    use_include_prefix_ = false;
-    gen_cob_style_ = false;
-    gen_no_client_completion_ = false;
-    gen_no_default_operators_ = false;
-    gen_templates_ = false;
-    gen_templates_only_ = false;
-    gen_moveable_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("pure_enums") == 0) {
-        gen_pure_enums_ = true;
-      } else if( iter->first.compare("include_prefix") == 0) {
-        use_include_prefix_ = true;
-      } else if( iter->first.compare("cob_style") == 0) {
-        gen_cob_style_ = true;
-      } else if( iter->first.compare("no_client_completion") == 0) {
-        gen_no_client_completion_ = true;
-      } else if( iter->first.compare("no_default_operators") == 0) {
-        gen_no_default_operators_ = true;
-      } else if( iter->first.compare("templates") == 0) {
-        gen_templates_ = true;
-        gen_templates_only_ = (iter->second == "only");
-      } else if( iter->first.compare("moveable_types") == 0) {
-        gen_moveable_ = true;
-      } else {
-        throw "unknown option cpp:" + iter->first; 
-      }
-    }
-
-    out_dir_base_ = "gen-cpp";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_forward_declaration(t_struct* tstruct);
-  void generate_struct(t_struct* tstruct) { generate_cpp_struct(tstruct, false); }
-  void generate_xception(t_struct* txception) { generate_cpp_struct(txception, true); }
-  void generate_cpp_struct(t_struct* tstruct, bool is_exception);
-
-  void generate_service(t_service* tservice);
-
-  void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
-  std::string render_const_value(std::ofstream& out,
-                                 std::string name,
-                                 t_type* type,
-                                 t_const_value* value);
-
-  void generate_struct_declaration(std::ofstream& out,
-                                   t_struct* tstruct,
-                                   bool is_exception = false,
-                                   bool pointers = false,
-                                   bool read = true,
-                                   bool write = true,
-                                   bool swap = false,
-                                   bool is_user_struct = false);
-  void generate_struct_definition(std::ofstream& out,
-                                  std::ofstream& force_cpp_out,
-                                  t_struct* tstruct,
-                                  bool setters = true);
-  void generate_copy_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_move_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_constructor_helper(std::ofstream& out,
-                                   t_struct* tstruct,
-                                   bool is_excpetion,
-                                   bool is_move);
-  void generate_assignment_operator(std::ofstream& out, t_struct* tstruct);
-  void generate_move_assignment_operator(std::ofstream& out, t_struct* tstruct);
-  void generate_assignment_helper(std::ofstream& out, t_struct* tstruct, bool is_move);
-  void generate_struct_reader(std::ofstream& out, t_struct* tstruct, bool pointers = false);
-  void generate_struct_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
-  void generate_struct_result_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
-  void generate_struct_swap(std::ofstream& out, t_struct* tstruct);
-  void generate_struct_print_method(std::ofstream& out, t_struct* tstruct);
-  void generate_exception_what_method(std::ofstream& out, t_struct* tstruct);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_interface(t_service* tservice, string style);
-  void generate_service_interface_factory(t_service* tservice, string style);
-  void generate_service_null(t_service* tservice, string style);
-  void generate_service_multiface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice, string style);
-  void generate_service_processor(t_service* tservice, string style);
-  void generate_service_skeleton(t_service* tservice);
-  void generate_process_function(t_service* tservice,
-                                 t_function* tfunction,
-                                 string style,
-                                 bool specialized = false);
-  void generate_function_helpers(t_service* tservice, t_function* tfunction);
-  void generate_service_async_skeleton(t_service* tservice);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  std::string suffix = "");
-
-  void generate_deserialize_struct(std::ofstream& out,
-                                   t_struct* tstruct,
-                                   std::string prefix = "",
-                                   bool pointer = false);
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix,
-                                         bool push_back,
-                                         std::string index);
-
-  void generate_serialize_field(std::ofstream& out,
-                                t_field* tfield,
-                                std::string prefix = "",
-                                std::string suffix = "");
-
-  void generate_serialize_struct(std::ofstream& out,
-                                 t_struct* tstruct,
-                                 std::string prefix = "",
-                                 bool pointer = false);
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out, t_map* tmap, std::string iter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  void generate_function_call(ostream& out,
-                              t_function* tfunction,
-                              string target,
-                              string iface,
-                              string arg_prefix);
-  /*
-   * Helper rendering functions
-   */
-
-  std::string namespace_prefix(std::string ns);
-  std::string namespace_open(std::string ns);
-  std::string namespace_close(std::string ns);
-  std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false);
-  std::string base_type_name(t_base_type::t_base tbase);
-  std::string declare_field(t_field* tfield,
-                            bool init = false,
-                            bool pointer = false,
-                            bool constant = false,
-                            bool reference = false);
-  std::string function_signature(t_function* tfunction,
-                                 std::string style,
-                                 std::string prefix = "",
-                                 bool name_params = true);
-  std::string cob_function_signature(t_function* tfunction,
-                                     std::string prefix = "",
-                                     bool name_params = true);
-  std::string argument_list(t_struct* tstruct, bool name_params = true, bool start_comma = false);
-  std::string type_to_enum(t_type* ttype);
-
-  void generate_enum_constant_list(std::ofstream& f,
-                                   const vector<t_enum_value*>& constants,
-                                   const char* prefix,
-                                   const char* suffix,
-                                   bool include_values);
-
-  void generate_struct_ostream_operator(std::ofstream& f, t_struct* tstruct);
-  void generate_struct_print_method_decl(std::ofstream& f, t_struct* tstruct);
-  void generate_exception_what_method_decl(std::ofstream& f,
-                                           t_struct* tstruct,
-                                           bool external = false);
-
-  bool is_reference(t_field* tfield) { return tfield->get_reference(); }
-
-  bool is_complex_type(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
-           || (ttype->is_base_type()
-               && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));
-  }
-
-  void set_use_include_prefix(bool use_include_prefix) { use_include_prefix_ = use_include_prefix; }
-
-private:
-  /**
-   * Returns the include prefix to use for a file generated by program, or the
-   * empty string if no include prefix should be used.
-   */
-  std::string get_include_prefix(const t_program& program) const;
-
-  /**
-   * True if we should generate pure enums for Thrift enums, instead of wrapper classes.
-   */
-  bool gen_pure_enums_;
-
-  /**
-   * True if we should generate templatized reader/writer methods.
-   */
-  bool gen_templates_;
-
-  /**
-   * True iff we should generate process function pointers for only templatized
-   * reader/writer methods.
-   */
-  bool gen_templates_only_;
-
-  /**
-   * True if we should generate move constructors & assignment operators.
-   */
-  bool gen_moveable_;
-
-  /**
-   * True iff we should use a path prefix in our #include statements for other
-   * thrift-generated header files.
-   */
-  bool use_include_prefix_;
-
-  /**
-   * True if we should generate "Continuation OBject"-style classes as well.
-   */
-  bool gen_cob_style_;
-
-  /**
-   * True if we should omit calls to completion__() in CobClient class.
-   */
-  bool gen_no_client_completion_;
-
-  /**
-   * True if we should omit generating the default opeartors ==, != and <.
-   */
-  bool gen_no_default_operators_;
-
-  /**
-   * Strings for namespace, computed once up front then used directly
-   */
-
-  std::string ns_open_;
-  std::string ns_close_;
-
-  /**
-   * File streams, stored here to avoid passing them as parameters to every
-   * function.
-   */
-
-  std::ofstream f_types_;
-  std::ofstream f_types_impl_;
-  std::ofstream f_types_tcc_;
-  std::ofstream f_header_;
-  std::ofstream f_service_;
-  std::ofstream f_service_tcc_;
-
-  // The ProcessorGenerator is used to generate parts of the code,
-  // so it needs access to many of our protected members and methods.
-  //
-  // TODO: The code really should be cleaned up so that helper methods for
-  // writing to the output files are separate from the generator classes
-  // themselves.
-  friend class ProcessorGenerator;
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- */
-void t_cpp_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  // Make output file
-  string f_types_name = get_out_dir() + program_name_ + "_types.h";
-  f_types_.open(f_types_name.c_str());
-
-  string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp";
-  f_types_impl_.open(f_types_impl_name.c_str());
-
-  if (gen_templates_) {
-    // If we don't open the stream, it appears to just discard data,
-    // which is fine.
-    string f_types_tcc_name = get_out_dir() + program_name_ + "_types.tcc";
-    f_types_tcc_.open(f_types_tcc_name.c_str());
-  }
-
-  // Print header
-  f_types_ << autogen_comment();
-  f_types_impl_ << autogen_comment();
-  f_types_tcc_ << autogen_comment();
-
-  // Start ifndef
-  f_types_ << "#ifndef " << program_name_ << "_TYPES_H" << endl << "#define " << program_name_
-           << "_TYPES_H" << endl << endl;
-  f_types_tcc_ << "#ifndef " << program_name_ << "_TYPES_TCC" << endl << "#define " << program_name_
-               << "_TYPES_TCC" << endl << endl;
-
-  // Include base types
-  f_types_ << "#include <iosfwd>" << endl
-           << endl
-           << "#include <thrift/Thrift.h>" << endl
-           << "#include <thrift/TApplicationException.h>" << endl
-           << "#include <thrift/TBase.h>" << endl
-           << "#include <thrift/protocol/TProtocol.h>" << endl
-           << "#include <thrift/transport/TTransport.h>" << endl
-           << endl;
-  // Include C++xx compatibility header
-  f_types_ << "#include <thrift/cxxfunctional.h>" << endl;
-
-  // Include other Thrift includes
-  const vector<t_program*>& includes = program_->get_includes();
-  for (size_t i = 0; i < includes.size(); ++i) {
-    f_types_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name()
-             << "_types.h\"" << endl;
-
-    // XXX(simpkins): If gen_templates_ is enabled, we currently assume all
-    // included files were also generated with templates enabled.
-    f_types_tcc_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name()
-                 << "_types.tcc\"" << endl;
-  }
-  f_types_ << endl;
-
-  // Include custom headers
-  const vector<string>& cpp_includes = program_->get_cpp_includes();
-  for (size_t i = 0; i < cpp_includes.size(); ++i) {
-    if (cpp_includes[i][0] == '<') {
-      f_types_ << "#include " << cpp_includes[i] << endl;
-    } else {
-      f_types_ << "#include \"" << cpp_includes[i] << "\"" << endl;
-    }
-  }
-  f_types_ << endl;
-
-  // Include the types file
-  f_types_impl_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
-                << "_types.h\"" << endl << endl;
-  f_types_tcc_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
-               << "_types.h\"" << endl << endl;
-
-  // The swap() code needs <algorithm> for std::swap()
-  f_types_impl_ << "#include <algorithm>" << endl;
-  // for operator<<
-  f_types_impl_ << "#include <ostream>" << endl << endl;
-  f_types_impl_ << "#include <thrift/TToString.h>" << endl << endl;
-
-  // Open namespace
-  ns_open_ = namespace_open(program_->get_namespace("cpp"));
-  ns_close_ = namespace_close(program_->get_namespace("cpp"));
-
-  f_types_ << ns_open_ << endl << endl;
-
-  f_types_impl_ << ns_open_ << endl << endl;
-
-  f_types_tcc_ << ns_open_ << endl << endl;
-}
-
-/**
- * Closes the output files.
- */
-void t_cpp_generator::close_generator() {
-  // Close namespace
-  f_types_ << ns_close_ << endl << endl;
-  f_types_impl_ << ns_close_ << endl;
-  f_types_tcc_ << ns_close_ << endl << endl;
-
-  // Include the types.tcc file from the types header file,
-  // so clients don't have to explicitly include the tcc file.
-  // TODO(simpkins): Make this a separate option.
-  if (gen_templates_) {
-    f_types_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
-             << "_types.tcc\"" << endl << endl;
-  }
-
-  // Close ifndef
-  f_types_ << "#endif" << endl;
-  f_types_tcc_ << "#endif" << endl;
-
-  // Close output file
-  f_types_.close();
-  f_types_impl_.close();
-  f_types_tcc_.close();
-}
-
-/**
- * Generates a typedef. This is just a simple 1-liner in C++
- *
- * @param ttypedef The type definition
- */
-void t_cpp_generator::generate_typedef(t_typedef* ttypedef) {
-  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " "
-           << ttypedef->get_symbolic() << ";" << endl << endl;
-}
-
-void t_cpp_generator::generate_enum_constant_list(std::ofstream& f,
-                                                  const vector<t_enum_value*>& constants,
-                                                  const char* prefix,
-                                                  const char* suffix,
-                                                  bool include_values) {
-  f << " {" << endl;
-  indent_up();
-
-  vector<t_enum_value*>::const_iterator c_iter;
-  bool first = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f << "," << endl;
-    }
-    indent(f) << prefix << (*c_iter)->get_name() << suffix;
-    if (include_values) {
-      f << " = " << (*c_iter)->get_value();
-    }
-  }
-
-  f << endl;
-  indent_down();
-  indent(f) << "};" << endl;
-}
-
-/**
- * Generates code for an enumerated type. In C++, this is essentially the same
- * as the thrift definition itself, using the enum keyword in C++.
- *
- * @param tenum The enumeration
- */
-void t_cpp_generator::generate_enum(t_enum* tenum) {
-  vector<t_enum_value*> constants = tenum->get_constants();
-
-  std::string enum_name = tenum->get_name();
-  if (!gen_pure_enums_) {
-    enum_name = "type";
-    f_types_ << indent() << "struct " << tenum->get_name() << " {" << endl;
-    indent_up();
-  }
-  f_types_ << indent() << "enum " << enum_name;
-
-  generate_enum_constant_list(f_types_, constants, "", "", true);
-
-  if (!gen_pure_enums_) {
-    indent_down();
-    f_types_ << "};" << endl;
-  }
-
-  f_types_ << endl;
-
-  /**
-     Generate a character array of enum names for debugging purposes.
-  */
-  std::string prefix = "";
-  if (!gen_pure_enums_) {
-    prefix = tenum->get_name() + "::";
-  }
-
-  f_types_impl_ << indent() << "int _k" << tenum->get_name() << "Values[] =";
-  generate_enum_constant_list(f_types_impl_, constants, prefix.c_str(), "", false);
-
-  f_types_impl_ << indent() << "const char* _k" << tenum->get_name() << "Names[] =";
-  generate_enum_constant_list(f_types_impl_, constants, "\"", "\"", false);
-
-  f_types_ << indent() << "extern const std::map<int, const char*> _" << tenum->get_name()
-           << "_VALUES_TO_NAMES;" << endl << endl;
-
-  f_types_impl_ << indent() << "const std::map<int, const char*> _" << tenum->get_name()
-                << "_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(" << constants.size() << ", _k"
-                << tenum->get_name() << "Values"
-                << ", _k" << tenum->get_name() << "Names), "
-                << "::apache::thrift::TEnumIterator(-1, NULL, NULL));" << endl << endl;
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_cpp_generator::generate_consts(std::vector<t_const*> consts) {
-  string f_consts_name = get_out_dir() + program_name_ + "_constants.h";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp";
-  ofstream f_consts_impl;
-  f_consts_impl.open(f_consts_impl_name.c_str());
-
-  // Print header
-  f_consts << autogen_comment();
-  f_consts_impl << autogen_comment();
-
-  // Start ifndef
-  f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_
-           << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program())
-           << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl;
-
-  f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_
-                << "_constants.h\"" << endl << endl << ns_open_ << endl << endl;
-
-  f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << "  "
-           << program_name_ << "Constants();" << endl << endl;
-  indent_up();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    string name = (*c_iter)->get_name();
-    t_type* type = (*c_iter)->get_type();
-    f_consts << indent() << type_name(type) << " " << name << ";" << endl;
-  }
-  indent_down();
-  f_consts << "};" << endl;
-
-  f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;"
-                << endl << endl << program_name_ << "Constants::" << program_name_
-                << "Constants() {" << endl;
-  indent_up();
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    print_const_value(f_consts_impl,
-                      (*c_iter)->get_name(),
-                      (*c_iter)->get_type(),
-                      (*c_iter)->get_value());
-  }
-  indent_down();
-  indent(f_consts_impl) << "}" << endl;
-
-  f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_
-           << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl;
-  f_consts.close();
-
-  f_consts_impl << endl << ns_close_ << endl << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-void t_cpp_generator::print_const_value(ofstream& out,
-                                        string name,
-                                        t_type* type,
-                                        t_const_value* value) {
-  type = get_true_type(type);
-  if (type->is_base_type()) {
-    string v2 = render_const_value(out, name, type, value);
-    indent(out) << name << " = " << v2 << ";" << endl << endl;
-  } else if (type->is_enum()) {
-    indent(out) << name << " = (" << type_name(type) << ")" << value->get_integer() << ";" << endl
-                << endl;
-  } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    bool is_nonrequired_field = false;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      is_nonrequired_field = false;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-          is_nonrequired_field = (*f_iter)->get_req() != t_field::T_REQUIRED;
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(out, name, field_type, v_iter->second);
-      indent(out) << name << "." << v_iter->first->get_string() << " = " << val << ";" << endl;
-      if (is_nonrequired_field) {
-        indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl;
-      }
-    }
-    out << endl;
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, name, ktype, v_iter->first);
-      string val = render_const_value(out, name, vtype, v_iter->second);
-      indent(out) << name << ".insert(std::make_pair(" << key << ", " << val << "));" << endl;
-    }
-    out << endl;
-  } else if (type->is_list()) {
-    t_type* etype = ((t_list*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      indent(out) << name << ".push_back(" << val << ");" << endl;
-    }
-    out << endl;
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, name, etype, *v_iter);
-      indent(out) << name << ".insert(" << val << ");" << endl;
-    }
-    out << endl;
-  } else {
-    throw "INVALID TYPE IN print_const_value: " + type->get_name();
-  }
-}
-
-/**
- *
- */
-string t_cpp_generator::render_const_value(ofstream& out,
-                                           string name,
-                                           t_type* type,
-                                           t_const_value* value) {
-  (void)name;
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << value->get_integer() << "LL";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << "(" << type_name(type) << ")" << value->get_integer();
-  } else {
-    string t = tmp("tmp");
-    indent(out) << type_name(type) << " " << t << ";" << endl;
-    print_const_value(out, t, type, value);
-    render << t;
-  }
-
-  return render.str();
-}
-
-void t_cpp_generator::generate_forward_declaration(t_struct* tstruct) {
-  // Forward declare struct def
-  f_types_ << indent() << "class " << tstruct->get_name() << ";" << endl << endl;
-}
-
-/**
- * Generates a struct definition for a thrift data type. This is a class
- * with data members and a read/write() function, plus a mirroring isset
- * inner class.
- *
- * @param tstruct The struct definition
- */
-void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) {
-  generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true);
-  generate_struct_definition(f_types_impl_, f_types_impl_, tstruct);
-
-  std::ofstream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_);
-  generate_struct_reader(out, tstruct);
-  generate_struct_writer(out, tstruct);
-  generate_struct_swap(f_types_impl_, tstruct);
-  generate_copy_constructor(f_types_impl_, tstruct, is_exception);
-  if (gen_moveable_) {
-    generate_move_constructor(f_types_impl_, tstruct, is_exception);
-  }
-  generate_assignment_operator(f_types_impl_, tstruct);
-  if (gen_moveable_) {
-    generate_move_assignment_operator(f_types_impl_, tstruct);
-  }
-  generate_struct_print_method(f_types_impl_, tstruct);
-  if (is_exception) {
-    generate_exception_what_method(f_types_impl_, tstruct);
-  }
-}
-
-void t_cpp_generator::generate_copy_constructor(ofstream& out,
-                                                t_struct* tstruct,
-                                                bool is_exception) {
-  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false);
-}
-
-void t_cpp_generator::generate_move_constructor(ofstream& out,
-                                                t_struct* tstruct,
-                                                bool is_exception) {
-  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true);
-}
-
-namespace {
-// Helper to convert a variable to rvalue, if move is enabled
-std::string maybeMove(std::string const& other, bool move) {
-  if (move) {
-    return "std::move(" + other + ")";
-  }
-  return other;
-}
-}
-
-void t_cpp_generator::generate_constructor_helper(ofstream& out,
-                                                  t_struct* tstruct,
-                                                  bool is_exception,
-                                                  bool is_move) {
-
-  std::string tmp_name = tmp("other");
-
-  indent(out) << tstruct->get_name() << "::" << tstruct->get_name();
-
-  if (is_move) {
-    out << "( " << tstruct->get_name() << "&& ";
-  } else {
-    out << "(const " << tstruct->get_name() << "& ";
-  }
-  out << tmp_name << ") ";
-  if (is_exception)
-    out << ": TException() ";
-  out << "{" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-
-  // eliminate compiler unused warning
-  if (members.empty())
-    indent(out) << "(void) " << tmp_name << ";" << endl;
-
-  vector<t_field*>::const_iterator f_iter;
-  bool has_nonrequired_fields = false;
-  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
-    if ((*f_iter)->get_req() != t_field::T_REQUIRED)
-      has_nonrequired_fields = true;
-    indent(out) << (*f_iter)->get_name() << " = "
-                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
-  }
-
-  if (has_nonrequired_fields) {
-    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
-  }
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_cpp_generator::generate_assignment_operator(ofstream& out, t_struct* tstruct) {
-  generate_assignment_helper(out, tstruct, /*is_move=*/false);
-}
-
-void t_cpp_generator::generate_move_assignment_operator(ofstream& out, t_struct* tstruct) {
-  generate_assignment_helper(out, tstruct, /*is_move=*/true);
-}
-
-void t_cpp_generator::generate_assignment_helper(ofstream& out, t_struct* tstruct, bool is_move) {
-  std::string tmp_name = tmp("other");
-
-  indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=(";
-
-  if (is_move) {
-    out << tstruct->get_name() << "&& ";
-  } else {
-    out << "const " << tstruct->get_name() << "& ";
-  }
-  out << tmp_name << ") {" << endl;
-
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-
-  // eliminate compiler unused warning
-  if (members.empty())
-    indent(out) << "(void) " << tmp_name << ";" << endl;
-
-  vector<t_field*>::const_iterator f_iter;
-  bool has_nonrequired_fields = false;
-  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
-    if ((*f_iter)->get_req() != t_field::T_REQUIRED)
-      has_nonrequired_fields = true;
-    indent(out) << (*f_iter)->get_name() << " = "
-                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
-  }
-  if (has_nonrequired_fields) {
-    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
-  }
-
-  indent(out) << "return *this;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-/**
- * Writes the struct declaration into the header file
- *
- * @param out Output stream
- * @param tstruct The struct
- */
-void t_cpp_generator::generate_struct_declaration(ofstream& out,
-                                                  t_struct* tstruct,
-                                                  bool is_exception,
-                                                  bool pointers,
-                                                  bool read,
-                                                  bool write,
-                                                  bool swap,
-                                                  bool is_user_struct) {
-  string extends = "";
-  if (is_exception) {
-    extends = " : public ::apache::thrift::TException";
-  } else {
-    if (is_user_struct && !gen_templates_) {
-      extends = " : public virtual ::apache::thrift::TBase";
-    }
-  }
-
-  // Get members
-  vector<t_field*>::const_iterator m_iter;
-  const vector<t_field*>& members = tstruct->get_members();
-
-  // Write the isset structure declaration outside the class. This makes
-  // the generated code amenable to processing by SWIG.
-  // We only declare the struct if it gets used in the class.
-
-  // Isset struct has boolean fields, but only for non-required fields.
-  bool has_nonrequired_fields = false;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if ((*m_iter)->get_req() != t_field::T_REQUIRED)
-      has_nonrequired_fields = true;
-  }
-
-  if (has_nonrequired_fields && (!pointers || read)) {
-
-    out << indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << endl;
-    indent_up();
-
-    indent(out) << "_" << tstruct->get_name() << "__isset() ";
-    bool first = true;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
-        continue;
-      }
-      string isSet = ((*m_iter)->get_value() != NULL) ? "true" : "false";
-      if (first) {
-        first = false;
-        out << ": " << (*m_iter)->get_name() << "(" << isSet << ")";
-      } else {
-        out << ", " << (*m_iter)->get_name() << "(" << isSet << ")";
-      }
-    }
-    out << " {}" << endl;
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        indent(out) << "bool " << (*m_iter)->get_name() << " :1;" << endl;
-      }
-    }
-
-    indent_down();
-    indent(out) << "} _" << tstruct->get_name() << "__isset;" << endl;
-  }
-
-  out << endl;
-
-  // Open struct def
-  out << indent() << "class " << tstruct->get_name() << extends << " {" << endl << indent()
-      << " public:" << endl << endl;
-  indent_up();
-
-  if (!pointers) {
-    // Copy constructor
-    indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&);" << endl;
-
-    // Move constructor
-    if (gen_moveable_) {
-      indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&);" << endl;
-    }
-
-    // Assignment Operator
-    indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&);"
-                << endl;
-
-    // Move assignment operator
-    if (gen_moveable_) {
-      indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&);" << endl;
-    }
-
-    // Default constructor
-    indent(out) << tstruct->get_name() << "()";
-
-    bool init_ctor = false;
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-      if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) {
-        string dval;
-        if (t->is_enum()) {
-          dval += "(" + type_name(t) + ")";
-        }
-        dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0";
-        t_const_value* cv = (*m_iter)->get_value();
-        if (cv != NULL) {
-          dval = render_const_value(out, (*m_iter)->get_name(), t, cv);
-        }
-        if (!init_ctor) {
-          init_ctor = true;
-          out << " : ";
-          out << (*m_iter)->get_name() << "(" << dval << ")";
-        } else {
-          out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
-        }
-      }
-    }
-    out << " {" << endl;
-    indent_up();
-    // TODO(dreiss): When everything else in Thrift is perfect,
-    // do more of these in the initializer list.
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = get_true_type((*m_iter)->get_type());
-
-      if (!t->is_base_type()) {
-        t_const_value* cv = (*m_iter)->get_value();
-        if (cv != NULL) {
-          print_const_value(out, (*m_iter)->get_name(), t, cv);
-        }
-      }
-    }
-    scope_down(out);
-  }
-
-  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
-    out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl;
-  }
-
-  // Declare all fields
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << declare_field(*m_iter,
-                                 false,
-                                 (pointers && !(*m_iter)->get_type()->is_xception()),
-                                 !read) << endl;
-  }
-
-  // Add the __isset data member if we need it, using the definition from above
-  if (has_nonrequired_fields && (!pointers || read)) {
-    out << endl << indent() << "_" << tstruct->get_name() << "__isset __isset;" << endl;
-  }
-
-  // Create a setter function for each field
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (pointers) {
-      continue;
-    }
-    if (is_reference((*m_iter))) {
-      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(boost::shared_ptr<"
-          << type_name((*m_iter)->get_type(), false, false) << ">";
-      out << " val);" << endl;
-    } else {
-      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "("
-          << type_name((*m_iter)->get_type(), false, true);
-      out << " val);" << endl;
-    }
-  }
-  out << endl;
-
-  if (!pointers) {
-    // Should we generate default operators?
-    if (!gen_no_default_operators_) {
-      // Generate an equality testing operator.  Make it inline since the compiler
-      // will do a better job than we would when deciding whether to inline it.
-      out << indent() << "bool operator == (const " << tstruct->get_name() << " & "
-          << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl;
-      scope_up(out);
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        // Most existing Thrift code does not use isset or optional/required,
-        // so we treat "default" fields as required.
-        if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-          out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs."
-              << (*m_iter)->get_name() << "))" << endl << indent() << "  return false;" << endl;
-        } else {
-          out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset."
-              << (*m_iter)->get_name() << ")" << endl << indent() << "  return false;" << endl
-              << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !("
-              << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl
-              << indent() << "  return false;" << endl;
-        }
-      }
-      indent(out) << "return true;" << endl;
-      scope_down(out);
-      out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {"
-          << endl << indent() << "  return !(*this == rhs);" << endl << indent() << "}" << endl
-          << endl;
-
-      // Generate the declaration of a less-than operator.  This must be
-      // implemented by the application developer if they wish to use it.  (They
-      // will get a link error if they try to use it without an implementation.)
-      out << indent() << "bool operator < (const " << tstruct->get_name() << " & ) const;" << endl
-          << endl;
-    }
-  }
-
-  if (read) {
-    if (gen_templates_) {
-      out << indent() << "template <class Protocol_>" << endl << indent()
-          << "uint32_t read(Protocol_* iprot);" << endl;
-    } else {
-      out << indent() << "uint32_t read("
-          << "::apache::thrift::protocol::TProtocol* iprot);" << endl;
-    }
-  }
-  if (write) {
-    if (gen_templates_) {
-      out << indent() << "template <class Protocol_>" << endl << indent()
-          << "uint32_t write(Protocol_* oprot) const;" << endl;
-    } else {
-      out << indent() << "uint32_t write("
-          << "::apache::thrift::protocol::TProtocol* oprot) const;" << endl;
-    }
-  }
-  out << endl;
-
-  if (is_user_struct) {
-    out << indent() << "virtual ";
-    generate_struct_print_method_decl(out, NULL);
-    out << ";" << endl;
-  }
-
-  // std::exception::what()
-  if (is_exception) {
-    out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << endl;
-    out << indent();
-    generate_exception_what_method_decl(out, tstruct, false);
-    out << ";" << endl;
-  }
-
-  indent_down();
-  indent(out) << "};" << endl << endl;
-
-  if (swap) {
-    // Generate a namespace-scope swap() function
-    out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
-        << " &b);" << endl << endl;
-  }
-
-  if (is_user_struct) {
-    generate_struct_ostream_operator(out, tstruct);
-  }
-}
-
-void t_cpp_generator::generate_struct_definition(ofstream& out,
-                                                 ofstream& force_cpp_out,
-                                                 t_struct* tstruct,
-                                                 bool setters) {
-  // Get members
-  vector<t_field*>::const_iterator m_iter;
-  const vector<t_field*>& members = tstruct->get_members();
-
-  // Destructor
-  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
-    force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name()
-                  << "() throw() {" << endl;
-    indent_up();
-
-    indent_down();
-    force_cpp_out << indent() << "}" << endl << endl;
-  }
-
-  // Create a setter function for each field
-  if (setters) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if (is_reference((*m_iter))) {
-        std::string type = type_name((*m_iter)->get_type());
-        out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
-            << (*m_iter)->get_name() << "(boost::shared_ptr<"
-            << type_name((*m_iter)->get_type(), false, false) << ">";
-        out << " val) {" << endl;
-      } else {
-        out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
-            << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true);
-        out << " val) {" << endl;
-      }
-      indent_up();
-      out << indent() << "this->" << (*m_iter)->get_name() << " = val;" << endl;
-      indent_down();
-
-      // assume all fields are required except optional fields.
-      // for optional fields change __isset.name to true
-      bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
-      if (is_optional) {
-        out << indent() << indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl;
-      }
-      out << indent() << "}" << endl;
-    }
-  }
-  out << endl;
-}
-
-/**
- * Makes a helper function to gen a struct reader.
- *
- * @param out Stream to write to
- * @param tstruct The struct
- */
-void t_cpp_generator::generate_struct_reader(ofstream& out, t_struct* tstruct, bool pointers) {
-  if (gen_templates_) {
-    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
-        << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl;
-  } else {
-    indent(out) << "uint32_t " << tstruct->get_name()
-                << "::read(::apache::thrift::protocol::TProtocol* iprot) {" << endl;
-  }
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // Declare stack tmp variables
-  out << endl
-      << indent() << "apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);" << endl
-      << indent() << "uint32_t xfer = 0;" << endl
-      << indent() << "std::string fname;" << endl
-      << indent() << "::apache::thrift::protocol::TType ftype;" << endl
-      << indent() << "int16_t fid;" << endl
-      << endl
-      << indent() << "xfer += iprot->readStructBegin(fname);" << endl
-      << endl
-      << indent() << "using ::apache::thrift::protocol::TProtocolException;" << endl
-      << endl;
-
-  // Required variables aren't in __isset, so we need tmp vars to check them.
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
-      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
-  }
-  out << endl;
-
-  // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
-  scope_up(out);
-
-  // Read beginning field marker
-  indent(out) << "xfer += iprot->readFieldBegin(fname, ftype, fid);" << endl;
-
-  // Check for field STOP marker
-  out << indent() << "if (ftype == ::apache::thrift::protocol::T_STOP) {" << endl << indent()
-      << "  break;" << endl << indent() << "}" << endl;
-
-  if (fields.empty()) {
-    out << indent() << "xfer += iprot->skip(ftype);" << endl;
-  } else {
-    // Switch statement on the field we are reading
-    indent(out) << "switch (fid)" << endl;
-
-    scope_up(out);
-
-    // Generate deserialization code for known cases
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
-      indent_up();
-      indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
-      indent_up();
-
-      const char* isset_prefix = ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset."
-                                                                               : "isset_";
-
-#if 0
-          // This code throws an exception if the same field is encountered twice.
-          // We've decided to leave it out for performance reasons.
-          // TODO(dreiss): Generate this code and "if" it out to make it easier
-          // for people recompiling thrift to include it.
-          out <<
-            indent() << "if (" << isset_prefix << (*f_iter)->get_name() << ")" << endl <<
-            indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
-#endif
-
-      if (pointers && !(*f_iter)->get_type()->is_xception()) {
-        generate_deserialize_field(out, *f_iter, "(*(this->", "))");
-      } else {
-        generate_deserialize_field(out, *f_iter, "this->");
-      }
-      out << indent() << isset_prefix << (*f_iter)->get_name() << " = true;" << endl;
-      indent_down();
-      out << indent() << "} else {" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl
-          <<
-          // TODO(dreiss): Make this an option when thrift structs
-          // have a common base class.
-          // indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl <<
-          indent() << "}" << endl << indent() << "break;" << endl;
-      indent_down();
-    }
-
-    // In the default case we skip the field
-    out << indent() << "default:" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl
-        << indent() << "  break;" << endl;
-
-    scope_down(out);
-  } //!fields.empty()
-  // Read field end marker
-  indent(out) << "xfer += iprot->readFieldEnd();" << endl;
-
-  scope_down(out);
-
-  out << endl << indent() << "xfer += iprot->readStructEnd();" << endl;
-
-  // Throw if any required fields are missing.
-  // We do this after reading the struct end so that
-  // there might possibly be a chance of continuing.
-  out << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
-      out << indent() << "if (!isset_" << (*f_iter)->get_name() << ')' << endl << indent()
-          << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
-  }
-
-  indent(out) << "return xfer;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates the write function.
- *
- * @param out Stream to write to
- * @param tstruct The struct
- */
-void t_cpp_generator::generate_struct_writer(ofstream& out, t_struct* tstruct, bool pointers) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  if (gen_templates_) {
-    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
-        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
-  } else {
-    indent(out) << "uint32_t " << tstruct->get_name()
-                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
-  }
-  indent_up();
-
-  out << indent() << "uint32_t xfer = 0;" << endl;
-
-  indent(out) << "apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);" << endl;
-  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool check_if_set = (*f_iter)->get_req() == t_field::T_OPTIONAL
-                        || (*f_iter)->get_type()->is_xception();
-    if (check_if_set) {
-      out << endl << indent() << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl;
-      indent_up();
-    } else {
-      out << endl;
-    }
-
-    // Write field header
-    out << indent() << "xfer += oprot->writeFieldBegin("
-        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
-        << (*f_iter)->get_key() << ");" << endl;
-    // Write field contents
-    if (pointers && !(*f_iter)->get_type()->is_xception()) {
-      generate_serialize_field(out, *f_iter, "(*(this->", "))");
-    } else {
-      generate_serialize_field(out, *f_iter, "this->");
-    }
-    // Write field closer
-    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
-    if (check_if_set) {
-      indent_down();
-      indent(out) << '}';
-    }
-  }
-
-  out << endl;
-
-  // Write the struct map
-  out << indent() << "xfer += oprot->writeFieldStop();" << endl << indent()
-      << "xfer += oprot->writeStructEnd();" << endl << indent()
-      << "return xfer;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Struct writer for result of a function, which can have only one of its
- * fields set and does a conditional if else look up into the __isset field
- * of the struct.
- *
- * @param out Output stream
- * @param tstruct The result struct
- */
-void t_cpp_generator::generate_struct_result_writer(ofstream& out,
-                                                    t_struct* tstruct,
-                                                    bool pointers) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  if (gen_templates_) {
-    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
-        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
-  } else {
-    indent(out) << "uint32_t " << tstruct->get_name()
-                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
-  }
-  indent_up();
-
-  out << endl << indent() << "uint32_t xfer = 0;" << endl << endl;
-
-  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
-
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-      out << endl << indent() << "if ";
-    } else {
-      out << " else if ";
-    }
-
-    out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl;
-
-    indent_up();
-
-    // Write field header
-    out << indent() << "xfer += oprot->writeFieldBegin("
-        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
-        << (*f_iter)->get_key() << ");" << endl;
-    // Write field contents
-    if (pointers) {
-      generate_serialize_field(out, *f_iter, "(*(this->", "))");
-    } else {
-      generate_serialize_field(out, *f_iter, "this->");
-    }
-    // Write field closer
-    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
-
-    indent_down();
-    indent(out) << "}";
-  }
-
-  // Write the struct map
-  out << endl << indent() << "xfer += oprot->writeFieldStop();" << endl << indent()
-      << "xfer += oprot->writeStructEnd();" << endl << indent() << "return xfer;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates the swap function.
- *
- * @param out Stream to write to
- * @param tstruct The struct
- */
-void t_cpp_generator::generate_struct_swap(ofstream& out, t_struct* tstruct) {
-  out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
-      << " &b) {" << endl;
-  indent_up();
-
-  // Let argument-dependent name lookup find the correct swap() function to
-  // use based on the argument types.  If none is found in the arguments'
-  // namespaces, fall back to ::std::swap().
-  out << indent() << "using ::std::swap;" << endl;
-
-  bool has_nonrequired_fields = false;
-  const vector<t_field*>& fields = tstruct->get_members();
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* tfield = *f_iter;
-
-    if (tfield->get_req() != t_field::T_REQUIRED) {
-      has_nonrequired_fields = true;
-    }
-
-    out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");"
-        << endl;
-  }
-
-  if (has_nonrequired_fields) {
-    out << indent() << "swap(a.__isset, b.__isset);" << endl;
-  }
-
-  // handle empty structs
-  if (fields.size() == 0) {
-    out << indent() << "(void) a;" << endl;
-    out << indent() << "(void) b;" << endl;
-  }
-
-  scope_down(out);
-  out << endl;
-}
-
-void t_cpp_generator::generate_struct_ostream_operator(std::ofstream& out, t_struct* tstruct) {
-  out << "inline std::ostream& operator<<(std::ostream& out, const "
-      << tstruct->get_name()
-      << "& obj)" << endl;
-  scope_up(out);
-  out << indent() << "obj.printTo(out);" << endl
-      << indent() << "return out;" << endl;
-  scope_down(out);
-  out << endl;
-}
-
-void t_cpp_generator::generate_struct_print_method_decl(std::ofstream& out, t_struct* tstruct) {
-  out << "void ";
-  if (tstruct) {
-    out << tstruct->get_name() << "::";
-  }
-  out << "printTo(std::ostream& out) const";
-}
-
-void t_cpp_generator::generate_exception_what_method_decl(std::ofstream& out,
-                                                          t_struct* tstruct,
-                                                          bool external) {
-  out << "const char* ";
-  if (external) {
-    out << tstruct->get_name() << "::";
-  }
-  out << "what() const throw()";
-}
-
-namespace struct_ostream_operator_generator {
-void generate_required_field_value(std::ofstream& out, const t_field* field) {
-  out << " << to_string(" << field->get_name() << ")";
-}
-
-void generate_optional_field_value(std::ofstream& out, const t_field* field) {
-  out << "; (__isset." << field->get_name() << " ? (out";
-  generate_required_field_value(out, field);
-  out << ") : (out << \"<null>\"))";
-}
-
-void generate_field_value(std::ofstream& out, const t_field* field) {
-  if (field->get_req() == t_field::T_OPTIONAL)
-    generate_optional_field_value(out, field);
-  else
-    generate_required_field_value(out, field);
-}
-
-void generate_field_name(std::ofstream& out, const t_field* field) {
-  out << "\"" << field->get_name() << "=\"";
-}
-
-void generate_field(std::ofstream& out, const t_field* field) {
-  generate_field_name(out, field);
-  generate_field_value(out, field);
-}
-
-void generate_fields(std::ofstream& out,
-                     const vector<t_field*>& fields,
-                     const std::string& indent) {
-  const vector<t_field*>::const_iterator beg = fields.begin();
-  const vector<t_field*>::const_iterator end = fields.end();
-
-  for (vector<t_field*>::const_iterator it = beg; it != end; ++it) {
-    out << indent << "out << ";
-
-    if (it != beg) {
-      out << "\", \" << ";
-    }
-
-    generate_field(out, *it);
-    out << ";" << endl;
-  }
-}
-}
-
-/**
- * Generates operator<<
- */
-void t_cpp_generator::generate_struct_print_method(std::ofstream& out, t_struct* tstruct) {
-  out << indent();
-  generate_struct_print_method_decl(out, tstruct);
-  out << " {" << endl;
-
-  indent_up();
-
-  out << indent() << "using ::apache::thrift::to_string;" << endl;
-  out << indent() << "out << \"" << tstruct->get_name() << "(\";" << endl;
-  struct_ostream_operator_generator::generate_fields(out, tstruct->get_members(), indent());
-  out << indent() << "out << \")\";" << endl;
-
-  indent_down();
-  out << "}" << endl << endl;
-}
-
-/**
- * Generates what() method for exceptions
- */
-void t_cpp_generator::generate_exception_what_method(std::ofstream& out, t_struct* tstruct) {
-  out << indent();
-  generate_exception_what_method_decl(out, tstruct, true);
-  out << " {" << endl;
-
-  indent_up();
-  out << indent() << "try {" << endl;
-
-  indent_up();
-  out << indent() << "std::stringstream ss;" << endl;
-  out << indent() << "ss << \"TException - service has thrown: \" << *this;" << endl;
-  out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << endl;
-  out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << endl;
-  indent_down();
-
-  out << indent() << "} catch (const std::exception&) {" << endl;
-
-  indent_up();
-  out << indent() << "return \"TException - service has thrown: " << tstruct->get_name() << "\";"
-      << endl;
-  indent_down();
-
-  out << indent() << "}" << endl;
-
-  indent_down();
-  out << "}" << endl << endl;
-}
-
-/**
- * Generates a thrift service. In C++, this comprises an entirely separate
- * header and source file. The header file defines the methods and includes
- * the data types defined in the main header file, and the implementation
- * file contains implementations of the basic printer and default interfaces.
- *
- * @param tservice The service definition
- */
-void t_cpp_generator::generate_service(t_service* tservice) {
-  string svcname = tservice->get_name();
-
-  // Make output files
-  string f_header_name = get_out_dir() + svcname + ".h";
-  f_header_.open(f_header_name.c_str());
-
-  // Print header file includes
-  f_header_ << autogen_comment();
-  f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl
-            << endl;
-  if (gen_cob_style_) {
-    f_header_ << "#include <thrift/transport/TBufferTransports.h>" << endl << // TMemoryBuffer
-        "#include <thrift/cxxfunctional.h>" << endl
-              << "namespace apache { namespace thrift { namespace async {" << endl
-              << "class TAsyncChannel;" << endl << "}}}" << endl;
-  }
-  f_header_ << "#include <thrift/TDispatchProcessor.h>" << endl;
-  if (gen_cob_style_) {
-    f_header_ << "#include <thrift/async/TAsyncDispatchProcessor.h>" << endl;
-  }
-  f_header_ << "#include <thrift/async/TConcurrentClientSyncInfo.h>" << endl;
-  f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\""
-            << endl;
-
-  t_service* extends_service = tservice->get_extends();
-  if (extends_service != NULL) {
-    f_header_ << "#include \"" << get_include_prefix(*(extends_service->get_program()))
-              << extends_service->get_name() << ".h\"" << endl;
-  }
-
-  f_header_ << endl << ns_open_ << endl << endl;
-
-  f_header_ << "#ifdef _WIN32\n"
-               "  #pragma warning( push )\n"
-               "  #pragma warning (disable : 4250 ) //inheriting methods via dominance \n"
-               "#endif\n\n";
-
-  // Service implementation file includes
-  string f_service_name = get_out_dir() + svcname + ".cpp";
-  f_service_.open(f_service_name.c_str());
-  f_service_ << autogen_comment();
-  f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl;
-  if (gen_cob_style_) {
-    f_service_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
-  }
-  if (gen_templates_) {
-    f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\""
-               << endl;
-
-    string f_service_tcc_name = get_out_dir() + svcname + ".tcc";
-    f_service_tcc_.open(f_service_tcc_name.c_str());
-    f_service_tcc_ << autogen_comment();
-    f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\""
-                   << endl;
-
-    f_service_tcc_ << "#ifndef " << svcname << "_TCC" << endl << "#define " << svcname << "_TCC"
-                   << endl << endl;
-
-    if (gen_cob_style_) {
-      f_service_tcc_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
-    }
-  }
-
-  f_service_ << endl << ns_open_ << endl << endl;
-  f_service_tcc_ << endl << ns_open_ << endl << endl;
-
-  // Generate all the components
-  generate_service_interface(tservice, "");
-  generate_service_interface_factory(tservice, "");
-  generate_service_null(tservice, "");
-  generate_service_helpers(tservice);
-  generate_service_client(tservice, "");
-  generate_service_processor(tservice, "");
-  generate_service_multiface(tservice);
-  generate_service_skeleton(tservice);
-  generate_service_client(tservice, "Concurrent");
-
-  // Generate all the cob components
-  if (gen_cob_style_) {
-    generate_service_interface(tservice, "CobCl");
-    generate_service_interface(tservice, "CobSv");
-    generate_service_interface_factory(tservice, "CobSv");
-    generate_service_null(tservice, "CobSv");
-    generate_service_client(tservice, "Cob");
-    generate_service_processor(tservice, "Cob");
-    generate_service_async_skeleton(tservice);
-  }
-
-  f_header_ << "#ifdef _WIN32\n"
-               "  #pragma warning( pop )\n"
-               "#endif\n\n";
-
-  // Close the namespace
-  f_service_ << ns_close_ << endl << endl;
-  f_service_tcc_ << ns_close_ << endl << endl;
-  f_header_ << ns_close_ << endl << endl;
-
-  // TODO(simpkins): Make this a separate option
-  if (gen_templates_) {
-    f_header_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" << endl
-              << "#include \"" << get_include_prefix(*get_program()) << program_name_
-              << "_types.tcc\"" << endl << endl;
-  }
-
-  f_header_ << "#endif" << endl;
-  f_service_tcc_ << "#endif" << endl;
-
-  // Close the files
-  f_service_tcc_.close();
-  f_service_.close();
-  f_header_.close();
-}
-
-/**
- * Generates helper functions for a service. Basically, this generates types
- * for all the arguments and results to functions.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_cpp_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    string name_orig = ts->get_name();
-
-    // TODO(dreiss): Why is this stuff not in generate_function_helpers?
-    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
-    generate_struct_declaration(f_header_, ts, false);
-    generate_struct_definition(out, f_service_, ts, false);
-    generate_struct_reader(out, ts);
-    generate_struct_writer(out, ts);
-    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs");
-    generate_struct_declaration(f_header_, ts, false, true, false, true);
-    generate_struct_definition(out, f_service_, ts, false);
-    generate_struct_writer(out, ts, true);
-    ts->set_name(name_orig);
-
-    generate_function_helpers(tservice, *f_iter);
-  }
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_cpp_generator::generate_service_interface(t_service* tservice, string style) {
-
-  string service_if_name = service_name_ + style + "If";
-  if (style == "CobCl") {
-    // Forward declare the client.
-    string client_name = service_name_ + "CobClient";
-    if (gen_templates_) {
-      client_name += "T";
-      service_if_name += "T";
-      indent(f_header_) << "template <class Protocol_>" << endl;
-    }
-    indent(f_header_) << "class " << client_name << ";" << endl << endl;
-  }
-
-  string extends = "";
-  if (tservice->get_extends() != NULL) {
-    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "If";
-    if (style == "CobCl" && gen_templates_) {
-      // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
-      // parent services were also generated with templates enabled.
-      extends += "T<Protocol_>";
-    }
-  }
-
-  if (style == "CobCl" && gen_templates_) {
-    f_header_ << "template <class Protocol_>" << endl;
-  }
-  f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl;
-  indent_up();
-  f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    if ((*f_iter)->has_doc())
-      f_header_ << endl;
-    generate_java_doc(f_header_, *f_iter);
-    f_header_ << indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl;
-  }
-  indent_down();
-  f_header_ << "};" << endl << endl;
-
-  if (style == "CobCl" && gen_templates_) {
-    // generate a backwards-compatible typedef for clients that do not
-    // know about the new template-style code
-    f_header_ << "typedef " << service_if_name << "< ::apache::thrift::protocol::TProtocol> "
-              << service_name_ << style << "If;" << endl << endl;
-  }
-}
-
-/**
- * Generates a service interface factory.
- *
- * @param tservice The service to generate an interface factory for.
- */
-void t_cpp_generator::generate_service_interface_factory(t_service* tservice, string style) {
-  string service_if_name = service_name_ + style + "If";
-
-  // Figure out the name of the upper-most parent class.
-  // Getting everything to work out properly with inheritance is annoying.
-  // Here's what we're doing for now:
-  //
-  // - All handlers implement getHandler(), but subclasses use covariant return
-  //   types to return their specific service interface class type.  We have to
-  //   use raw pointers because of this; shared_ptr<> can't be used for
-  //   covariant return types.
-  //
-  // - Since we're not using shared_ptr<>, we also provide a releaseHandler()
-  //   function that must be called to release a pointer to a handler obtained
-  //   via getHandler().
-  //
-  //   releaseHandler() always accepts a pointer to the upper-most parent class
-  //   type.  This is necessary since the parent versions of releaseHandler()
-  //   may accept any of the parent types, not just the most specific subclass
-  //   type.  Implementations can use dynamic_cast to cast the pointer to the
-  //   subclass type if desired.
-  t_service* base_service = tservice;
-  while (base_service->get_extends() != NULL) {
-    base_service = base_service->get_extends();
-  }
-  string base_if_name = type_name(base_service) + style + "If";
-
-  // Generate the abstract factory class
-  string factory_name = service_if_name + "Factory";
-  string extends;
-  if (tservice->get_extends() != NULL) {
-    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "IfFactory";
-  }
-
-  f_header_ << "class " << factory_name << extends << " {" << endl << " public:" << endl;
-  indent_up();
-  f_header_ << indent() << "typedef " << service_if_name << " Handler;" << endl << endl << indent()
-            << "virtual ~" << factory_name << "() {}" << endl << endl << indent() << "virtual "
-            << service_if_name << "* getHandler("
-            << "const ::apache::thrift::TConnectionInfo& connInfo) = 0;" << endl << indent()
-            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) = 0;" << endl;
-
-  indent_down();
-  f_header_ << "};" << endl << endl;
-
-  // Generate the singleton factory class
-  string singleton_factory_name = service_if_name + "SingletonFactory";
-  f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {"
-            << endl << " public:" << endl;
-  indent_up();
-  f_header_ << indent() << singleton_factory_name << "(const boost::shared_ptr<" << service_if_name
-            << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~"
-            << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual "
-            << service_if_name << "* getHandler("
-            << "const ::apache::thrift::TConnectionInfo&) {" << endl << indent()
-            << "  return iface_.get();" << endl << indent() << "}" << endl << indent()
-            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) {}" << endl;
-
-  f_header_ << endl << " protected:" << endl << indent() << "boost::shared_ptr<" << service_if_name
-            << "> iface_;" << endl;
-
-  indent_down();
-  f_header_ << "};" << endl << endl;
-}
-
-/**
- * Generates a null implementation of the service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_cpp_generator::generate_service_null(t_service* tservice, string style) {
-  string extends = "";
-  if (tservice->get_extends() != NULL) {
-    extends = " , virtual public " + type_name(tservice->get_extends()) + style + "Null";
-  }
-  f_header_ << "class " << service_name_ << style << "Null : virtual public " << service_name_
-            << style << "If" << extends << " {" << endl << " public:" << endl;
-  indent_up();
-  f_header_ << indent() << "virtual ~" << service_name_ << style << "Null() {}" << endl;
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_header_ << indent() << function_signature(*f_iter, style, "", false) << " {" << endl;
-    indent_up();
-
-    t_type* returntype = (*f_iter)->get_returntype();
-    t_field returnfield(returntype, "_return");
-
-    if (style == "") {
-      if (returntype->is_void() || is_complex_type(returntype)) {
-        f_header_ << indent() << "return;" << endl;
-      } else {
-        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent()
-                  << "return _return;" << endl;
-      }
-    } else if (style == "CobSv") {
-      if (returntype->is_void()) {
-        f_header_ << indent() << "return cob();" << endl;
-      } else {
-        t_field returnfield(returntype, "_return");
-        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent()
-                  << "return cob(_return);" << endl;
-      }
-
-    } else {
-      throw "UNKNOWN STYLE";
-    }
-
-    indent_down();
-    f_header_ << indent() << "}" << endl;
-  }
-  indent_down();
-  f_header_ << "};" << endl << endl;
-}
-
-void t_cpp_generator::generate_function_call(ostream& out,
-                                             t_function* tfunction,
-                                             string target,
-                                             string iface,
-                                             string arg_prefix) {
-  bool first = true;
-  t_type* ret_type = get_true_type(tfunction->get_returntype());
-  out << indent();
-  if (!tfunction->is_oneway() && !ret_type->is_void()) {
-    if (is_complex_type(ret_type)) {
-      first = false;
-      out << iface << "->" << tfunction->get_name() << "(" << target;
-    } else {
-      out << target << " = " << iface << "->" << tfunction->get_name() << "(";
-    }
-  } else {
-    out << iface << "->" << tfunction->get_name() << "(";
-  }
-  const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      out << ", ";
-    }
-    out << arg_prefix << (*f_iter)->get_name();
-  }
-  out << ");" << endl;
-}
-
-void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) {
-  string svcname = tservice->get_name();
-
-  // Service implementation file includes
-  string f_skeleton_name = get_out_dir() + svcname + "_async_server.skeleton.cpp";
-
-  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
-
-  ofstream f_skeleton;
-  f_skeleton.open(f_skeleton_name.c_str());
-  f_skeleton << "// This autogenerated skeleton file illustrates one way to adapt a synchronous"
-             << endl << "// interface into an asynchronous interface. You should copy it to another"
-             << endl
-             << "// filename to avoid overwriting it and rewrite as asynchronous any functions"
-             << endl << "// that would otherwise introduce unwanted latency." << endl << endl
-             << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl
-             << "#include <thrift/protocol/TBinaryProtocol.h>" << endl << endl
-             << "using namespace ::apache::thrift;" << endl
-             << "using namespace ::apache::thrift::protocol;" << endl
-             << "using namespace ::apache::thrift::transport;" << endl
-             << "using namespace ::apache::thrift::async;" << endl << endl
-             << "using boost::shared_ptr;" << endl << endl;
-
-  // the following code would not compile:
-  // using namespace ;
-  // using namespace ::;
-  if ((!ns.empty()) && (ns.compare(" ::") != 0)) {
-    f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl;
-  }
-
-  f_skeleton << "class " << svcname << "AsyncHandler : "
-             << "public " << svcname << "CobSvIf {" << endl << " public:" << endl;
-  indent_up();
-  f_skeleton << indent() << svcname << "AsyncHandler() {" << endl << indent()
-             << "  syncHandler_ = std::auto_ptr<" << svcname << "Handler>(new " << svcname
-             << "Handler);" << endl << indent() << "  // Your initialization goes here" << endl
-             << indent() << "}" << endl;
-  f_skeleton << indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl;
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_skeleton << endl << indent() << function_signature(*f_iter, "CobSv", "", true) << " {"
-               << endl;
-    indent_up();
-
-    t_type* returntype = (*f_iter)->get_returntype();
-    t_field returnfield(returntype, "_return");
-
-    string target = returntype->is_void() ? "" : "_return";
-    if (!returntype->is_void()) {
-      f_skeleton << indent() << declare_field(&returnfield, true) << endl;
-    }
-    generate_function_call(f_skeleton, *f_iter, target, "syncHandler_", "");
-    f_skeleton << indent() << "return cob(" << target << ");" << endl;
-
-    scope_down(f_skeleton);
-  }
-  f_skeleton << endl << " protected:" << endl << indent() << "std::auto_ptr<" << svcname
-             << "Handler> syncHandler_;" << endl;
-  indent_down();
-  f_skeleton << "};" << endl << endl;
-}
-
-/**
- * Generates a multiface, which is a single server that just takes a set
- * of objects implementing the interface and calls them all, returning the
- * value of the last one to be called.
- *
- * @param tservice The service to generate a multiserver for.
- */
-void t_cpp_generator::generate_service_multiface(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  string extends = "";
-  string extends_multiface = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_multiface = ", public " + extends + "Multiface";
-  }
-
-  string list_type = string("std::vector<boost::shared_ptr<") + service_name_ + "If> >";
-
-  // Generate the header portion
-  f_header_ << "class " << service_name_ << "Multiface : "
-            << "virtual public " << service_name_ << "If" << extends_multiface << " {" << endl
-            << " public:" << endl;
-  indent_up();
-  f_header_ << indent() << service_name_ << "Multiface(" << list_type
-            << "& ifaces) : ifaces_(ifaces) {" << endl;
-  if (!extends.empty()) {
-    f_header_ << indent()
-              << "  std::vector<boost::shared_ptr<" + service_name_ + "If> >::iterator iter;"
-              << endl << indent() << "  for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {"
-              << endl << indent() << "    " << extends << "Multiface::add(*iter);" << endl
-              << indent() << "  }" << endl;
-  }
-  f_header_ << indent() << "}" << endl << indent() << "virtual ~" << service_name_
-            << "Multiface() {}" << endl;
-  indent_down();
-
-  // Protected data members
-  f_header_ << " protected:" << endl;
-  indent_up();
-  f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_
-            << "Multiface() {}" << endl << indent() << "void add(boost::shared_ptr<"
-            << service_name_ << "If> iface) {" << endl;
-  if (!extends.empty()) {
-    f_header_ << indent() << "  " << extends << "Multiface::add(iface);" << endl;
-  }
-  f_header_ << indent() << "  ifaces_.push_back(iface);" << endl << indent() << "}" << endl;
-  indent_down();
-
-  f_header_ << indent() << " public:" << endl;
-  indent_up();
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arglist = (*f_iter)->get_arglist();
-    const vector<t_field*>& args = arglist->get_members();
-    vector<t_field*>::const_iterator a_iter;
-
-    string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "(";
-    bool first = true;
-    if (is_complex_type((*f_iter)->get_returntype())) {
-      call += "_return";
-      first = false;
-    }
-    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
-      if (first) {
-        first = false;
-      } else {
-        call += ", ";
-      }
-      call += (*a_iter)->get_name();
-    }
-    call += ")";
-
-    f_header_ << indent() << function_signature(*f_iter, "") << " {" << endl;
-    indent_up();
-    f_header_ << indent() << "size_t sz = ifaces_.size();" << endl << indent() << "size_t i = 0;"
-              << endl << indent() << "for (; i < (sz - 1); ++i) {" << endl;
-    indent_up();
-    f_header_ << indent() << call << ";" << endl;
-    indent_down();
-    f_header_ << indent() << "}" << endl;
-
-    if (!(*f_iter)->get_returntype()->is_void()) {
-      if (is_complex_type((*f_iter)->get_returntype())) {
-        f_header_ << indent() << call << ";" << endl << indent() << "return;" << endl;
-      } else {
-        f_header_ << indent() << "return " << call << ";" << endl;
-      }
-    } else {
-      f_header_ << indent() << call << ";" << endl;
-    }
-
-    indent_down();
-    f_header_ << indent() << "}" << endl << endl;
-  }
-
-  indent_down();
-  f_header_ << indent() << "};" << endl << endl;
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_cpp_generator::generate_service_client(t_service* tservice, string style) {
-  string ifstyle;
-  if (style == "Cob") {
-    ifstyle = "CobCl";
-  }
-
-  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
-  string template_header, template_suffix, short_suffix, protocol_type, _this;
-  string const prot_factory_type = "::apache::thrift::protocol::TProtocolFactory";
-  if (gen_templates_) {
-    template_header = "template <class Protocol_>\n";
-    short_suffix = "T";
-    template_suffix = "T<Protocol_>";
-    protocol_type = "Protocol_";
-    _this = "this->";
-  } else {
-    protocol_type = "::apache::thrift::protocol::TProtocol";
-  }
-  string prot_ptr = "boost::shared_ptr< " + protocol_type + ">";
-  string client_suffix = "Client" + template_suffix;
-  string if_suffix = "If";
-  if (style == "Cob") {
-    if_suffix += template_suffix;
-  }
-
-  string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
-    // parent services were also generated with templates enabled.
-    extends = type_name(tservice->get_extends());
-    extends_client = ", public " + extends + style + client_suffix;
-  }
-
-  // Generate the header portion
-  if (style == "Concurrent") {
-    f_header_ << "// The \'concurrent\' client is a thread safe client that correctly handles\n"
-                 "// out of order responses.  It is slower than the regular client, so should\n"
-                 "// only be used when you need to share a connection among multiple threads\n";
-  }
-  f_header_ << template_header << "class " << service_name_ << style << "Client" << short_suffix
-            << " : "
-            << "virtual public " << service_name_ << ifstyle << if_suffix << extends_client << " {"
-            << endl << " public:" << endl;
-
-  indent_up();
-  if (style != "Cob") {
-    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr
-              << " prot) ";
-
-    if (extends.empty()) {
-      f_header_ << "{" << endl;
-      f_header_ << indent() << "  setProtocol" << short_suffix << "(prot);" << endl << indent()
-                << "}" << endl;
-    } else {
-      f_header_ << ":" << endl;
-      f_header_ << indent() << "  " << extends << style << client_suffix << "(prot, prot) {}"
-                << endl;
-    }
-
-    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr
-              << " iprot, " << prot_ptr << " oprot) ";
-    if (extends.empty()) {
-      f_header_ << "{" << endl;
-      f_header_ << indent() << "  setProtocol" << short_suffix << "(iprot,oprot);" << endl
-                << indent() << "}" << endl;
-    } else {
-      f_header_ << ":" << indent() << "  " << extends << style << client_suffix
-                << "(iprot, oprot) {}" << endl;
-    }
-
-    // create the setProtocol methods
-    if (extends.empty()) {
-      f_header_ << " private:" << endl;
-      // 1: one parameter
-      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " prot) {"
-                << endl;
-      f_header_ << indent() << "setProtocol" << short_suffix << "(prot,prot);" << endl;
-      f_header_ << indent() << "}" << endl;
-      // 2: two parameter
-      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " iprot, "
-                << prot_ptr << " oprot) {" << endl;
-
-      f_header_ << indent() << "  piprot_=iprot;" << endl << indent() << "  poprot_=oprot;" << endl
-                << indent() << "  iprot_ = iprot.get();" << endl << indent()
-                << "  oprot_ = oprot.get();" << endl;
-
-      f_header_ << indent() << "}" << endl;
-      f_header_ << " public:" << endl;
-    }
-
-    // Generate getters for the protocols.
-    // Note that these are not currently templated for simplicity.
-    // TODO(simpkins): should they be templated?
-    f_header_ << indent()
-              << "boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {"
-              << endl << indent() << "  return " << _this << "piprot_;" << endl << indent() << "}"
-              << endl;
-
-    f_header_ << indent()
-              << "boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {"
-              << endl << indent() << "  return " << _this << "poprot_;" << endl << indent() << "}"
-              << endl;
-
-  } else /* if (style == "Cob") */ {
-    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "("
-              << "boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, "
-              << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl;
-    if (extends.empty()) {
-      f_header_ << indent() << "  channel_(channel)," << endl << indent()
-                << "  itrans_(new ::apache::thrift::transport::TMemoryBuffer())," << endl
-                << indent() << "  otrans_(new ::apache::thrift::transport::TMemoryBuffer()),"
-                << endl;
-      if (gen_templates_) {
-        // TProtocolFactory classes return generic TProtocol pointers.
-        // We have to dynamic cast to the Protocol_ type we are expecting.
-        f_header_ << indent() << "  piprot_(boost::dynamic_pointer_cast<Protocol_>("
-                  << "protocolFactory->getProtocol(itrans_)))," << endl << indent()
-                  << "  poprot_(boost::dynamic_pointer_cast<Protocol_>("
-                  << "protocolFactory->getProtocol(otrans_))) {" << endl;
-        // Throw a TException if either dynamic cast failed.
-        f_header_ << indent() << "  if (!piprot_ || !poprot_) {" << endl << indent()
-                  << "    throw ::apache::thrift::TException(\""
-                  << "TProtocolFactory returned unexpected protocol type in " << service_name_
-                  << style << "Client" << short_suffix << " constructor\");" << endl << indent()
-                  << "  }" << endl;
-      } else {
-        f_header_ << indent() << "  piprot_(protocolFactory->getProtocol(itrans_))," << endl
-                  << indent() << "  poprot_(protocolFactory->getProtocol(otrans_)) {" << endl;
-      }
-      f_header_ << indent() << "  iprot_ = piprot_.get();" << endl << indent()
-                << "  oprot_ = poprot_.get();" << endl << indent() << "}" << endl;
-    } else {
-      f_header_ << indent() << "  " << extends << style << client_suffix
-                << "(channel, protocolFactory) {}" << endl;
-    }
-  }
-
-  if (style == "Cob") {
-    f_header_ << indent()
-              << "boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl
-              << indent() << "  return " << _this << "channel_;" << endl << indent() << "}" << endl;
-    if (!gen_no_client_completion_) {
-      f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl;
-    }
-  }
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    indent(f_header_) << function_signature(*f_iter, ifstyle) << ";" << endl;
-    // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style.
-    if (style == "Concurrent" && !(*f_iter)->is_oneway()) {
-      // concurrent clients need to move the seqid from the send function to the
-      // recv function.  Oneway methods don't have a recv function, so we don't need to
-      // move the seqid for them.  Attempting to do so wo

<TRUNCATED>

[53/55] [abbrv] thrift git commit: THRIFT-3748 Node.js Deserialization of lists of lists is broken

Posted by ns...@apache.org.
THRIFT-3748 Node.js Deserialization of lists of lists is broken

This closes #957


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/a400c690
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/a400c690
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/a400c690

Branch: refs/heads/master
Commit: a400c690eb4dc79b0dd89d7f159931487c856dae
Parents: 052abc3
Author: Nobuaki Sukegawa <ns...@apache.org>
Authored: Sat Mar 19 23:55:06 2016 +0900
Committer: Nobuaki Sukegawa <ns...@apache.org>
Committed: Mon Sep 26 01:42:02 2016 +0900

----------------------------------------------------------------------
 lib/nodejs/lib/thrift/json_protocol.js   |  7 ++-
 lib/nodejs/test/deep-constructor.test.js | 73 +++++++++++++++++++++++++--
 test/JsDeepConstructorTest.thrift        |  2 +
 3 files changed, 77 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/a400c690/lib/nodejs/lib/thrift/json_protocol.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/json_protocol.js b/lib/nodejs/lib/thrift/json_protocol.js
index 2e0d29a..f31e3b2 100644
--- a/lib/nodejs/lib/thrift/json_protocol.js
+++ b/lib/nodejs/lib/thrift/json_protocol.js
@@ -634,7 +634,12 @@ TJSONProtocol.prototype.readListBegin = function() {
 
 /** Deserializes the end of a list. */
 TJSONProtocol.prototype.readListEnd = function() {
-  this.readFieldEnd();
+  var pos = this.rpos.pop() - 2;
+  var st = this.rstack;
+  st.pop();
+  if (st instanceof Array && st.length > pos && st[pos].length > 0) {
+    st.push(st[pos].shift());
+  }
 };
 
 /**

http://git-wip-us.apache.org/repos/asf/thrift/blob/a400c690/lib/nodejs/test/deep-constructor.test.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/deep-constructor.test.js b/lib/nodejs/test/deep-constructor.test.js
index 8dd29ee..2caeb82 100644
--- a/lib/nodejs/test/deep-constructor.test.js
+++ b/lib/nodejs/test/deep-constructor.test.js
@@ -91,9 +91,22 @@ function createThriftObj() {
           DB: new ttypes.Simple({value: 'k'})
         }
       ]
-    }
-  }
-  );
+    },
+
+    list_of_list_field: [
+      ['l00', 'l01', 'l02'],
+      ['l10', 'l11', 'l12'],
+      ['l20', 'l21', 'l22'],
+    ],
+
+    list_of_list_of_list_field: [
+      [['m000', 'm001', 'm002'], ['m010', 'm011', 'm012'], ['m020', 'm021', 'm022']],
+      [['m100', 'm101', 'm102'], ['m110', 'm111', 'm112'], ['m120', 'm121', 'm122']],
+      [['m200', 'm201', 'm202'], ['m210', 'm211', 'm212'], ['m220', 'm221', 'm222']],
+    ],
+
+
+  });
 }
 
 
@@ -138,7 +151,20 @@ function createJsObj() {
           DB: {value: 'k'}
         }
       ]
-    }
+    },
+
+    list_of_list_field: [
+      ['l00', 'l01', 'l02'],
+      ['l10', 'l11', 'l12'],
+      ['l20', 'l21', 'l22'],
+    ],
+
+    list_of_list_of_list_field: [
+      [['m000', 'm001', 'm002'], ['m010', 'm011', 'm012'], ['m020', 'm021', 'm022']],
+      [['m100', 'm101', 'm102'], ['m110', 'm111', 'm112'], ['m120', 'm121', 'm122']],
+      [['m200', 'm201', 'm202'], ['m210', 'm211', 'm212'], ['m220', 'm221', 'm222']],
+    ],
+
   };
 }
 
@@ -155,6 +181,45 @@ function assertValues(obj, assert) {
     assert.equals(obj.struct_nested_containers_field[0][0].C[1].value, 'i');
     assert.equals(obj.struct_nested_containers_field2.D[0].DA.value, 'j');
     assert.equals(obj.struct_nested_containers_field2.D[1].DB.value, 'k');
+    assert.equals(obj.list_of_list_field[0][0], 'l00');
+    assert.equals(obj.list_of_list_field[0][1], 'l01');
+    assert.equals(obj.list_of_list_field[0][2], 'l02');
+    assert.equals(obj.list_of_list_field[1][0], 'l10');
+    assert.equals(obj.list_of_list_field[1][1], 'l11');
+    assert.equals(obj.list_of_list_field[1][2], 'l12');
+    assert.equals(obj.list_of_list_field[2][0], 'l20');
+    assert.equals(obj.list_of_list_field[2][1], 'l21');
+    assert.equals(obj.list_of_list_field[2][2], 'l22');
+
+    assert.equals(obj.list_of_list_of_list_field[0][0][0], 'm000');
+    assert.equals(obj.list_of_list_of_list_field[0][0][1], 'm001');
+    assert.equals(obj.list_of_list_of_list_field[0][0][2], 'm002');
+    assert.equals(obj.list_of_list_of_list_field[0][1][0], 'm010');
+    assert.equals(obj.list_of_list_of_list_field[0][1][1], 'm011');
+    assert.equals(obj.list_of_list_of_list_field[0][1][2], 'm012');
+    assert.equals(obj.list_of_list_of_list_field[0][2][0], 'm020');
+    assert.equals(obj.list_of_list_of_list_field[0][2][1], 'm021');
+    assert.equals(obj.list_of_list_of_list_field[0][2][2], 'm022');
+
+    assert.equals(obj.list_of_list_of_list_field[1][0][0], 'm100');
+    assert.equals(obj.list_of_list_of_list_field[1][0][1], 'm101');
+    assert.equals(obj.list_of_list_of_list_field[1][0][2], 'm102');
+    assert.equals(obj.list_of_list_of_list_field[1][1][0], 'm110');
+    assert.equals(obj.list_of_list_of_list_field[1][1][1], 'm111');
+    assert.equals(obj.list_of_list_of_list_field[1][1][2], 'm112');
+    assert.equals(obj.list_of_list_of_list_field[1][2][0], 'm120');
+    assert.equals(obj.list_of_list_of_list_field[1][2][1], 'm121');
+    assert.equals(obj.list_of_list_of_list_field[1][2][2], 'm122');
+
+    assert.equals(obj.list_of_list_of_list_field[2][0][0], 'm200');
+    assert.equals(obj.list_of_list_of_list_field[2][0][1], 'm201');
+    assert.equals(obj.list_of_list_of_list_field[2][0][2], 'm202');
+    assert.equals(obj.list_of_list_of_list_field[2][1][0], 'm210');
+    assert.equals(obj.list_of_list_of_list_field[2][1][1], 'm211');
+    assert.equals(obj.list_of_list_of_list_field[2][1][2], 'm212');
+    assert.equals(obj.list_of_list_of_list_field[2][2][0], 'm220');
+    assert.equals(obj.list_of_list_of_list_field[2][2][1], 'm221');
+    assert.equals(obj.list_of_list_of_list_field[2][2][2], 'm222');
 }
 
 function createTestCases(serialize, deserialize) {

http://git-wip-us.apache.org/repos/asf/thrift/blob/a400c690/test/JsDeepConstructorTest.thrift
----------------------------------------------------------------------
diff --git a/test/JsDeepConstructorTest.thrift b/test/JsDeepConstructorTest.thrift
index c2e23af..ef5126f 100644
--- a/test/JsDeepConstructorTest.thrift
+++ b/test/JsDeepConstructorTest.thrift
@@ -9,6 +9,8 @@ struct Complex {
   4: map<string,Simple> struct_map_field
   5: list<set<map<string,list<Simple>>>> struct_nested_containers_field
   6: map<string, list<map<string,Simple>> > struct_nested_containers_field2
+  7: list<list<string>> list_of_list_field
+  8: list<list<list<string>>> list_of_list_of_list_field
 }
 
 struct ComplexList {


[12/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_haxe_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc
new file mode 100644
index 0000000..e7be1a5
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc
@@ -0,0 +1,2981 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <sstream>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <stdexcept>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Haxe code generator.
+ *
+ */
+class t_haxe_generator : public t_oop_generator {
+public:
+  t_haxe_generator(t_program* program,
+                   const std::map<std::string, std::string>& parsed_options,
+                   const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    callbacks_ = false;
+    rtti_ = false;
+    buildmacro_ = "";
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("callbacks") == 0) {
+        callbacks_ = true;
+      } else if( iter->first.compare("rtti") == 0) {
+        rtti_ = true;
+      } else if( iter->first.compare("buildmacro") == 0) {
+        buildmacro_ = (iter->second);
+      } else {
+        throw "unknown option haxe:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-haxe";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ofstream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false);
+  std::string render_const_value(ofstream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result = false);
+
+  void generate_haxe_struct_definition(std::ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false,
+                                       bool is_result = false);
+  // removed -- equality,compare_to
+  void generate_haxe_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_haxe_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_haxe_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_haxe_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_haxe_struct_tostring(std::ofstream& out, t_struct* tstruct);
+  void generate_haxe_meta_data_map(std::ofstream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  std::string get_haxe_type_string(t_type* type);
+  void generate_reflection_setters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_reflection_getters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
+  void generate_property_getters_setters(std::ofstream& out, t_struct* tstruct);
+
+  void generate_function_helpers(t_function* tfunction);
+  std::string get_cap_name(std::string name);
+  std::string generate_isset_check(t_field* field);
+  std::string generate_isset_check(std::string field);
+  void generate_isset_set(ofstream& out, t_field* field);
+  // removed std::string isset_field_id(t_field* field);
+
+  void generate_service_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+  void generate_service_method_signature(t_function* tfunction, bool is_interface);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_haxe_doc(std::ofstream& out, t_doc* tdoc);
+  void generate_haxe_doc(std::ofstream& out, t_function* tdoc);
+
+  void generate_rtti_decoration(std::ofstream& out);
+  void generate_macro_decoration(std::ofstream& out);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string haxe_package();
+  std::string haxe_type_imports();
+  std::string haxe_thrift_imports();
+  std::string haxe_thrift_gen_imports(t_struct* tstruct, string& imports);
+  std::string haxe_thrift_gen_imports(t_service* tservice);
+  std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false);
+  std::string base_type_name(t_base_type* tbase, bool in_container = false);
+  std::string declare_field(t_field* tfield, bool init = false);
+  std::string function_signature_callback(t_function* tfunction);
+  std::string function_signature_normal(t_function* tfunction);
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string get_enum_class_name(t_type* type);
+  string generate_service_method_onsuccess(t_function* tfunction, bool as_type, bool omit_name);
+  void generate_service_method_signature_callback(t_function* tfunction, bool is_interface);
+  void generate_service_method_signature_normal(t_function* tfunction, bool is_interface);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    if (ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()) {
+      return true;
+    }
+
+    if (ttype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_STRING:
+        // case t_base_type::TYPE_I64:  - Int64 is not really nullable, even though it behaved that
+        // way before Haxe 3.2.0
+        return true;
+      default:
+        return false;
+      }
+    }
+
+    return false;
+  }
+
+  std::string constant_name(std::string name);
+
+private:
+  bool callbacks_;
+  bool rtti_;
+  string buildmacro_;
+
+  /**
+   * File streams
+   */
+
+  std::string package_name_;
+  std::ofstream f_service_;
+  std::string package_dir_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_haxe_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  package_name_ = program_->get_namespace("haxe");
+
+  // Haxe package names are lowercase
+  if (package_name_.length() > 0) {
+    package_name_[0] = tolower(package_name_[0]);
+    size_t index = package_name_.find('.');
+    while (index != std::string::npos) {
+      if (++index < package_name_.length()) {
+        package_name_[index] = tolower(package_name_[index]);
+      }
+      index = package_name_.find('.', index);
+    }
+  }
+
+  string dir = package_name_;
+  string subdir = get_out_dir();
+  string::size_type loc;
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  package_dir_ = subdir;
+}
+
+/**
+ * Packages the generated file
+ *
+ * @return String of the package, i.e. "package org.apache.thriftdemo;"
+ */
+string t_haxe_generator::haxe_package() {
+  if (!package_name_.empty()) {
+    return string("package ") + package_name_;
+  }
+  return "package";
+}
+
+/**
+ * Prints standard haxe imports
+ *
+ * @return List of imports for haxe types that are used in here
+ */
+string t_haxe_generator::haxe_type_imports() {
+  return string() + "import org.apache.thrift.helper.*;\n" + "import haxe.io.Bytes;\n"
+         + "import haxe.ds.IntMap;\n" + "import haxe.ds.StringMap;\n"
+         + "import haxe.ds.ObjectMap;\n" + "\n" + "#if flash\n"
+         + "import flash.errors.ArgumentError;\n" + "#end\n" + "\n";
+}
+
+/**
+ * Prints standard haxe imports
+ *
+ * @return List of imports necessary for thrift
+ */
+string t_haxe_generator::haxe_thrift_imports() {
+  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
+         + "import org.apache.thrift.protocol.*;\n" + "\n";
+}
+
+/**
+ * Prints imports needed for a given type
+ *
+ * @return List of imports necessary for a given t_struct
+ */
+string t_haxe_generator::haxe_thrift_gen_imports(t_struct* tstruct, string& imports) {
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // For each type check if it is from a different namespace
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_program* program = (*m_iter)->get_type()->get_program();
+    if (program != NULL && program != program_) {
+      string package = program->get_namespace("haxe");
+      if (!package.empty()) {
+        if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) {
+          imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n");
+        }
+      }
+    }
+  }
+  return imports;
+}
+
+/**
+ * Prints imports needed for a given type
+ *
+ * @return List of imports necessary for a given t_service
+ */
+string t_haxe_generator::haxe_thrift_gen_imports(t_service* tservice) {
+  string imports;
+  const vector<t_function*>& functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+
+  // For each type check if it is from a different namespace
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_program* program = (*f_iter)->get_returntype()->get_program();
+    if (program != NULL && program != program_) {
+      string package = program->get_namespace("haxe");
+      if (!package.empty()) {
+        if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) {
+          imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name()
+                         + ";\n");
+        }
+      }
+    }
+
+    haxe_thrift_gen_imports((*f_iter)->get_arglist(), imports);
+    haxe_thrift_gen_imports((*f_iter)->get_xceptions(), imports);
+  }
+
+  return imports;
+}
+
+/**
+ * Nothing in haxe
+ */
+void t_haxe_generator::close_generator() {
+}
+
+/**
+ * Generates a typedef. This is not done in haxe, since it does
+ * not support arbitrary name replacements, and it'd be a wacky waste
+ * of overhead to make wrapper classes.
+ *
+ * @param ttypedef The type definition
+ */
+void t_haxe_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Enums are a class with a set of static constants.
+ *
+ * @param tenum The enumeration
+ */
+void t_haxe_generator::generate_enum(t_enum* tenum) {
+  // Make output file
+  string f_enum_name = package_dir_ + "/" + get_cap_name(tenum->get_name()) + ".hx";
+  ofstream f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  // Comment and package it
+  f_enum << autogen_comment() << haxe_package() << ";" << endl << endl;
+
+  // Add haxe imports
+  f_enum << string() + "import org.apache.thrift.helper.*;" << endl << endl;
+
+  generate_rtti_decoration(f_enum);
+  generate_macro_decoration(f_enum);
+  indent(f_enum) << "class " << get_cap_name(tenum->get_name()) << " ";
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "public static inline var " << (*c_iter)->get_name() << " : Int = " << value
+                   << ";" << endl;
+  }
+
+  // Create a static Set with all valid values for this enum
+  f_enum << endl;
+
+  indent(f_enum) << "public static var VALID_VALUES = { new IntSet( [";
+  indent_up();
+  bool firstValue = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    // populate set
+    f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name();
+    firstValue = false;
+  }
+  indent_down();
+  f_enum << "]); };" << endl;
+
+  indent(f_enum) << "public static var VALUES_TO_NAMES = { [";
+  indent_up();
+  firstValue = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    f_enum << (firstValue ? "" : ",") << endl;
+    indent(f_enum) << (*c_iter)->get_name() << " => \"" << (*c_iter)->get_name() << "\"";
+    firstValue = false;
+  }
+  f_enum << endl;
+  indent_down();
+  indent(f_enum) << "]; };" << endl;
+
+  scope_down(f_enum); // end class
+
+  f_enum.close();
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_haxe_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  string f_consts_name = package_dir_ + "/" + get_cap_name(program_name_) + "Constants.hx";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  // Print header
+  f_consts << autogen_comment() << haxe_package() << ";" << endl << endl;
+
+  f_consts << endl;
+
+  f_consts << haxe_type_imports();
+
+  generate_rtti_decoration(f_consts);
+  generate_macro_decoration(f_consts);
+  indent(f_consts) << "class " << get_cap_name(program_name_) << "Constants {" << endl << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value(),
+                      false);
+  }
+  indent_down();
+  indent(f_consts) << "}" << endl;
+  f_consts.close();
+}
+
+void t_haxe_generator::print_const_value(std::ofstream& out,
+                                         string name,
+                                         t_type* type,
+                                         t_const_value* value,
+                                         bool in_static,
+                                         bool defval) {
+  type = get_true_type(type);
+
+  indent(out);
+  if (!defval) {
+    out << (in_static ? "var " : "public static inline var  ");
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = " << value->get_integer() << ";" << endl << endl;
+  } else if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
+        << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function() : Void {" << endl;
+      indent_up();
+    }
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << ".";
+      out << v_iter->first->get_string() << " = " << val << ";" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function() : Void {" << endl;
+      indent_up();
+    }
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << "[" << key << "] = " << val << ";" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function() : Void {" << endl;
+      indent_up();
+    }
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << "." << (type->is_list() ? "push" : "add") << "(" << val << ");"
+                  << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_haxe_generator::render_const_value(ofstream& out,
+                                            string name,
+                                            t_type* type,
+                                            t_const_value* value) {
+  (void)name;
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+      render << "(byte)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I16:
+      render << "(short)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "L";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << "(double)" << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with data members, read(), write(), and an inner Isset class.
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_struct(t_struct* tstruct) {
+  generate_haxe_struct(tstruct, false);
+}
+
+/**
+ * Exceptions are structs, but they inherit from Exception
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_xception(t_struct* txception) {
+  generate_haxe_struct(txception, true);
+}
+
+/**
+ * Haxe struct definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + get_cap_name(tstruct->get_name()) + ".hx";
+  ofstream f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << haxe_package() << ";" << endl;
+
+  f_struct << endl;
+
+  string imports;
+
+  f_struct << haxe_type_imports() << haxe_thrift_imports()
+           << haxe_thrift_gen_imports(tstruct, imports) << endl;
+
+  generate_haxe_struct_definition(f_struct, tstruct, is_exception, is_result);
+
+  f_struct.close();
+}
+
+/**
+ * haxe struct definition. This has various parameters, as it could be
+ * generated standalone or inside another class as a helper. If it
+ * is a helper than it is a static class.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param in_class     If inside a class, needs to be static class
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_haxe_generator::generate_haxe_struct_definition(ofstream& out,
+                                                       t_struct* tstruct,
+                                                       bool is_exception,
+                                                       bool is_result) {
+  generate_haxe_doc(out, tstruct);
+
+  string clsname = get_cap_name(tstruct->get_name());
+
+  generate_rtti_decoration(out);
+  generate_macro_decoration(out);
+  indent(out) << "class " << clsname << " ";
+
+  if (is_exception) {
+    out << "extends TException ";
+  }
+  out << "implements TBase ";
+
+  scope_up(out);
+  indent(out) << endl;
+
+  indent(out) << "static var STRUCT_DESC = { new TStruct(\"" << tstruct->get_name() << "\"); };"
+              << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "static var " << constant_name((*m_iter)->get_name())
+                << "_FIELD_DESC = { new TField(\"" << (*m_iter)->get_name() << "\", "
+                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << "); };"
+                << endl;
+  }
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_haxe_doc(out, *m_iter);
+    // indent(out) << "private var _" << (*m_iter)->get_name() + " : " +
+    // type_name((*m_iter)->get_type()) << ";" << endl;
+    indent(out) << "@:isVar" << endl;
+    indent(out) << "public var "
+                << (*m_iter)->get_name() + "(get,set) : "
+                   + get_cap_name(type_name((*m_iter)->get_type())) << ";" << endl;
+  }
+
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "inline static var " << upcase_string((*m_iter)->get_name())
+                << "_FIELD_ID : Int = " << (*m_iter)->get_key() << ";" << endl;
+  }
+
+  out << endl;
+
+  // Inner Isset class
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (!type_can_be_null((*m_iter)->get_type())) {
+        indent(out) << "private var __isset_" << (*m_iter)->get_name() << " : Bool = false;"
+                    << endl;
+      }
+    }
+  }
+
+  out << endl;
+
+  // Static initializer to populate global class to struct metadata map
+  if (false) {
+    // TODO: reactivate when needed
+    generate_haxe_meta_data_map(out, tstruct);
+    indent(out) << "{" << endl;
+    indent_up();
+    indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);"
+                << endl;
+    indent_down();
+    indent(out) << "}" << endl;
+    indent(out) << "}" << endl;
+  }
+
+  // Default constructor
+  indent(out) << "public function new() {" << endl;
+  indent_up();
+  if (is_exception) {
+    indent(out) << "super();" << endl;
+  }
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if ((*m_iter)->get_value() != NULL) {
+      indent(out) << "this." << (*m_iter)->get_name() << " = "
+                  << (*m_iter)->get_value()->get_integer() << ";" << endl;
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  generate_property_getters_setters(out, tstruct);
+  generate_generic_field_getters_setters(out, tstruct);
+  generate_generic_isset_method(out, tstruct);
+
+  generate_haxe_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_haxe_struct_result_writer(out, tstruct);
+  } else {
+    generate_haxe_struct_writer(out, tstruct);
+  }
+  generate_haxe_struct_tostring(out, tstruct);
+  generate_haxe_validator(out, tstruct);
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_haxe_struct_reader(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public function read( iprot : TProtocol) : Void {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "iprot.IncrementRecursionDepth();" << endl;
+  indent(out) << "try" << endl;
+  scope_up(out);
+
+  // Declare stack tmp variables and read struct header
+  out << indent() << "var field : TField;" << endl << indent() << "iprot.readStructBegin();"
+      << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "field = iprot.readFieldBegin();" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (field.type == TType.STOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (field.id)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << "_FIELD_ID:" << endl;
+    indent_up();
+    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "this.");
+    generate_isset_set(out, *f_iter);
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+        << endl << indent() << "}" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "default:" << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+      << endl;
+
+  scope_down(out);
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  out << indent() << "iprot.readStructEnd();" << endl << endl;
+
+  indent(out) << "iprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+  indent(out) << "catch(e:Dynamic)" << endl;
+  scope_up(out);
+  indent(out) << "iprot.DecrementRecursionDepth();" << endl;
+  indent(out) << "throw e;" << endl;
+  scope_down(out);
+
+  // check for required fields of primitive type
+  // (which can be checked here but not in the general validate method)
+  out << endl << indent() << "// check for required fields of primitive type, which can't be "
+                             "checked in the validate method" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
+      out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent()
+          << "  throw new TProtocolException(TProtocolException.UNKNOWN, \"Required field '"
+          << (*f_iter)->get_name()
+          << "' was not found in serialized data! Struct: \" + toString());" << endl << indent()
+          << "}" << endl;
+    }
+  }
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+// generates haxe method to perform various checks
+// (e.g. check that all required fields are set)
+void t_haxe_generator::generate_haxe_validator(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public function validate() : Void {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      if (type_can_be_null((*f_iter)->get_type())) {
+        indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
+        indent(out)
+            << "  throw new TProtocolException(TProtocolException.UNKNOWN, \"Required field '"
+            << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl;
+        indent(out) << "}" << endl;
+      } else {
+        indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
+                    << "' because it's a primitive." << endl;
+      }
+    }
+  }
+
+  // check that fields of type enum have valid values
+  out << indent() << "// check that fields of type enum have valid values" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    t_type* type = field->get_type();
+    // if field is an enum, check that its value is valid
+    if (type->is_enum()) {
+      indent(out) << "if (" << generate_isset_check(field) << " && !"
+                  << get_cap_name(get_enum_class_name(type)) << ".VALID_VALUES.contains("
+                  << field->get_name() << ")){" << endl;
+      indent_up();
+      indent(out) << "throw new TProtocolException(TProtocolException.UNKNOWN, \"The field '"
+                  << field->get_name() << "' has been assigned the invalid value \" + "
+                  << field->get_name() << ");" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_haxe_struct_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public function write(oprot:TProtocol) : Void {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl;
+  indent(out) << "oprot.IncrementRecursionDepth();" << endl;
+  indent(out) << "try" << endl;
+  scope_up(out);
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent(out) << "oprot.writeFieldStop();" << endl;
+  indent(out) << "oprot.writeStructEnd();" << endl;
+
+  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+  indent(out) << "catch(e:Dynamic)" << endl;
+  scope_up(out);
+  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
+  indent(out) << "throw e;" << endl;
+  scope_down(out);
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct,
+ * which is a function result. These fields are only written
+ * if they are set in the Isset array, and only one of them
+ * can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_haxe_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public function write(oprot:TProtocol) : Void {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "oprot.IncrementRecursionDepth();" << endl;
+  indent(out) << "try" << endl;
+  scope_up(out);
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
+
+    indent_up();
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+
+  indent(out) << endl;
+  indent(out) << "oprot.writeFieldStop();" << endl;
+  indent(out) << "oprot.writeStructEnd();" << endl;
+
+  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+  indent(out) << "catch(e:Dynamic)" << endl;
+  scope_up(out);
+  indent(out) << "oprot.DecrementRecursionDepth();" << endl;
+  indent(out) << "throw e;" << endl;
+  scope_down(out);
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+void t_haxe_generator::generate_reflection_getters(ostringstream& out,
+                                                   t_type* type,
+                                                   string field_name,
+                                                   string cap_name) {
+  (void)type;
+  (void)cap_name;
+  indent(out) << "case " << upcase_string(field_name) << "_FIELD_ID:" << endl;
+  indent_up();
+  indent(out) << "return this." << field_name << ";" << endl;
+  indent_down();
+}
+
+void t_haxe_generator::generate_reflection_setters(ostringstream& out,
+                                                   t_type* type,
+                                                   string field_name,
+                                                   string cap_name) {
+  (void)type;
+  (void)cap_name;
+  indent(out) << "case " << upcase_string(field_name) << "_FIELD_ID:" << endl;
+  indent_up();
+  indent(out) << "if (value == null) {" << endl;
+  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
+  indent(out) << "} else {" << endl;
+  indent(out) << "  this." << field_name << " = value;" << endl;
+  indent(out) << "}" << endl << endl;
+
+  indent_down();
+}
+
+void t_haxe_generator::generate_generic_field_getters_setters(std::ofstream& out,
+                                                              t_struct* tstruct) {
+
+  std::ostringstream getter_stream;
+  std::ostringstream setter_stream;
+
+  // build up the bodies of both the getter and setter at once
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    indent_up();
+    generate_reflection_setters(setter_stream, type, field_name, cap_name);
+    generate_reflection_getters(getter_stream, type, field_name, cap_name);
+    indent_down();
+  }
+
+  // create the setter
+  indent(out) << "public function setFieldValue(fieldID : Int, value : Dynamic) : Void {" << endl;
+  indent_up();
+
+  if (fields.size() > 0) {
+    indent(out) << "switch (fieldID) {" << endl;
+    out << setter_stream.str();
+    indent(out) << "default:" << endl;
+    indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+    indent(out) << "}" << endl;
+  } else {
+    indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // create the getter
+  indent(out) << "public function getFieldValue(fieldID : Int) : Dynamic {" << endl;
+  indent_up();
+
+  if (fields.size() > 0) {
+    indent(out) << "switch (fieldID) {" << endl;
+    out << getter_stream.str();
+    indent(out) << "default:" << endl;
+    indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+    indent(out) << "}" << endl;
+  } else {
+    indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+  }
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+// Creates a generic isSet method that takes the field number as argument
+void t_haxe_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // create the isSet method
+  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
+                 "value) and false otherwise" << endl;
+  indent(out) << "public function isSet(fieldID : Int) : Bool {" << endl;
+  indent_up();
+  if (fields.size() > 0) {
+    indent(out) << "switch (fieldID) {" << endl;
+
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = *f_iter;
+      indent(out) << "case " << upcase_string(field->get_name()) << "_FIELD_ID:" << endl;
+      indent_up();
+      indent(out) << "return " << generate_isset_check(field) << ";" << endl;
+      indent_down();
+    }
+
+    indent(out) << "default:" << endl;
+    indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+    indent(out) << "}" << endl;
+  } else {
+    indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a set of property setters/getters for the given struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_property_getters_setters(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    // Simple getter
+    generate_haxe_doc(out, field);
+    indent(out) << "public function get_" << field_name << "() : " << get_cap_name(type_name(type))
+                << " {" << endl;
+    indent_up();
+    indent(out) << "return this." << field_name << ";" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Simple setter
+    generate_haxe_doc(out, field);
+    indent(out) << "public function set_" << field_name << "(" << field_name << ":"
+                << get_cap_name(type_name(type)) << ") : " << get_cap_name(type_name(type)) << " {"
+                << endl;
+    indent_up();
+    indent(out) << "this." << field_name << " = " << field_name << ";" << endl;
+    generate_isset_set(out, field);
+    indent(out) << "return this." << field_name << ";" << endl;
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Unsetter
+    indent(out) << "public function unset" << cap_name << "() : Void {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "this." << field_name << " = null;" << endl;
+    } else {
+      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // isSet method
+    indent(out) << "// Returns true if field " << field_name
+                << " is set (has been assigned a value) and false otherwise" << endl;
+    indent(out) << "public function is" << get_cap_name("set") << cap_name << "() : Bool {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "return this." << field_name << " != null;" << endl;
+    } else {
+      indent(out) << "return this.__isset_" << field_name << ";" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a toString() method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_haxe_struct_tostring(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public "
+      << "function toString() : String {" << endl;
+  indent_up();
+
+  out << indent() << "var ret : String = \"" << tstruct->get_name() << "(\";" << endl;
+  out << indent() << "var first : Bool = true;" << endl << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+
+    t_field* field = (*f_iter);
+
+    if (!first) {
+      indent(out) << "if (!first) ret +=  \", \";" << endl;
+    }
+    indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl;
+    bool can_be_null = type_can_be_null(field->get_type());
+    if (can_be_null) {
+      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
+      indent(out) << "  ret += \"null\";" << endl;
+      indent(out) << "} else {" << endl;
+      indent_up();
+    }
+
+    if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
+      indent(out) << "  ret += \"BINARY\";" << endl;
+    } else if (field->get_type()->is_enum()) {
+      indent(out) << "var " << field->get_name()
+                  << "_name : String = " << get_cap_name(get_enum_class_name(field->get_type()))
+                  << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl;
+      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
+      indent(out) << "  ret += " << field->get_name() << "_name;" << endl;
+      indent(out) << "  ret += \" (\";" << endl;
+      indent(out) << "}" << endl;
+      indent(out) << "ret += this." << field->get_name() << ";" << endl;
+      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
+      indent(out) << "  ret += \")\";" << endl;
+      indent(out) << "}" << endl;
+    } else {
+      indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl;
+    }
+
+    if (can_be_null) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    indent(out) << "first = false;" << endl;
+
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    first = false;
+  }
+  out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a static map with meta data to store information such as fieldID to
+ * fieldName mapping
+ *
+ * @param tstruct The struct definition
+ */
+void t_haxe_generator::generate_haxe_meta_data_map(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Static Map with fieldID -> FieldMetaData mappings
+  indent(out) << "inline static var metaDataMap : IntMap = new IntMap();" << endl;
+
+  if (fields.size() > 0) {
+    // Populate map
+    scope_up(out);
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = *f_iter;
+      std::string field_name = field->get_name();
+      indent(out) << "metaDataMap[" << upcase_string(field_name)
+                  << "_FIELD_ID] = new FieldMetaData(\"" << field_name << "\", ";
+
+      // Set field requirement type (required, optional, etc.)
+      if (field->get_req() == t_field::T_REQUIRED) {
+        out << "TFieldRequirementType.REQUIRED, ";
+      } else if (field->get_req() == t_field::T_OPTIONAL) {
+        out << "TFieldRequirementType.OPTIONAL, ";
+      } else {
+        out << "TFieldRequirementType.DEFAULT, ";
+      }
+
+      // Create value meta data
+      generate_field_value_meta_data(out, field->get_type());
+      out << ");" << endl;
+    }
+    scope_down(out);
+  }
+}
+
+/**
+ * Returns a string with the haxe representation of the given thrift type
+ * (e.g. for the type struct it returns "TType.STRUCT")
+ */
+std::string t_haxe_generator::get_haxe_type_string(t_type* type) {
+  if (type->is_list()) {
+    return "TType.LIST";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_typedef()) {
+    return get_haxe_type_string(((t_typedef*)type)->get_type());
+  } else if (type->is_base_type()) {
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_VOID:
+      return "TType.VOID";
+      break;
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+      break;
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+      break;
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+      break;
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+      break;
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+      break;
+    default:
+      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
+                               + "\" passed to t_haxe_generator::get_haxe_type_string!");
+      break; // This should never happen!
+    }
+  } else {
+    throw std::runtime_error(
+        "Unknown thrift type \"" + type->get_name()
+        + "\" passed to t_haxe_generator::get_haxe_type_string!"); // This should never happen!
+  }
+}
+
+void t_haxe_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+  out << endl;
+  indent_up();
+  indent_up();
+  if (type->is_struct()) {
+    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type);
+  } else if (type->is_container()) {
+    if (type->is_list()) {
+      indent(out) << "new ListMetaData(TType.LIST, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else if (type->is_set()) {
+      indent(out) << "new SetMetaData(TType.SET, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else { // map
+      indent(out) << "new MapMetaData(TType.MAP, ";
+      t_type* key_type = ((t_map*)type)->get_key_type();
+      t_type* val_type = ((t_map*)type)->get_val_type();
+      generate_field_value_meta_data(out, key_type);
+      out << ", ";
+      generate_field_value_meta_data(out, val_type);
+    }
+  } else {
+    indent(out) << "new FieldValueMetaData(" << get_haxe_type_string(type);
+  }
+  out << ")";
+  indent_down();
+  indent_down();
+}
+
+/**
+ * Generates a thrift service. In C++, this comprises an entirely separate
+ * header and source file. The header file defines the methods and includes
+ * the data types defined in the main header file, and the implementation
+ * file contains implementations of the basic printer and default interfaces.
+ *
+ * @param tservice The service definition
+ */
+void t_haxe_generator::generate_service(t_service* tservice) {
+  // Make interface file
+  string f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + ".hx";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << haxe_package() << ";" << endl;
+
+  f_service_ << endl << haxe_type_imports() << haxe_thrift_imports()
+             << haxe_thrift_gen_imports(tservice);
+
+  if (tservice->get_extends() != NULL) {
+    t_type* parent = tservice->get_extends();
+    string parent_namespace = parent->get_program()->get_namespace("haxe");
+    if (!parent_namespace.empty() && parent_namespace != package_name_) {
+      f_service_ << "import " << type_name(parent) << ";" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_interface(tservice);
+
+  f_service_.close();
+
+  // Now make the implementation/client file
+  f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "Impl.hx";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << haxe_package() << ";" << endl << endl << haxe_type_imports()
+             << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice) << endl;
+
+  if (tservice->get_extends() != NULL) {
+    t_type* parent = tservice->get_extends();
+    string parent_namespace = parent->get_program()->get_namespace("haxe");
+    if (!parent_namespace.empty() && parent_namespace != package_name_) {
+      f_service_ << "import " << type_name(parent) << "Impl;" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_client(tservice);
+
+  f_service_.close();
+
+  // Now make the helper class files
+  generate_service_helpers(tservice);
+
+  // Now make the processor/server file
+  f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "Processor.hx";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << haxe_package() << ";" << endl << endl << haxe_type_imports()
+             << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice) << endl;
+
+  if (!package_name_.empty()) {
+    f_service_ << "import " << package_name_ << ".*;" << endl;
+    f_service_ << "import " << package_name_ << "." << get_cap_name(service_name_).c_str()
+               << "Impl;" << endl;
+    f_service_ << endl;
+  }
+
+  generate_service_server(tservice);
+
+  f_service_.close();
+}
+
+/**
+ * Generates the code snippet for the onSuccess callbacks
+ *
+ * @param tfunction The service function to generate code for.
+ */
+string t_haxe_generator::generate_service_method_onsuccess(t_function* tfunction,
+                                                           bool as_type,
+                                                           bool omit_name) {
+  if (tfunction->is_oneway()) {
+    return "";
+  }
+
+  string name = "";
+  if (!omit_name) {
+    name = "onSuccess";
+    if (as_type) {
+      name += " : ";
+    }
+  }
+
+  if (tfunction->get_returntype()->is_void()) {
+    if (as_type) {
+      return name + "Void->Void = null";
+    } else {
+      return name + "() : Void";
+    }
+  }
+
+  if (as_type) {
+    return name + type_name(tfunction->get_returntype()) + "->Void = null";
+  } else {
+    return name + "( retval : " + type_name(tfunction->get_returntype()) + ")";
+  }
+}
+
+/**
+ * Generates a service method header
+ *
+ * @param tfunction The service function to generate code for.
+ */
+void t_haxe_generator::generate_service_method_signature(t_function* tfunction, bool is_interface) {
+  if (callbacks_) {
+    generate_service_method_signature_callback(tfunction, is_interface);
+  } else {
+    generate_service_method_signature_normal(tfunction, is_interface);
+  }
+}
+
+/**
+ * Generates a service method header in "normal" style
+ *
+ * @param tfunction The service function to generate code for.
+ */
+void t_haxe_generator::generate_service_method_signature_normal(t_function* tfunction,
+                                                                bool is_interface) {
+  if (is_interface) {
+    indent(f_service_) << function_signature_normal(tfunction) << ";" << endl << endl;
+  } else {
+    indent(f_service_) << "public " << function_signature_normal(tfunction) << " {" << endl;
+  }
+}
+
+/**
+ * Generates a service method header in "callback" style
+ *
+ * @param tfunction The service function to generate code for.
+ */
+void t_haxe_generator::generate_service_method_signature_callback(t_function* tfunction,
+                                                                  bool is_interface) {
+  if (!tfunction->is_oneway()) {
+    std::string on_success_impl = generate_service_method_onsuccess(tfunction, false, false);
+    indent(f_service_) << "// function onError(Dynamic) : Void;" << endl;
+    indent(f_service_) << "// function " << on_success_impl.c_str() << ";" << endl;
+  }
+
+  if (is_interface) {
+    indent(f_service_) << function_signature_callback(tfunction) << ";" << endl << endl;
+  } else {
+    indent(f_service_) << "public " << function_signature_callback(tfunction) << " {" << endl;
+  }
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_haxe_generator::generate_service_interface(t_service* tservice) {
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends_iface = " extends " + tservice->get_extends()->get_name();
+  }
+
+  generate_haxe_doc(f_service_, tservice);
+  // generate_rtti_decoration(f_service_); - not yet, because of
+  // https://github.com/HaxeFoundation/haxe/issues/3626
+  generate_macro_decoration(f_service_);
+  f_service_ << indent() << "interface " << get_cap_name(service_name_) << extends_iface << " {"
+             << endl << endl;
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_haxe_doc(f_service_, *f_iter);
+    generate_service_method_signature(*f_iter, true);
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates structs for all the service args and return types
+ *
+ * @param tservice The service
+ */
+void t_haxe_generator::generate_service_helpers(t_service* tservice) {
+  f_service_ << endl << endl;
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_haxe_struct(ts, false);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_haxe_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = get_cap_name(tservice->get_extends()->get_name());
+    extends_client = " extends " + extends + "Impl";
+  }
+
+  generate_rtti_decoration(f_service_);
+  // build macro is inherited from interface
+  indent(f_service_) << "class " << get_cap_name(service_name_) << "Impl" << extends_client
+                     << " implements " << get_cap_name(service_name_) << " {" << endl << endl;
+  indent_up();
+
+  indent(f_service_) << "public function new( iprot : TProtocol, oprot : TProtocol = null)" << endl;
+  scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ << indent() << "iprot_ = iprot;" << endl;
+    f_service_ << indent() << "if (oprot == null) {" << endl;
+    indent_up();
+    f_service_ << indent() << "oprot_ = iprot;" << endl;
+    indent_down();
+    f_service_ << indent() << "} else {" << endl;
+    indent_up();
+    f_service_ << indent() << "oprot_ = oprot;" << endl;
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+  } else {
+    f_service_ << indent() << "super(iprot, oprot);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "private var iprot_ : TProtocol;" << endl << indent()
+               << "private var oprot_ : TProtocol;" << endl << indent()
+               << "private var seqid_ : Int;" << endl << endl;
+
+    indent(f_service_) << "public function getInputProtocol() : TProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.iprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    indent(f_service_) << "public function getOutputProtocol() : TProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.oprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    generate_service_method_signature(*f_iter, false);
+
+    indent_up();
+
+    // Get the struct of function call params
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    string argsname = get_cap_name((*f_iter)->get_name() + "_args");
+    vector<t_field*>::const_iterator fld_iter;
+    const vector<t_field*>& fields = arg_struct->get_members();
+
+    // Serialize the request
+    string calltype = (*f_iter)->is_oneway() ? "ONEWAY" : "CALL";
+    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname
+               << "\", TMessageType." << calltype << ", seqid_));" << endl << indent()
+               << "var args : " << argsname << " = new " << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
+               << "oprot_.writeMessageEnd();" << endl;
+
+    if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
+      f_service_ << indent() << "var retval : " << type_name((*f_iter)->get_returntype()) << ";"
+                 << endl;
+    }
+
+    if ((*f_iter)->is_oneway()) {
+      f_service_ << indent() << "oprot_.getTransport().flush();" << endl;
+    } else {
+      indent(f_service_) << "oprot_.getTransport().flush(function(error:Dynamic) : Void {" << endl;
+      indent_up();
+      if (callbacks_) {
+        indent(f_service_) << "try {" << endl;
+        indent_up();
+      }
+      string resultname = get_cap_name((*f_iter)->get_name() + "_result");
+      indent(f_service_) << "if (error != null) {" << endl;
+      indent_up();
+      if (callbacks_) {
+        indent(f_service_) << "if (onError != null) onError(error);" << endl;
+        indent(f_service_) << "return;" << endl;
+      } else {
+        indent(f_service_) << "throw error;" << endl;
+      }
+      indent_down();
+      indent(f_service_) << "}" << endl;
+      indent(f_service_) << "var msg : TMessage = iprot_.readMessageBegin();" << endl;
+      indent(f_service_) << "if (msg.type == TMessageType.EXCEPTION) {" << endl;
+      indent_up();
+      indent(f_service_) << "var x = TApplicationException.read(iprot_);" << endl;
+      indent(f_service_) << "iprot_.readMessageEnd();" << endl;
+      if (callbacks_) {
+        indent(f_service_) << "if (onError != null) onError(x);" << endl;
+        indent(f_service_) << "return;" << endl;
+      } else {
+        indent(f_service_) << "throw x;" << endl;
+      }
+      indent_down();
+      indent(f_service_) << "}" << endl;
+      indent(f_service_) << "var result : " << resultname << " = new " << resultname << "();"
+                         << endl;
+      indent(f_service_) << "result.read(iprot_);" << endl;
+      indent(f_service_) << "iprot_.readMessageEnd();" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "if (result." << generate_isset_check("success") << ") {" << endl;
+        indent_up();
+        if (callbacks_) {
+          indent(f_service_) << "if (onSuccess != null) onSuccess(result.success);" << endl;
+          indent(f_service_) << "return;" << endl;
+        } else {
+          indent(f_service_) << "retval = result.success;" << endl;
+          indent(f_service_) << "return;" << endl;
+        }
+        indent_down();
+        indent(f_service_) << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        indent(f_service_) << "if (result." << (*x_iter)->get_name() << " != null) {" << endl;
+        indent_up();
+        if (callbacks_) {
+          indent(f_service_) << "if (onError != null) onError(result." << (*x_iter)->get_name()
+                             << ");" << endl;
+          indent(f_service_) << "return;" << endl;
+        } else {
+          indent(f_service_) << "throw result." << (*x_iter)->get_name() << ";" << endl;
+        }
+        indent_down();
+        indent(f_service_) << "}" << endl;
+      }
+
+      // If you get here it's an exception, unless a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        if (callbacks_) {
+          indent(f_service_) << "if (onSuccess != null) onSuccess();" << endl;
+        }
+        indent(f_service_) << "return;" << endl;
+      } else {
+        if (callbacks_) {
+          indent(f_service_) << "if (onError != null)" << endl;
+          indent_up();
+          indent(f_service_)
+              << "onError( new TApplicationException(TApplicationException.MISSING_RESULT," << endl;
+          indent(f_service_) << "                               \"" << (*f_iter)->get_name()
+                             << " failed: unknown result\"));" << endl;
+          indent_down();
+        } else {
+          indent(f_service_)
+              << "throw new TApplicationException(TApplicationException.MISSING_RESULT," << endl;
+          indent(f_service_) << "                            \"" << (*f_iter)->get_name()
+                             << " failed: unknown result\");" << endl;
+        }
+      }
+
+      if (callbacks_) {
+        indent_down();
+        indent(f_service_) << "} catch( e : TException) {" << endl;
+        indent_up();
+        indent(f_service_) << "if (onError != null) onError(e);" << endl;
+        indent_down();
+        indent(f_service_) << "}" << endl;
+      }
+
+      indent_down();
+      indent(f_service_) << "});" << endl;
+    }
+
+    if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
+      f_service_ << indent() << "return retval;" << endl;
+    }
+
+    // Close function
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl;
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_haxe_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // Extends stuff
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = get_cap_name(type_name(tservice->get_extends()));
+    extends_processor = " extends " + extends + "Processor";
+  }
+
+  // Generate the header portion
+  generate_rtti_decoration(f_service_);
+  generate_macro_decoration(f_service_);
+  indent(f_service_) << "class " << get_cap_name(service_name_) << "Processor" << extends_processor
+                     << " implements TProcessor {" << endl << endl;
+  indent_up();
+
+  f_service_ << indent() << "private var " << get_cap_name(service_name_)
+             << "_iface_ : " << get_cap_name(service_name_) << ";" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent()
+               << "private var PROCESS_MAP = new StringMap< Int->TProtocol->TProtocol->Void >();"
+               << endl;
+  }
+
+  f_service_ << endl;
+
+  indent(f_service_) << "public function new( iface : " << get_cap_name(service_name_) << ")"
+                     << endl;
+  scope_up(f_service_);
+  if (!extends.empty()) {
+    f_service_ << indent() << "super(iface);" << endl;
+  }
+  f_service_ << indent() << get_cap_name(service_name_) << "_iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "PROCESS_MAP.set(\"" << (*f_iter)->get_name() << "\", "
+               << (*f_iter)->get_name() << "());" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the server implementation
+  string override = "";
+  if (tservice->get_extends() != NULL) {
+    override = "override ";
+  }
+  indent(f_service_) << override
+                     << "public function process( iprot : TProtocol, oprot : TProtocol) : Bool"
+                     << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "var msg : TMessage = iprot.readMessageBegin();" << endl;
+
+  // TODO(mcslee): validate message, was the seqid etc. legit?
+  // AS- If all method is oneway:
+  // do you have an oprot?
+  // do you you need nullcheck?
+  f_service_
+      << indent() << "var fn  = PROCESS_MAP.get(msg.name);" << endl << indent()
+      << "if (fn == null) {" << endl << indent() << "  TProtocolUtil.skip(iprot, TType.STRUCT);"
+      << endl << indent() << "  iprot.readMessageEnd();" << endl << indent()
+      << "  var x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid "
+         "method name: '\"+msg.name+\"'\");" << endl << indent()
+      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
+      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
+      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
+      << "  return true;" << endl << indent() << "}" << endl << indent()
+      << "fn( msg.seqid, iprot, oprot);" << endl;
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_haxe_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  string resultname = get_cap_name(tfunction->get_name() + "_result");
+  t_struct result(program_, resultname);
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_haxe_struct(&result, false, true);
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_haxe_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open class
+  indent(f_service_) << "private function " << tfunction->get_name()
+                     << "() : Int->TProtocol->TProtocol->Void {" << endl;
+  indent_up();
+
+  // Open function
+  indent(f_service_) << "return function( seqid : Int, iprot : TProtocol, oprot : TProtocol) : Void"
+                     << endl;
+  scope_up(f_service_);
+
+  string argsname = get_cap_name(tfunction->get_name() + "_args");
+  string resultname = get_cap_name(tfunction->get_name() + "_result");
+
+  f_service_ << indent() << "var args : " << argsname << " = new " << argsname << "();" << endl
+             << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();"
+             << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "var result : " << resultname << " = new " << resultname << "();"
+               << endl;
+  }
+
+  // Try block for any  function to catch (defined or undefined) exceptions
+  f_service_ << indent() << "try {" << endl;
+  indent_up();
+
+  if (callbacks_) {
+    // callback function style onError/onSuccess
+
+    // Generate the function call
+    t_struct* arg_struct = tfunction->get_arglist();
+    const std::vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    f_service_ << indent();
+    f_service_ << get_cap_name(service_name_) << "_iface_." << tfunction->get_name() << "(";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+
+    if (tfunction->is_oneway()) {
+      f_service_ << ");" << endl;
+    } else {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      string on_success = generate_service_method_onsuccess(tfunction, false, true);
+      indent_up();
+      f_service_ << endl;
+      indent(f_service_) << "null,  // errors are thrown by the handler" << endl;
+      if (tfunction->get_returntype()->is_void()) {
+        indent(f_service_) << "null); // no retval" << endl;
+      } else {
+        indent(f_service_) << "function" << on_success.c_str() << " {" << endl;
+        if (!tfunction->get_returntype()->is_void()) {
+          indent_up();
+          indent(f_service_) << "result.success = retval;" << endl;
+          indent_down();
+        }
+        indent(f_service_) << "});" << endl;
+      }
+      indent_down();
+    }
+
+  } else {
+    // normal function():result style
+
+    // Generate the function call
+    t_struct* arg_struct = tfunction->get_arglist();
+    const std::vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    f_service_ << indent();
+    if (!(tfunction->is_oneway() || tfunction->get_returntype()->is_void())) {
+      f_service_ << "result.success = ";
+    }
+    f_service_ << get_cap_name(service_name_) << "_iface_." << tfunction->get_name() << "(";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+    f_service_ << ");" << endl;
+  }
+
+  indent_down();
+  f_service_ << indent() << "}";
+  if (!tfunction->is_oneway()) {
+    // catch exceptions defined in the IDL
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << " catch (" << (*x_iter)->get_name() << ":"
+                 << get_cap_name(type_name((*x_iter)->get_type(), false, false)) << ") {" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                   << (*x_iter)->get_name() << ";" << endl;
+        indent_down();
+        f_service_ << indent() << "}";
+      } else {
+        f_service_ << "}";
+      }
+    }
+  }
+
+  // always catch all exceptions to prevent from service denial
+  f_service_ << " catch (th : Dynamic) {" << endl;
+  indent_up();
+  indent(f_service_) << "trace(\"Internal error processing " << tfunction->get_name() << "\", th);"
+                     << endl;
+  if (!tfunction->is_oneway()) {
+    indent(f_service_) << "var x = new TApplicationException(TApplicationException.INTERNAL_ERROR, "
+                          "\"Internal error processing " << tfunction->get_name() << "\");" << endl;
+    indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+                       << "\", TMessageType.EXCEPTION, seqid));" << endl;
+    indent(f_service_) << "x.write(oprot);" << endl;
+    indent(f_service_) << "oprot.writeMessageEnd();" << endl;
+    indent(f_service_) << "oprot.getTransport().flush();" << endl;
+  }
+  indent(f_service_) << "return;" << endl;
+  indent_down();
+  f_service_ << indent() << "}" << endl;
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "return;" << endl;
+    scope_down(f_service_);
+
+    // Close class
+    indent_down();
+    f_service_ << indent() << "}" << endl << endl;
+    return;
+  }
+
+  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
+             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
+             << "oprot.getTransport().flush();" << endl;
+
+  // Close function
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Close class
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param prefix The variable name or container for this field
+ */
+void t_haxe_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    indent(out) << name << " = iprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "readBinary();";
+        } else {
+          out << "readString();";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool();";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte();";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16();";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32();";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64();";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble();";
+        break;
+      default:
+        throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32();";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, invokes read()
+ */
+void t_haxe_generator::generate_deserialize_struct(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   string prefix) {
+  out << indent() << prefix << " = new " << get_cap_name(type_name(tstruct)) << "();" << endl
+      << indent() << prefix << ".read(iprot);" << endl;
+}
+
+/**
+ * Deserializes a container by reading its size and then iterating
+ */
+void t_haxe_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  string obj;
+
+  if (ttype->is_map()) {
+    obj = tmp("_map");
+  } else if (ttype->is_set()) {
+    obj = tmp("_set");
+  } else if (ttype->is_list()) {
+    obj = tmp("_list");
+  }
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "var " << obj << " = iprot.readMapBegin();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "var " << obj << " = iprot.readSetBegin();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "var " << obj << " = iprot.readListBegin();" << endl;
+  }
+
+  indent(out) << prefix << " = new " << type_name(ttype, false, true)
+              // size the collection correctly
+              << "("
+              << ");" << endl;
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for( " << i << " in 0 ... " << obj << ".size)" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "iprot.readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot.readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "iprot.readListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_haxe_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey) << endl;
+  indent(out) << declare_field(&fval) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << ".set( " << key << ", " << val << ");" << endl;
+}
+
+/**
+ * Deserializes a set element
+ */
+void t_haxe_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
+}
+
+/**
+ * Deserializes a list element
+ */
+void t_haxe_generator::generate_deserialize_list_element(ofstream& out,
+                                                         t_list* tlist,
+                                                         string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_haxe_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + tfield->get_name());
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = prefix + tfield->get_name();
+    indent(out) << "oprot.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "writeBinary(" << name << ");";
+        } else {
+          out << "writeString(" << name << ");";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ");";
+        break;
+      default:
+        throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ");";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_haxe_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  out << indent() << prefix << ".write(oprot);" << endl;
+}
+
+/**
+ * Serializes a container by writing its size then the elements.
+ *
+ * @param ttype  The type of container
+ * @param prefix String prefix for fields
+ */
+void t_haxe_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    string iter = tmp("_key");
+    string counter = tmp("_sizeCounter");
+    indent(out) << "var " << counter << " : Int = 0;" << endl;
+    indent(out) << "for( " << iter << " in " << prefix << ") {" << endl;
+    indent(out) << "  " << counter << +"++;" << endl;
+    indent(out) << "}" << endl;
+
+    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));"
+                << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                << ", " << prefix << ".size));" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListBegin(new TList("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
+                << endl;
+  }
+
+  string iter = tmp("elem");
+  if (ttype->is_map()) {
+    indent(out) << "for( " << iter << " in " << prefix << ".keys())" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "for( " << iter << " in " << prefix << ".toArray())" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "for( " << iter << " in " << prefix << ")" << endl;
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ */
+void t_haxe_generator::generate_ser

<TRUNCATED>

[21/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc
new file mode 100644
index 0000000..eba94c0
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc
@@ -0,0 +1,3301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ostream;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Objective-C code generator.
+ *
+ * mostly copy/pasting/tweaking from mcslee's work.
+ */
+class t_cocoa_generator : public t_oop_generator {
+public:
+  t_cocoa_generator(t_program* program,
+                    const std::map<std::string, std::string>& parsed_options,
+                    const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    log_unexpected_ = false;
+    validate_required_ = false;
+    async_clients_ = false;
+    promise_kit_ = false;
+    debug_descriptions_ = false;
+    pods_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("log_unexpected") == 0) {
+        log_unexpected_ = true;
+      } else if( iter->first.compare("validate_required") == 0) {
+        validate_required_ = true;
+      } else if( iter->first.compare("async_clients") == 0) {
+        async_clients_ = true;
+      } else if( iter->first.compare("promise_kit") == 0) {
+        promise_kit_ = true;
+      } else if( iter->first.compare("debug_descriptions") == 0) {
+        debug_descriptions_ = true;
+      } else if( iter->first.compare("pods") == 0) {
+        pods_ = true;
+      } else {
+        throw "unknown option cocoa:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-cocoa";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(ostream& out,
+                         string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool defval = false);
+  std::string render_const_value(ostream& out,
+                                 t_type* type,
+                                 t_const_value* value,
+                                 bool box_it = false);
+
+  void generate_cocoa_struct(t_struct* tstruct, bool is_exception);
+  void generate_cocoa_struct_interface(std::ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false);
+  void generate_cocoa_struct_implementation(std::ofstream& out,
+                                            t_struct* tstruct,
+                                            bool is_xception = false,
+                                            bool is_result = false);
+  void generate_cocoa_struct_initializer_signature(std::ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_init_with_coder_method(ofstream& out,
+                                                    t_struct* tstruct,
+                                                    bool is_exception);
+  void generate_cocoa_struct_encode_with_coder_method(ofstream& out,
+                                                      t_struct* tstruct,
+                                                      bool is_exception);
+  void generate_cocoa_struct_copy_method(ofstream& out,
+                                         t_struct* tstruct,
+                                         bool is_exception);
+  void generate_cocoa_struct_hash_method(ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_is_equal_method(ofstream& out,
+                                             t_struct* tstruct,
+                                             bool is_exception);
+  void generate_cocoa_struct_field_accessor_implementations(std::ofstream& out,
+                                                            t_struct* tstruct,
+                                                            bool is_exception);
+  void generate_cocoa_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_description(std::ofstream& out, t_struct* tstruct);
+
+  std::string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
+  std::string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
+  void generate_function_helpers(t_service *tservice, t_function* tfunction);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_cocoa_service_protocol(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_async_protocol(std::ofstream& out, t_service* tservice);
+
+  void generate_cocoa_service_client_interface(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_client_async_interface(std::ofstream& out, t_service* tservice);
+
+  void generate_cocoa_service_client_send_function_implementation(ofstream& out,
+                                                                  t_service* tservice,
+                                                                  t_function* tfunction,
+                                                                  bool needs_protocol);
+  void generate_cocoa_service_client_send_function_invocation(ofstream& out, t_function* tfunction);
+  void generate_cocoa_service_client_send_async_function_invocation(ofstream& out,
+                                                                    t_function* tfunction,
+                                                                    string failureBlockName);
+  void generate_cocoa_service_client_recv_function_implementation(ofstream& out,
+                                                                  t_service* tservice,
+                                                                  t_function* tfunction,
+                                                                  bool needs_protocol);
+  void generate_cocoa_service_client_implementation(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_client_async_implementation(std::ofstream& out, t_service* tservice);
+
+  void generate_cocoa_service_server_interface(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_server_implementation(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string fieldName);
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string fieldName = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out,
+                                       t_list* tlist,
+                                       std::string index,
+                                       std::string listName);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string cocoa_prefix();
+  std::string cocoa_imports();
+  std::string cocoa_thrift_imports();
+  std::string type_name(t_type* ttype, bool class_ref = false, bool needs_mutable = false);
+  std::string element_type_name(t_type* ttype);
+  std::string base_type_name(t_base_type* tbase);
+  std::string declare_property(t_field* tfield);
+  std::string declare_property_isset(t_field* tfield);
+  std::string declare_property_unset(t_field* tfield);
+  std::string invalid_return_statement(t_function* tfunction);
+  std::string function_signature(t_function* tfunction, bool include_error);
+  std::string async_function_signature(t_function* tfunction, bool include_error);
+  std::string promise_function_signature(t_function* tfunction);
+  std::string argument_list(t_struct* tstruct, string protocol_name, bool include_error);
+  std::string type_to_enum(t_type* ttype);
+  std::string format_string_for_type(t_type* type);
+  std::string format_cast_for_type(t_type* type);
+  std::string call_field_setter(t_field* tfield, std::string fieldName);
+  std::string box(t_type *ttype, std::string field_name);
+  std::string unbox(t_type* ttype, std::string field_name);
+  std::string getter_name(string field_name);
+  std::string setter_name(string field_name);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+private:
+  std::string cocoa_prefix_;
+  std::string constants_declarations_;
+  int error_constant_;
+
+  /**
+   * File streams
+   */
+
+  std::ofstream f_header_;
+  std::ofstream f_impl_;
+
+  bool log_unexpected_;
+  bool validate_required_;
+  bool async_clients_;
+  bool promise_kit_;
+  bool debug_descriptions_;
+  bool pods_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ */
+void t_cocoa_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  cocoa_prefix_ = program_->get_namespace("cocoa");
+
+  // we have a .h header file...
+  string f_header_name = cocoa_prefix_ + capitalize(program_name_) + ".h";
+  string f_header_fullname = get_out_dir() + f_header_name;
+  f_header_.open(f_header_fullname.c_str());
+
+  f_header_ << autogen_comment() << endl;
+
+  f_header_ << cocoa_imports() << cocoa_thrift_imports();
+
+  // ...and a .m implementation file
+  string f_impl_name = cocoa_prefix_ + capitalize(program_name_) + ".m";
+  string f_impl_fullname = get_out_dir() + f_impl_name;
+  f_impl_.open(f_impl_fullname.c_str());
+
+  f_impl_ << autogen_comment() << endl;
+
+  f_impl_ << cocoa_imports() << cocoa_thrift_imports() << "#import \"" << f_header_name << "\""
+          << endl << endl;
+
+  error_constant_ = 60000;
+}
+
+/**
+ * Prints standard Cocoa imports
+ *
+ * @return List of imports for Cocoa libraries
+ */
+string t_cocoa_generator::cocoa_imports() {
+  return string() + "#import <Foundation/Foundation.h>\n" + "\n";
+}
+
+/**
+ * Prints thrift runtime imports
+ *
+ * @return List of imports necessary for thrift runtime
+ */
+string t_cocoa_generator::cocoa_thrift_imports() {
+
+  vector<string> includes_list;
+  includes_list.push_back("TProtocol.h");
+  includes_list.push_back("TProtocolFactory.h");
+  includes_list.push_back("TApplicationError.h");
+  includes_list.push_back("TProtocolError.h");
+  includes_list.push_back("TProtocolUtil.h");
+  includes_list.push_back("TProcessor.h");
+  includes_list.push_back("TBase.h");
+  includes_list.push_back("TAsyncTransport.h");
+  includes_list.push_back("TBaseClient.h");
+
+  std::ostringstream includes;
+
+  vector<string>::const_iterator i_iter;
+  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) {
+    includes << "#import ";
+    if (pods_) {
+      includes << "<Thrift/" << *i_iter << ">";
+    } else {
+      includes << "\"" << *i_iter << "\"";
+    }
+    includes << endl;
+  }
+
+  includes << endl;
+
+  if (promise_kit_) {
+    includes << "#import ";
+    if (pods_) {
+      includes << "<PromiseKit/PromiseKit.h>";
+    } else {
+      includes << "\"PromiseKit.h\"";
+    }
+    includes << endl;
+  }
+
+  // Include other Thrift includes
+  const vector<t_program*>& other_includes = program_->get_includes();
+  for (size_t i = 0; i < other_includes.size(); ++i) {
+    includes << "#import \""
+             << other_includes[i]->get_namespace("cocoa")
+             << capitalize(other_includes[i]->get_name())
+             << ".h\"" << endl;
+  }
+
+  includes << endl;
+
+  return includes.str();
+}
+
+/**
+ * Finish up generation.
+ */
+void t_cocoa_generator::close_generator() {
+  // stick our constants declarations at the end of the header file
+  // since they refer to things we are defining.
+  f_header_ << constants_declarations_ << endl;
+}
+
+/**
+ * Generates a typedef. This is just a simple 1-liner in objective-c
+ *
+ * @param ttypedef The type definition
+ */
+void t_cocoa_generator::generate_typedef(t_typedef* ttypedef) {
+  if (ttypedef->get_type()->is_map()) {
+    t_map *map = (t_map *)ttypedef->get_type();
+    if (map->get_key_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(map->get_key_type(), true) << ";" << endl;
+    }
+    if (map->get_val_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(map->get_val_type(), true) << ";" << endl;
+    }
+  }
+  else if (ttypedef->get_type()->is_set()) {
+    t_set *set = (t_set *)ttypedef->get_type();
+    if (set->get_elem_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(set->get_elem_type(), true) << ";" << endl;
+    }
+  }
+  else if (ttypedef->get_type()->is_list()) {
+    t_list *list = (t_list *)ttypedef->get_type();
+    if (list->get_elem_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(list->get_elem_type(), true) << ";" << endl;
+    }
+  }
+  f_header_ << indent() << "typedef " << type_name(ttypedef->get_type()) << " " << cocoa_prefix_
+            << ttypedef->get_symbolic() << ";" << endl << endl;
+  if (ttypedef->get_type()->is_container()) {
+    f_header_ << indent() << "typedef " << type_name(ttypedef->get_type(), false, true) << " " << cocoa_prefix_
+              << "Mutable" << ttypedef->get_symbolic() << ";" << endl << endl;
+  }
+}
+
+/**
+ * Generates code for an enumerated type. In Objective-C, this is
+ * essentially the same as the thrift definition itself, instead using
+ * NS_ENUM keyword in Objective-C.  For namespace purposes, the name of
+ * the enum is prefixed to each element in keeping with Cocoa & Swift
+ * standards.
+ *
+ * @param tenum The enumeration
+ */
+void t_cocoa_generator::generate_enum(t_enum* tenum) {
+  f_header_ << indent() << "typedef NS_ENUM(SInt32, " << cocoa_prefix_ << tenum->get_name() << ") {" << endl;
+  indent_up();
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  bool first = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_header_ << "," << endl;
+    }
+    f_header_ << indent() << cocoa_prefix_ << tenum->get_name() << (*c_iter)->get_name();
+    f_header_ << " = " << (*c_iter)->get_value();
+  }
+
+  indent_down();
+  f_header_ << endl << "};" << endl << endl;
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
+  std::ostringstream const_interface;
+
+  const_interface << "FOUNDATION_EXPORT NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain;" << endl
+                  << endl;
+
+
+  bool needs_class = false;
+
+  // Public constants for base types & strings
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    t_type* type = (*c_iter)->get_type()->get_true_type();
+    if (!type->is_container() && !type->is_struct()) {
+      const_interface << "FOUNDATION_EXPORT " << type_name(type) << " "
+                      << cocoa_prefix_ << capitalize((*c_iter)->get_name()) << ";" << endl;
+    }
+    else {
+      needs_class = true;
+    }
+  }
+
+
+  string constants_class_name = cocoa_prefix_ + capitalize(program_name_) + "Constants";
+
+  if (needs_class) {
+
+    const_interface << endl;
+
+    const_interface << "@interface " << constants_class_name << " : NSObject ";
+    scope_up(const_interface);
+    scope_down(const_interface);
+
+    // getter method for each constant defined.
+    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+      string name = (*c_iter)->get_name();
+      t_type* type = (*c_iter)->get_type()->get_true_type();
+      if (type->is_container() || type->is_struct()) {
+        t_type* type = (*c_iter)->get_type();
+        const_interface << endl << "+ (" << type_name(type) << ") " << name << ";" << endl;
+      }
+    }
+
+    const_interface << endl << "@end";
+  }
+
+  // this gets spit into the header file in ::close_generator
+  constants_declarations_ = const_interface.str();
+
+  f_impl_ << "NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain = "
+          << "@\"" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain\";" << endl << endl;
+
+  // variables in the .m hold all simple constant values
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    t_type* type = (*c_iter)->get_type();
+    f_impl_ << type_name(type) << " " << cocoa_prefix_ << name;
+    t_type* ttype = type->get_true_type();
+    if (!ttype->is_container() && !ttype->is_struct()) {
+      f_impl_ << " = " << render_const_value(f_impl_, type, (*c_iter)->get_value());
+    }
+    f_impl_ << ";" << endl;
+  }
+  f_impl_ << endl;
+
+  if (needs_class) {
+
+    f_impl_ << "@implementation " << constants_class_name << endl << endl;
+
+    // initialize complex constants when the class is loaded
+    f_impl_ << "+ (void) initialize ";
+    scope_up(f_impl_);
+
+    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+      t_type* ttype = (*c_iter)->get_type()->get_true_type();
+      if (ttype->is_container() || ttype->is_struct()) {
+        f_impl_ << endl;
+        print_const_value(f_impl_,
+                          cocoa_prefix_ + (*c_iter)->get_name(),
+                          (*c_iter)->get_type(),
+                          (*c_iter)->get_value(),
+                          false);
+        f_impl_ << ";" << endl;
+      }
+    }
+    scope_down(f_impl_);
+
+    // getter method for each constant
+    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+      string name = (*c_iter)->get_name();
+      t_type* type = (*c_iter)->get_type()->get_true_type();
+      if (type->is_container() || type->is_struct()) {
+        f_impl_ << endl << "+ (" << type_name(type) << ") " << name << " ";
+        scope_up(f_impl_);
+        indent(f_impl_) << "return " << cocoa_prefix_ << name << ";" << endl;
+        scope_down(f_impl_);
+      }
+    }
+
+    f_impl_ << "@end" << endl << endl;
+  }
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with protected data members, read(), write(), and getters and setters.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_struct(t_struct* tstruct) {
+  generate_cocoa_struct_interface(f_header_, tstruct, false);
+  generate_cocoa_struct_implementation(f_impl_, tstruct, false);
+}
+
+/**
+ * Exceptions are structs, but they inherit from NSException
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_xception(t_struct* txception) {
+  generate_cocoa_struct_interface(f_header_, txception, true);
+  generate_cocoa_struct_implementation(f_impl_, txception, true);
+}
+
+/**
+ * Generate the interface for a struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_interface(ofstream& out,
+                                                        t_struct* tstruct,
+                                                        bool is_exception) {
+
+  if (is_exception) {
+    out << "enum {" << endl
+        << "  " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() <<  " = -" << error_constant_++ << endl
+        << "};" << endl
+        << endl;
+  }
+
+  out << "@interface " << cocoa_prefix_ << tstruct->get_name() << " : ";
+
+  if (is_exception) {
+    out << "NSError ";
+  } else {
+    out << "NSObject ";
+  }
+  out << "<TBase, NSCoding, NSCopying> " << endl;
+
+  out << endl;
+
+  // properties
+  const vector<t_field*>& members = tstruct->get_members();
+  if (members.size() > 0) {
+    vector<t_field*>::const_iterator m_iter;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << indent() << declare_property(*m_iter) << endl;
+      out << indent() << declare_property_isset(*m_iter) << endl;
+      out << indent() << declare_property_unset(*m_iter) << endl;
+      out << endl;
+    }
+  }
+
+  out << endl;
+
+  // initializer for all fields
+  if (!members.empty()) {
+    generate_cocoa_struct_initializer_signature(out, tstruct);
+    out << ";" << endl;
+  }
+  out << endl;
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generate signature for initializer of struct with a parameter for
+ * each field.
+ */
+void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ofstream& out,
+                                                                    t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  indent(out) << "- (instancetype) initWith";
+  for (m_iter = members.begin(); m_iter != members.end();) {
+    if (m_iter == members.begin()) {
+      out << capitalize((*m_iter)->get_name());
+    } else {
+      out << (*m_iter)->get_name();
+    }
+    out << ": (" << type_name((*m_iter)->get_type()) << ") " << (*m_iter)->get_name();
+    ++m_iter;
+    if (m_iter != members.end()) {
+      out << " ";
+    }
+  }
+}
+
+/**
+ * Generate the initWithCoder method for this struct so it's compatible with
+ * the NSCoding protocol
+ */
+void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ofstream& out,
+                                                                     t_struct* tstruct,
+                                                                     bool is_exception) {
+
+  indent(out) << "- (instancetype) initWithCoder: (NSCoder *) decoder" << endl;
+  scope_up(out);
+
+  if (is_exception) {
+    // NSExceptions conform to NSCoding, so we can call super
+    indent(out) << "self = [super initWithCoder: decoder];" << endl;
+  } else {
+    indent(out) << "self = [super init];" << endl;
+  }
+
+  indent(out) << "if (self) ";
+  scope_up(out);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "if ([decoder containsValueForKey: @\"" << (*m_iter)->get_name() << "\"])"
+        << endl;
+    scope_up(out);
+    out << indent() << "_" << (*m_iter)->get_name() << " = ";
+    if (type_can_be_null(t)) {
+      out << "[decoder decodeObjectForKey: @\"" << (*m_iter)->get_name() << "\"];"
+          << endl;
+    } else if (t->is_enum()) {
+      out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+    } else {
+      t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_BOOL:
+        out << "[decoder decodeBoolForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I8:
+        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I16:
+        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I32:
+        out << "[decoder decodeInt32ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I64:
+        out << "[decoder decodeInt64ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "[decoder decodeDoubleForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      default:
+        throw "compiler error: don't know how to decode thrift type: "
+            + t_base_type::t_base_name(tbase);
+      }
+    }
+    out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl;
+    scope_down(out);
+  }
+
+  scope_down(out);
+
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the encodeWithCoder method for this struct so it's compatible with
+ * the NSCoding protocol
+ */
+void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ofstream& out,
+                                                                       t_struct* tstruct,
+                                                                       bool is_exception) {
+
+  indent(out) << "- (void) encodeWithCoder: (NSCoder *) encoder" << endl;
+  scope_up(out);
+
+  if (is_exception) {
+    // NSExceptions conform to NSCoding, so we can call super
+    out << indent() << "[super encodeWithCoder: encoder];" << endl;
+  }
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
+    scope_up(out);
+    if (type_can_be_null(t)) {
+      out << indent() << "[encoder encodeObject: _" << (*m_iter)->get_name() << " forKey: @\""
+          << (*m_iter)->get_name() << "\"];" << endl;
+    } else if (t->is_enum()) {
+      out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
+          << (*m_iter)->get_name() << "\"];" << endl;
+    } else {
+      t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_BOOL:
+        out << indent() << "[encoder encodeBool: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I8:
+        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I16:
+        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I32:
+        out << indent() << "[encoder encodeInt32: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I64:
+        out << indent() << "[encoder encodeInt64: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << indent() << "[encoder encodeDouble: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      default:
+        throw "compiler error: don't know how to encode thrift type: "
+            + t_base_type::t_base_name(tbase);
+      }
+    }
+    scope_down(out);
+  }
+
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the copy method for this struct
+ */
+void t_cocoa_generator::generate_cocoa_struct_copy_method(ofstream& out, t_struct* tstruct, bool is_exception) {
+  out << indent() << "- (instancetype) copyWithZone:(NSZone *)zone" << endl;
+  scope_up(out);
+
+  if (is_exception) {
+    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " errorWithDomain: self.domain code: self.code userInfo: self.userInfo];" << endl;
+  } else {
+    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " new];" << endl;
+  }
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
+    scope_up(out);
+    if (type_can_be_null(t)) {
+      out << indent() << "val." << (*m_iter)->get_name() << " = [self." << (*m_iter)->get_name() << " copy];";
+    } else {
+      out << indent() << "val." << (*m_iter)->get_name() << " = self." << (*m_iter)->get_name() << ";";
+    }
+    out << endl;
+    scope_down(out);
+  }
+
+  out << indent() << "return val;" << endl;
+
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the hash method for this struct
+ */
+void t_cocoa_generator::generate_cocoa_struct_hash_method(ofstream& out, t_struct* tstruct) {
+  indent(out) << "- (NSUInteger) hash" << endl;
+  scope_up(out);
+  out << indent() << "NSUInteger hash = 17;" << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "hash = (hash * 31) ^ _" << (*m_iter)->get_name()
+        << "IsSet ? 2654435761 : 0;" << endl;
+    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
+    scope_up(out);
+    if (type_can_be_null(t)) {
+      out << indent() << "hash = (hash * 31) ^ [_" << (*m_iter)->get_name() << " hash];" << endl;
+    } else {
+      out << indent() << "hash = (hash * 31) ^ [@(_" << (*m_iter)->get_name() << ") hash];"
+          << endl;
+    }
+    scope_down(out);
+  }
+
+  out << indent() << "return hash;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the isEqual method for this struct
+ */
+void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ofstream& out, t_struct* tstruct, bool is_exception) {
+  indent(out) << "- (BOOL) isEqual: (id) anObject" << endl;
+  scope_up(out);
+
+  indent(out) << "if (self == anObject) {" << endl;
+  indent_up();
+  indent(out) << "return YES;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  string class_name = cocoa_prefix_ + tstruct->get_name();
+
+  if (is_exception) {
+    indent(out) << "if (![super isEqual:anObject]) {" << endl;
+    indent_up();
+    indent(out) << "return NO;" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+  else {
+    indent(out) << "if (![anObject isKindOfClass:[" << class_name << " class]]) {" << endl;
+    indent_up();
+    indent(out) << "return NO;" << endl;
+    indent_down();
+    indent(out) << "}" << endl;
+  }
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  if (!members.empty()) {
+    indent(out) << class_name << " *other = (" << class_name << " *)anObject;" << endl;
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      string name = (*m_iter)->get_name();
+      if (type_can_be_null(t)) {
+        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl
+            << indent() << "    "
+            << "(_" << name << "IsSet && "
+            << "((_" << name << " || other->_" << name << ") && "
+            << "![_" << name << " isEqual:other->_" << name << "]))) {" << endl;
+      } else {
+        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl
+            << indent() << "    "
+            << "(_" << name << "IsSet && "
+            << "(_" << name << " != other->_" << name << "))) {" << endl;
+      }
+      indent_up();
+      indent(out) << "return NO;" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  out << indent() << "return YES;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate struct implementation.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_cocoa_generator::generate_cocoa_struct_implementation(ofstream& out,
+                                                             t_struct* tstruct,
+                                                             bool is_exception,
+                                                             bool is_result) {
+  indent(out) << "@implementation " << cocoa_prefix_ << tstruct->get_name() << endl << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // exceptions need to call the designated initializer on NSException
+  if (is_exception) {
+    out << indent() << "- (instancetype) init" << endl;
+    scope_up(out);
+    out << indent() << "return [super initWithDomain: " << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain" << endl
+        << indent() << "                        code: " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() << endl
+        << indent() << "                    userInfo: nil];" << endl;
+    scope_down(out);
+    out << endl;
+  } else {
+    // struct
+
+    // default initializer
+    // setup instance variables with default values
+    indent(out) << "- (instancetype) init" << endl;
+    scope_up(out);
+    indent(out) << "self = [super init];" << endl;
+    indent(out) << "if (self)";
+    scope_up(out);
+    if (members.size() > 0) {
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        t_type* t = get_true_type((*m_iter)->get_type());
+        if ((*m_iter)->get_value() != NULL) {
+          print_const_value(out,
+                            "self." + (*m_iter)->get_name(),
+                            t,
+                            (*m_iter)->get_value(),
+                            false);
+        }
+      }
+    }
+    scope_down(out);
+    indent(out) << "return self;" << endl;
+    scope_down(out);
+    out << endl;
+  }
+
+  // initializer with all fields as params
+  if (!members.empty()) {
+    generate_cocoa_struct_initializer_signature(out, tstruct);
+    out << endl;
+    scope_up(out);
+    if (is_exception) {
+      out << indent() << "self = [self init];" << endl;
+    } else {
+      out << indent() << "self = [super init];" << endl;
+    }
+
+    indent(out) << "if (self)";
+    scope_up(out);
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << indent() << "_" << (*m_iter)->get_name() << " = ";
+      if (get_true_type((*m_iter)->get_type())->is_container()) {
+        out << "[" << (*m_iter)->get_name() << " mutableCopy];" << endl;
+      } else {
+        out << (*m_iter)->get_name() << ";" << endl;
+      }
+      out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl;
+    }
+    scope_down(out);
+
+    out << indent() << "return self;" << endl;
+    scope_down(out);
+    out << endl;
+  }
+
+  // initWithCoder for NSCoding
+  generate_cocoa_struct_init_with_coder_method(out, tstruct, is_exception);
+  // encodeWithCoder for NSCoding
+  generate_cocoa_struct_encode_with_coder_method(out, tstruct, is_exception);
+  // hash and isEqual for NSObject
+  generate_cocoa_struct_hash_method(out, tstruct);
+  generate_cocoa_struct_is_equal_method(out, tstruct, is_exception);
+  // copy for NSObject
+  generate_cocoa_struct_copy_method(out, tstruct, is_exception);
+
+  // the rest of the methods
+  generate_cocoa_struct_field_accessor_implementations(out, tstruct, is_exception);
+  generate_cocoa_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_cocoa_struct_result_writer(out, tstruct);
+  } else {
+    generate_cocoa_struct_writer(out, tstruct);
+  }
+  generate_cocoa_struct_validator(out, tstruct);
+  generate_cocoa_struct_description(out, tstruct);
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_reader(ofstream& out, t_struct* tstruct) {
+  out << "- (BOOL) read: (id <TProtocol>) inProtocol error: (NSError *__autoreleasing *)__thriftError" << endl;
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables
+  indent(out) << "NSString * fieldName;" << endl;
+  indent(out) << "SInt32 fieldType;" << endl;
+  indent(out) << "SInt32 fieldID;" << endl;
+  out << endl;
+
+  indent(out) << "if (![inProtocol readStructBeginReturningName: NULL error: __thriftError]) return NO;" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out)
+      << "if (![inProtocol readFieldBeginReturningName: &fieldName type: &fieldType fieldID: &fieldID error: __thriftError]) return NO;"
+      << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (fieldType == TTypeSTOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (fieldID)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (fieldType == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "fieldValue");
+    indent(out) << call_field_setter(*f_iter, "fieldValue") << endl;
+
+    indent_down();
+    out << indent() << "} else { " << endl;
+    if (log_unexpected_) {
+      out << indent() << "  NSLog(@\"%s: field ID %i has unexpected type %i.  Skipping.\", "
+                         "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl;
+    }
+
+    out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
+    out << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "default:" << endl;
+  if (log_unexpected_) {
+    out << indent() << "  NSLog(@\"%s: unexpected field ID %i with type %i.  Skipping.\", "
+                       "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl;
+  }
+
+  out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
+
+  out << indent() << "  break;" << endl;
+
+  scope_down(out);
+
+  // Read field end marker
+  indent(out) << "if (![inProtocol readFieldEnd: __thriftError]) return NO;" << endl;
+
+  scope_down(out);
+
+  out << indent() << "if (![inProtocol readStructEnd: __thriftError]) return NO;" << endl;
+
+  // performs various checks (e.g. check that all required fields are set)
+  if (validate_required_) {
+    out << indent() << "if (![self validate: __thriftError]) return NO;" << endl;
+  }
+
+  indent(out) << "return YES;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out << indent() << "if (_" << (*f_iter)->get_name() << "IsSet) {" << endl;
+    indent_up();
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name()
+                << "\" type: " << type_to_enum((*f_iter)->get_type())
+                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name());
+
+    // Write field closer
+    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
+
+    if (null_allowed) {
+      scope_down(out);
+    }
+    scope_down(out);
+  }
+  // Write the struct map
+  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl
+      << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl;
+
+  indent(out) << "return YES;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct, which
+ * is a function result. These fields are only written if they are
+ * set, and only one of them can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(_" << (*f_iter)->get_name() << "IsSet) {" << endl;
+    indent_up();
+
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name()
+                << "\" type: " << type_to_enum((*f_iter)->get_type())
+                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name());
+
+    // Write field closer
+    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
+
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+
+    indent_down();
+    indent(out) << "}";
+  }
+  // Write the struct map
+  out << endl << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;"
+      << endl << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;"
+      << endl;
+
+  indent(out) << "return YES;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to perform various checks
+ * (e.g. check that all required fields are set)
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_validator(ofstream& out, t_struct* tstruct) {
+  out << indent() << "- (BOOL) validate: (NSError *__autoreleasing *)__thriftError {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      out << indent() << "if (!_" << field->get_name() << "IsSet) ";
+      scope_up(out);
+      indent(out) << "if (__thriftError) ";
+      scope_up(out);
+      out << indent() << "*__thriftError = [NSError errorWithDomain: TProtocolErrorDomain" << endl
+          << indent() << "                                     code: TProtocolErrorUnknown" << endl
+          << indent() << "                                 userInfo: @{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMissingRequiredField)," << endl
+          << indent() << "                                             TProtocolErrorFieldNameKey: @\"" << (*f_iter)->get_name() << "\"}];" << endl;
+      scope_down(out);
+      scope_down(out);
+    }
+  }
+  indent(out) << "return YES;" << endl;
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generate property accessor methods for all fields in the struct.
+ * getter, setter, isset getter.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ofstream& out,
+                                                                             t_struct* tstruct,
+                                                                             bool is_exception) {
+  (void)is_exception;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = field_name;
+    cap_name[0] = toupper(cap_name[0]);
+
+    // Simple setter
+    indent(out) << "- (void) set" << cap_name << ": (" << type_name(type, false, true) << ") " << field_name
+                << " {" << endl;
+    indent_up();
+    indent(out) << "_" << field_name << " = " << field_name << ";" << endl;
+    indent(out) << "_" << field_name << "IsSet = YES;" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Unsetter - do we need this?
+    indent(out) << "- (void) unset" << cap_name << " {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "_" << field_name << " = nil;" << endl;
+    }
+    indent(out) << "_" << field_name << "IsSet = NO;" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a description method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_description(ofstream& out, t_struct* tstruct) {
+
+  // Allow use of debugDescription so the app can add description via a cateogory/extension
+  if (debug_descriptions_) {
+    out << indent() << "- (NSString *) debugDescription {" << endl;
+  }
+  else {
+    out << indent() << "- (NSString *) description {" << endl;
+  }
+  indent_up();
+
+  out << indent() << "NSMutableString * ms = [NSMutableString stringWithString: @\""
+      << cocoa_prefix_ << tstruct->get_name() << "(\"];" << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      indent(out) << "[ms appendString: @\"" << (*f_iter)->get_name() << ":\"];" << endl;
+    } else {
+      indent(out) << "[ms appendString: @\"," << (*f_iter)->get_name() << ":\"];" << endl;
+    }
+    t_type* ttype = (*f_iter)->get_type();
+    indent(out) << "[ms appendFormat: @\"" << format_string_for_type(ttype) << "\", "
+                << format_cast_for_type(ttype) << "_" << (*f_iter)->get_name() << "];" << endl;
+  }
+  out << indent() << "[ms appendString: @\")\"];" << endl << indent()
+      << "return [NSString stringWithString: ms];" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a thrift service.  In Objective-C this consists of a
+ * protocol definition, a client interface and a client implementation.
+ *
+ * @param tservice The service definition
+ */
+void t_cocoa_generator::generate_service(t_service* tservice) {
+  generate_cocoa_service_protocol(f_header_, tservice);
+  generate_cocoa_service_client_interface(f_header_, tservice);
+  generate_cocoa_service_server_interface(f_header_, tservice);
+  generate_cocoa_service_helpers(tservice);
+  generate_cocoa_service_client_implementation(f_impl_, tservice);
+  generate_cocoa_service_server_implementation(f_impl_, tservice);
+  if (async_clients_) {
+    generate_cocoa_service_async_protocol(f_header_, tservice);
+    generate_cocoa_service_client_async_interface(f_header_, tservice);
+    generate_cocoa_service_client_async_implementation(f_impl_, tservice);
+  }
+}
+
+/**
+ * Generates structs for all the service return types
+ *
+ * @param tservice The service
+ */
+void t_cocoa_generator::generate_cocoa_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    t_struct* ts = (*f_iter)->get_arglist();
+
+    string qname = function_args_helper_struct_type(tservice, *f_iter);
+
+    t_struct qname_ts = t_struct(ts->get_program(), qname);
+
+    const vector<t_field*>& members = ts->get_members();
+    vector<t_field*>::const_iterator m_iter;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      qname_ts.append(*m_iter);
+    }
+
+    generate_cocoa_struct_interface(f_impl_, &qname_ts, false);
+    generate_cocoa_struct_implementation(f_impl_, &qname_ts, false, false);
+    generate_function_helpers(tservice, *f_iter);
+  }
+}
+
+string t_cocoa_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return tservice->get_name() + "_" + tfunction->get_name();
+  } else {
+    return tservice->get_name() + "_" + tfunction->get_name() + "_result";
+  }
+}
+
+string t_cocoa_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) {
+  return tservice->get_name() + "_" + tfunction->get_name() + "_args";
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_cocoa_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  // create a result struct with a success field of the return type,
+  // and a field for each type of exception thrown
+  t_struct result(program_, function_result_helper_struct_type(tservice, tfunction));
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  // generate the result struct
+  generate_cocoa_struct_interface(f_impl_, &result, false);
+  generate_cocoa_struct_implementation(f_impl_, &result, false, true);
+}
+
+/**
+ * Generates a service protocol definition.
+ *
+ * @param tservice The service to generate a protocol definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_protocol(ofstream& out, t_service* tservice) {
+  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << " <NSObject>" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    out << "- " << function_signature(*f_iter, true) << ";"
+        << "  // throws ";
+    t_struct* xs = (*f_iter)->get_xceptions();
+    const std::vector<t_field*>& xceptions = xs->get_members();
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      out << type_name((*x_iter)->get_type()) + ", ";
+    }
+    out << "TException" << endl;
+  }
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates an asynchronous service protocol definition.
+ *
+ * @param tservice The service to generate a protocol definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_async_protocol(ofstream& out, t_service* tservice) {
+  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << "Async"
+      << " <NSObject>" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    out << "- " << async_function_signature(*f_iter, false) << ";" << endl;
+    if (promise_kit_) {
+      out << "- " << promise_function_signature(*f_iter) << ";" << endl;
+    }
+  }
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service client interface definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_interface(ofstream& out,
+                                                                t_service* tservice) {
+  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "Client : TBaseClient <"
+      << cocoa_prefix_ << tservice->get_name() << "> " << endl;
+
+  out << "- (id) initWithProtocol: (id <TProtocol>) protocol;" << endl;
+  out << "- (id) initWithInProtocol: (id <TProtocol>) inProtocol outProtocol: (id <TProtocol>) "
+         "outProtocol;" << endl;
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service client interface definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_async_interface(ofstream& out,
+                                                                      t_service* tservice) {
+  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "ClientAsync : TBaseClient <"
+      << cocoa_prefix_ << tservice->get_name() << "Async> " << endl
+      << endl;
+
+  out << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) protocolFactory "
+      << "transportFactory: (id <TAsyncTransportFactory>) transportFactory;" << endl;
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service server interface definition. In other words, the TProcess implementation for
+ *the
+ * service definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_server_interface(ofstream& out,
+                                                                t_service* tservice) {
+  out << "@interface " << cocoa_prefix_ << tservice->get_name()
+      << "Processor : NSObject <TProcessor> " << endl;
+
+  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_
+      << tservice->get_name() << ">) service;" << endl;
+  out << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service;" << endl;
+
+  out << "@end" << endl << endl;
+}
+
+void t_cocoa_generator::generate_cocoa_service_client_send_function_implementation(
+    ofstream& out,
+    t_service *tservice,
+    t_function* tfunction,
+    bool needs_protocol) {
+  string funname = tfunction->get_name();
+
+  t_function send_function(g_type_bool,
+                           string("send_") + tfunction->get_name(),
+                           tfunction->get_arglist());
+
+  string argsname = function_args_helper_struct_type(tservice, tfunction);
+
+  // Open function
+  indent(out) << "- (BOOL) send_" << tfunction->get_name() << argument_list(tfunction->get_arglist(), needs_protocol ? "outProtocol" : "", true) << endl;
+  scope_up(out);
+
+  // Serialize the request
+  out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\""
+      << (tfunction->is_oneway() ? " type: TMessageTypeONEWAY" : " type: TMessageTypeCALL")
+      << " sequenceID: 0 error: __thriftError]) return NO;" << endl;
+
+  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << argsname
+                  << "\" error: __thriftError]) return NO;" << endl;
+
+  // write out function parameters
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+    string fieldName = (*fld_iter)->get_name();
+    if (type_can_be_null((*fld_iter)->get_type())) {
+      out << indent() << "if (" << fieldName << " != nil)";
+      scope_up(out);
+    }
+    out << indent() << "if (![outProtocol writeFieldBeginWithName: @\"" << fieldName
+        << "\""
+           " type: " << type_to_enum((*fld_iter)->get_type())
+        << " fieldID: " << (*fld_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
+
+    generate_serialize_field(out, *fld_iter, fieldName);
+
+    out << indent() << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
+
+    if (type_can_be_null((*fld_iter)->get_type())) {
+      indent_down();
+      out << indent() << "}" << endl;
+    }
+  }
+
+  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl;
+  out << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "return YES;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+void t_cocoa_generator::generate_cocoa_service_client_recv_function_implementation(
+    ofstream& out,
+    t_service* tservice,
+    t_function* tfunction,
+    bool needs_protocol) {
+
+
+  // Open function
+  indent(out) << "- (BOOL) recv_" << tfunction->get_name();
+  if (!tfunction->get_returntype()->is_void()) {
+    out << ": (" << type_name(tfunction->get_returntype(), false, true) << " *) result ";
+    if (needs_protocol) {
+      out << "protocol";
+    } else {
+      out << "error";
+    }
+  }
+  if (needs_protocol) {
+    out << ": (id<TProtocol>) inProtocol error";
+  }
+  out << ": (NSError *__autoreleasing *)__thriftError" << endl;
+  scope_up(out);
+
+  // TODO(mcslee): Message validation here, was the seqid etc ok?
+
+  // check for an exception
+  out << indent() << "NSError *incomingException = [self checkIncomingMessageException: inProtocol];" << endl
+      << indent() << "if (incomingException)";
+  scope_up(out);
+  out << indent() << "if (__thriftError)";
+  scope_up(out);
+  out << indent() << "*__thriftError = incomingException;" << endl;
+  scope_down(out);
+  out << indent() << "return NO;" << endl;
+  scope_down(out);
+
+  // FIXME - could optimize here to reduce creation of temporary objects.
+  string resultname = function_result_helper_struct_type(tservice, tfunction);
+  out << indent() << cocoa_prefix_ << resultname << " * resulter = [" << cocoa_prefix_ << resultname << " new];" << endl;
+  indent(out) << "if (![resulter read: inProtocol error: __thriftError]) return NO;" << endl;
+  indent(out) << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
+
+  // Careful, only return _result if not a void function
+  if (!tfunction->get_returntype()->is_void()) {
+    out << indent() << "if (resulter.successIsSet)";
+    scope_up(out);
+    out << indent() << "*result = resulter.success;" << endl;
+    out << indent() << "return YES;" << endl;
+    scope_down(out);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+    out << indent() << "if (resulter." << (*x_iter)->get_name() << "IsSet)";
+    scope_up(out);
+    out << indent() << "if (__thriftError)";
+    scope_up(out);
+    out << indent() << "*__thriftError = [resulter " << (*x_iter)->get_name() << "];" << endl;
+    scope_down(out);
+    out << indent() << "return NO;" << endl;
+    scope_down(out);
+  }
+
+  // If you get here it's an exception, unless a void function
+  if (tfunction->get_returntype()->is_void()) {
+    indent(out) << "return YES;" << endl;
+  } else {
+    out << indent() << "if (__thriftError)";
+    scope_up(out);
+    out << indent() << "*__thriftError = [NSError errorWithDomain: TApplicationErrorDomain" << endl
+        << indent() << "                                     code: TApplicationErrorMissingResult" << endl
+        << indent() << "                                 userInfo: @{TApplicationErrorMethodKey: @\""
+        << tfunction->get_name() << "\"}];" << endl;
+    scope_down(out);
+    out << indent() << "return NO;" << endl;
+  }
+
+  // Close function
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates an invocation of a given 'send_' function.
+ *
+ * @param tfunction The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_send_function_invocation(
+                                                                               ofstream& out,
+                                                                               t_function* tfunction) {
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  out << indent() << "if (![self send_" << tfunction->get_name();
+  bool first = true;
+  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+    string fieldName = (*fld_iter)->get_name();
+    out << " ";
+    if (first) {
+      first = false;
+      out << ": " << fieldName;
+    } else {
+      out << fieldName << ": " << fieldName;
+    }
+  }
+  if (!fields.empty()) {
+    out << " error";
+  }
+  out << ": __thriftError]) " << invalid_return_statement(tfunction) << endl;
+}
+
+/**
+ * Generates an invocation of a given 'send_' function.
+ *
+ * @param tfunction The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_send_async_function_invocation(
+                                                                                     ofstream& out,
+                                                                                     t_function* tfunction,
+                                                                                     string failureBlockName) {
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  out << indent() << "if (![self send_" << tfunction->get_name();
+  bool first = true;
+  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+    string fieldName = (*fld_iter)->get_name();
+    out << " ";
+    if (first) {
+      first = false;
+      out << ": " << fieldName;
+    } else {
+      out << fieldName << ": " << fieldName;
+    }
+  }
+  if (!fields.empty()) {
+    out << " protocol";
+  }
+  out << ": protocol error: &thriftError]) ";
+  scope_up(out);
+  out << indent() << failureBlockName << "(thriftError);" << endl
+      << indent() << "return;" << endl;
+  scope_down(out);
+}
+
+/**
+ * Generates a service client implementation.
+ *
+ * @param tservice The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_implementation(ofstream& out,
+                                                                     t_service* tservice) {
+
+  string name = cocoa_prefix_ + tservice->get_name() + "Client";
+
+  out << "@interface " << name << " () ";
+  scope_up(out);
+  out << endl;
+  out << indent() << "id<TProtocol> inProtocol;" << endl;
+  out << indent() << "id<TProtocol> outProtocol;" << endl;
+  out << endl;
+  scope_down(out);
+  out << endl;
+  out << "@end" << endl << endl;
+
+  out << "@implementation " << name << endl;
+
+  // initializers
+  out << "- (id) initWithProtocol: (id <TProtocol>) protocol" << endl;
+  scope_up(out);
+  out << indent() << "return [self initWithInProtocol: protocol outProtocol: protocol];" << endl;
+  scope_down(out);
+  out << endl;
+
+  out << "- (id) initWithInProtocol: (id <TProtocol>) anInProtocol outProtocol: (id <TProtocol>) "
+         "anOutProtocol" << endl;
+  scope_up(out);
+  out << indent() << "self = [super init];" << endl;
+  out << indent() << "if (self) ";
+  scope_up(out);
+  out << indent() << "inProtocol = anInProtocol;" << endl;
+  out << indent() << "outProtocol = anOutProtocol;" << endl;
+  scope_down(out);
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+  out << endl;
+
+  // generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, false);
+
+    if (!(*f_iter)->is_oneway()) {
+      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, false);
+    }
+
+    // Open function
+    indent(out) << "- " << function_signature(*f_iter, true) << endl;
+    scope_up(out);
+    generate_cocoa_service_client_send_function_invocation(out, *f_iter);
+
+    out << indent() << "if (![[outProtocol transport] flush: __thriftError]) " << invalid_return_statement(*f_iter) << endl;
+    if (!(*f_iter)->is_oneway()) {
+      if ((*f_iter)->get_returntype()->is_void()) {
+        out << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": __thriftError]) return NO;" << endl;
+        out << indent() << "return YES;" << endl;
+      } else {
+        out << indent() << type_name((*f_iter)->get_returntype(), false, true) << " __result;" << endl
+            << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": &__result error: __thriftError]) "
+            << invalid_return_statement(*f_iter) << endl;
+        if (type_can_be_null((*f_iter)->get_returntype())) {
+          out << indent() << "return __result;" << endl;
+        } else {
+          out << indent() << "return @(__result);" << endl;
+        }
+      }
+    }
+    else {
+      out << indent() << "return YES;" << endl;
+    }
+    scope_down(out);
+    out << endl;
+  }
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service client implementation for its asynchronous interface.
+ *
+ * @param tservice The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ofstream& out,
+                                                                           t_service* tservice) {
+
+  string name = cocoa_prefix_ + tservice->get_name() + "ClientAsync";
+
+  out << "@interface " << name << " () ";
+  scope_up(out);
+  out << endl;
+  out << indent() << "id<TProtocolFactory> protocolFactory;" << endl;
+  out << indent() << "id<TAsyncTransportFactory> transportFactory;" << endl;
+  out << endl;
+  scope_down(out);
+  out << endl;
+  out << "@end" << endl << endl;
+
+
+  out << "@implementation " << name << endl
+      << endl << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) aProtocolFactory "
+                 "transportFactory: (id <TAsyncTransportFactory>) aTransportFactory;" << endl;
+
+  scope_up(out);
+  out << indent() << "self = [super init];" << endl;
+  out << indent() << "if (self) {" << endl;
+  out << indent() << "  protocolFactory = aProtocolFactory;" << endl;
+  out << indent() << "  transportFactory = aTransportFactory;" << endl;
+  out << indent() << "}" << endl;
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+  out << endl;
+
+  // generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, true);
+
+    if (!(*f_iter)->is_oneway()) {
+      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, true);
+    }
+
+    // Open function
+    indent(out) << "- " << async_function_signature(*f_iter, false) << endl;
+    scope_up(out);
+
+    out << indent() << "NSError *thriftError;" << endl
+        << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl
+        << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl
+        << endl;
+
+    generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "failureBlock");
+
+    out << indent() << "[transport flushWithCompletion:^{" << endl;
+    indent_up();
+
+    if (!(*f_iter)->is_oneway()) {
+      out << indent() << "NSError *thriftError;" << endl;
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl;
+      }
+      out << indent() << "if (![self recv_" << (*f_iter)->get_name();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        out << ": &result protocol";
+      }
+      out << ": protocol error: &thriftError]) ";
+      scope_up(out);
+      out << indent() << "failureBlock(thriftError);" << endl
+          << indent() << "return;" << endl;
+      scope_down(out);
+    }
+
+    out << indent() << "responseBlock(";
+    if (!(*f_iter)->is_oneway() && !(*f_iter)->get_returntype()->is_void()) {
+      out << "result";
+    }
+    out << ");" << endl;
+
+    indent_down();
+
+    out << indent() << "} failure:failureBlock];" << endl;
+
+    scope_down(out);
+
+    out << endl;
+
+    // Promise function
+    if (promise_kit_) {
+
+      indent(out) << "- " << promise_function_signature(*f_iter) << endl;
+      scope_up(out);
+
+      out << indent() << "return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {" << endl;
+      indent_up();
+
+      out << indent() << "NSError *thriftError;" << endl
+          << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl
+          << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl
+          << endl;
+
+      generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "resolver");
+
+      out << indent() << "[transport flushWithCompletion:^{" << endl;
+      indent_up();
+
+      if (!(*f_iter)->is_oneway()) {
+        out << indent() << "NSError *thriftError;" << endl;
+
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl;
+        }
+        out << indent() << "if (![self recv_" << (*f_iter)->get_name();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          out << ": &result protocol";
+        }
+        out << ": protocol error: &thriftError]) ";
+        scope_up(out);
+        out << indent() << "resolver(thriftError);" << endl
+            << indent() << "return;" << endl;
+        scope_down(out);
+      }
+
+      out << indent() << "resolver(";
+      if ((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void()) {
+        out << "@YES";
+      } else if (type_can_be_null((*f_iter)->get_returntype())) {
+        out << "result";
+      } else {
+        out << "@(result)";
+      }
+      out << ");" << endl;
+
+      indent_down();
+
+      out << indent() << "} failure:^(NSError *error) {" << endl;
+      indent_up();
+      out << indent() << "resolver(error);" << endl;
+      indent_down();
+      out << indent() << "}];" << endl;
+
+      indent_down();
+      out << indent() << "}];" << endl;
+
+      scope_down(out);
+
+      out << endl;
+
+    }
+
+  }
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service server implementation.  In other words the actual TProcessor implementation
+ * for the service.
+ *
+ * @param tservice The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_server_implementation(ofstream& out,
+                                                                     t_service* tservice) {
+
+  string name = cocoa_prefix_ + tservice->get_name() + "Processor";
+
+  out << "@interface " << name << " () ";
+
+  scope_up(out);
+  out << indent() << "id <" << cocoa_prefix_ << tservice->get_name() << "> service;" << endl;
+  out << indent() << "NSDictionary * methodMap;" << endl;
+  scope_down(out);
+
+  out << "@end" << endl << endl;
+
+  out << "@implementation " << name << endl;
+
+  // initializer
+  out << endl;
+  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ << tservice->get_name() << ">) aService" << endl;
+  scope_up(out);
+  out << indent() << "self = [super init];" << endl;
+  out << indent() << "if (self) ";
+  scope_up(out);
+  out << indent() << "service = aService;" << endl;
+  out << indent() << "methodMap = [NSMutableDictionary dictionary];" << endl;
+
+  // generate method map for routing incoming calls
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+    scope_up(out);
+    out << indent() << "SEL s = @selector(process_" << funname << "_withSequenceID:inProtocol:outProtocol:error:);" << endl;
+    out << indent() << "NSMethodSignature * sig = [self methodSignatureForSelector: s];" << endl;
+    out << indent() << "NSInvocation * invocation = [NSInvocation invocationWithMethodSignature: sig];" << endl;
+    out << indent() << "[invocation setSelector: s];" << endl;
+    out << indent() << "[invocation retainArguments];" << endl;
+    out << indent() << "[methodMap setValue: invocation forKey: @\"" << funname << "\"];" << endl;
+    scope_down(out);
+  }
+  scope_down(out);
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+
+  // implementation of the 'service' method which returns the service associated with this
+  // processor
+  out << endl;
+  out << indent() << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service" << endl;
+  out << indent() << "{" << endl;
+  out << indent() << "  return service;" << endl;
+  out << indent() << "}" << endl;
+
+  // implementation of the TProcess method, which dispatches the incoming call using the method map
+  out << endl;
+  out << indent() << "- (BOOL) processOnInputProtocol: (id <TProtocol>) inProtocol" << endl;
+  out << indent() << "                 outputProtocol: (id <TProtocol>) outProtocol" << endl;
+  out << indent() << "                          error: (NSError *__autoreleasing *)__thriftError" << endl;
+  out << indent() << "{" << endl;
+  out << indent() << "  NSString * messageName;" << endl;
+  out << indent() << "  SInt32 messageType;" << endl;
+  out << indent() << "  SInt32 seqID;" << endl;
+  out << indent() << "  if (![inProtocol readMessageBeginReturningName: &messageName" << endl;
+  out << indent() << "                                       type: &messageType" << endl;
+  out << indent() << "                                 sequenceID: &seqID" << endl;
+  out << indent() << "                                      error: __thriftError]) return NO;" << endl;
+  out << indent() << "  NSInvocation * invocation = [methodMap valueForKey: messageName];" << endl;
+  out << indent() << "  if (invocation == nil) {" << endl;
+  out << indent() << "    if (![TProtocolUtil skipType: TTypeSTRUCT onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "    NSError * x = [NSError errorWithDomain: TApplicationErrorDomain" << endl;
+  out << indent() << "                                      code: TApplicationErrorUnknownMethod" << endl;
+  out << indent() << "                                  userInfo: @{TApplicationErrorMethodKey: messageName}];" << endl;
+  out << indent() << "    if (![outProtocol writeMessageBeginWithName: messageName" << endl;
+  out << indent() << "                                           type: TMessageTypeEXCEPTION" << endl;
+  out << indent() << "                                     sequenceID: seqID" << endl;
+  out << indent() << "                                          error: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![x write: outProtocol error: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl;
+  out << indent() << "    return YES;" << endl;
+  out << indent() << "  }" << endl;
+  out << indent() << "  // NSInvocation does not conform to NSCopying protocol" << endl;
+  out << indent() << "  NSInvocation * i = [NSInvocation invocationWithMethodSignature: "
+                     "[invocation methodSignature]];" << endl;
+  out << indent() << "  [i setSelector: [invocation selector]];" << endl;
+  out << indent() << "  [i setArgument: &seqID atIndex: 2];" << endl;
+  out << indent() << "  [i setArgument: &inProtocol atIndex: 3];" << endl;
+  out << indent() << "  [i setArgument: &outProtocol atIndex: 4];" << endl;
+  out << indent() << "  [i setArgument: &__thriftError atIndex: 5];" << endl;
+  out << indent() << "  [i setTarget: self];" << endl;
+  out << indent() << "  [i invoke];" << endl;
+  out << indent() << "  return YES;" << endl;
+  out << indent() << "}" << endl;
+
+  // generate a process_XXXX method for each service function, which reads args, calls the service,
+  // and writes results
+  functions = tservice->get_functions();
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    out << endl;
+    string funname = (*f_iter)->get_name();
+    out << indent() << "- (BOOL) process_" << funname
+        << "_withSequenceID: (SInt32) seqID inProtocol: (id<TProtocol>) inProtocol outProtocol: "
+           "(id<TProtocol>) outProtocol error:(NSError *__autoreleasing *)__thriftError" << endl;
+    scope_up(out);
+    string argstype = cocoa_prefix_ + function_args_helper_struct_type(tservice, *f_iter);
+    out << indent() << argstype << " * args = [" << argstype << " new];" << endl;
+    out << indent() << "if (![args read: inProtocol error: __thriftError]) return NO;" << endl;
+    out << indent() << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
+
+    // prepare the result if not oneway
+    if (!(*f_iter)->is_oneway()) {
+      string resulttype = cocoa_prefix_ + function_result_helper_struct_type(tservice, *f_iter);
+      out << indent() << resulttype << " * result = [" << resulttype << " new];" << endl;
+    }
+
+    // make the call to the actual service object
+    out << indent();
+    if ((*f_iter)->get_returntype()->is_void()) {
+      out << "BOOL";
+    } else if (type_can_be_null((*f_iter)->get_returntype())) {
+      out << type_name((*f_iter)->get_returntype(), false, true);
+    } else {
+      out << "NSNumber *";
+    }
+    out << " serviceResult = ";
+    if ((*f_iter)->get_returntype()->get_true_type()->is_container()) {
+      out << "(" << type_name((*f_iter)->get_returntype(), false, true) << ")";
+    }
+    out << "[service " << funname;
+    // supplying arguments
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      string fieldName = (*fld_iter)->get_name();
+      if (first) {
+        first = false;
+        out << ": [args " << fieldName << "]";
+      } else {
+        out << " " << fieldName << ": [args " << fieldName << "]";
+      }
+    }
+    if (!fields.empty()) {
+      out << " error";
+    }
+    out << ": __thriftError];" << endl;
+    out << indent() << "if (!serviceResult) return NO;" << endl;
+    if (!(*f_iter)->get_returntype()->is_void()) {
+      out << indent() << "[result setSuccess: " << unbox((*f_iter)->get_returntype(), "serviceResult") << "];" << endl;
+    }
+
+    // write out the result if not oneway
+    if (!(*f_iter)->is_oneway()) {
+      out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" << endl;
+      out << indent() << "                                       type: TMessageTypeREPLY" << endl;
+      out << indent() << "                                 sequenceID: seqID" << endl;
+      out << indent() << "                                      error: __thriftError]) return NO;" << endl;
+      out << indent() << "if (![result write: outProtocol error: __thriftError]) return NO;" << endl;
+      out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
+      out << indent() << "if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl;
+    }
+    out << indent() << "return YES;" << endl;
+
+    scope_down(out);
+  }
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param fieldName The variable name for this field
+ */
+void t_cocoa_generator::generate_deserialize_field(ofstream& out,
+                                                   t_field* tfield,
+                                                   string fieldName) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, fieldName);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, fieldName);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << type_name(type) << " " << fieldName << ";" << endl;
+    indent(out) << "if (![inProtocol ";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + tfield->get_name();
+        break;
+      case t_base_type::TYPE_STRING:
+        if (((t_base_type*)type)->is_binary()) {
+          out << "readBinary:&" << fieldName << " error: __thriftError]";
+        } else {
+          out << "readString:&" << fieldName << " error: __thriftError]";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte:(UInt8 *)&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble:&" << fieldName << " error: __thriftError]";
+        break;
+      default:
+        throw "compiler error: no Objective-C name for base type "
+            + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32:&" << fieldName << " error: __thriftError]";
+    }
+    out << ") return NO;" << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, allocates the struct and invokes read:
+ */
+void t_cocoa_generator::generate_deserialize_struct(ofstream& out,
+                                                    t_struct* tstruct,
+                                                    string fieldName) {
+  indent(out) << type_name(tstruct) << fieldName << " = [[" << type_name(tstruct, true)
+              << " alloc] init];" << endl;
+  indent(out) << "if (![" << fieldName << " read: inProtocol error: __thriftError]) return NO;" << endl;
+}
+
+/**
+ * Deserializes a container by reading its size and then iterating
+ */
+void t_cocoa_generator::generate_deserialize_container(ofstream& out,
+                                                       t_type* ttype,
+                                                       string fieldName) {
+  string size = tmp("_size");
+  indent(out) << "SInt32 " << size << ";" << endl;
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "if (![inProtocol readMapBeginReturningKeyType: NULL valueType: NULL size: &" << size << " error: __thriftError]) return NO;" << endl;
+    indent(out) << "NSMutableDictionary * " << fieldName
+                << " = [[NSMutableDictionary alloc] initWithCapacity: " << size << "];" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "if (![inProtocol readSetBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;"
+                << endl;
+    indent(out) << "NSMutableSet * " << fieldName
+                << " = [[NSMutableSet alloc] initWithCapacity: " << size << "];" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "if (![inProtocol readListBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;"
+                << endl;
+    indent(out) << "NSMutableArray * " << fieldName
+                << " = [[NSMutableArray alloc] initWithCapacity: " << size << "];" << endl;
+  }
+  // FIXME - the code above does not verify that the element types of
+  // the containers being read match the element types of the
+  // containers we are reading into.  Does that matter?
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "int

<TRUNCATED>

[20/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
new file mode 100644
index 0000000..cbe8da2
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
@@ -0,0 +1,4374 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <cassert>
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <sys/stat.h>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostream;
+using std::string;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * C++ code generator. This is legitimacy incarnate.
+ *
+ */
+class t_cpp_generator : public t_oop_generator {
+public:
+  t_cpp_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+
+    gen_pure_enums_ = false;
+    use_include_prefix_ = false;
+    gen_cob_style_ = false;
+    gen_no_client_completion_ = false;
+    gen_no_default_operators_ = false;
+    gen_templates_ = false;
+    gen_templates_only_ = false;
+    gen_moveable_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("pure_enums") == 0) {
+        gen_pure_enums_ = true;
+      } else if( iter->first.compare("include_prefix") == 0) {
+        use_include_prefix_ = true;
+      } else if( iter->first.compare("cob_style") == 0) {
+        gen_cob_style_ = true;
+      } else if( iter->first.compare("no_client_completion") == 0) {
+        gen_no_client_completion_ = true;
+      } else if( iter->first.compare("no_default_operators") == 0) {
+        gen_no_default_operators_ = true;
+      } else if( iter->first.compare("templates") == 0) {
+        gen_templates_ = true;
+        gen_templates_only_ = (iter->second == "only");
+      } else if( iter->first.compare("moveable_types") == 0) {
+        gen_moveable_ = true;
+      } else {
+        throw "unknown option cpp:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-cpp";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_forward_declaration(t_struct* tstruct);
+  void generate_struct(t_struct* tstruct) { generate_cpp_struct(tstruct, false); }
+  void generate_xception(t_struct* txception) { generate_cpp_struct(txception, true); }
+  void generate_cpp_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
+  std::string render_const_value(std::ofstream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  void generate_struct_declaration(std::ofstream& out,
+                                   t_struct* tstruct,
+                                   bool is_exception = false,
+                                   bool pointers = false,
+                                   bool read = true,
+                                   bool write = true,
+                                   bool swap = false,
+                                   bool is_user_struct = false);
+  void generate_struct_definition(std::ofstream& out,
+                                  std::ofstream& force_cpp_out,
+                                  t_struct* tstruct,
+                                  bool setters = true);
+  void generate_copy_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
+  void generate_move_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
+  void generate_constructor_helper(std::ofstream& out,
+                                   t_struct* tstruct,
+                                   bool is_excpetion,
+                                   bool is_move);
+  void generate_assignment_operator(std::ofstream& out, t_struct* tstruct);
+  void generate_move_assignment_operator(std::ofstream& out, t_struct* tstruct);
+  void generate_assignment_helper(std::ofstream& out, t_struct* tstruct, bool is_move);
+  void generate_struct_reader(std::ofstream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_result_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_swap(std::ofstream& out, t_struct* tstruct);
+  void generate_struct_print_method(std::ofstream& out, t_struct* tstruct);
+  void generate_exception_what_method(std::ofstream& out, t_struct* tstruct);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_interface(t_service* tservice, string style);
+  void generate_service_interface_factory(t_service* tservice, string style);
+  void generate_service_null(t_service* tservice, string style);
+  void generate_service_multiface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice, string style);
+  void generate_service_processor(t_service* tservice, string style);
+  void generate_service_skeleton(t_service* tservice);
+  void generate_process_function(t_service* tservice,
+                                 t_function* tfunction,
+                                 string style,
+                                 bool specialized = false);
+  void generate_function_helpers(t_service* tservice, t_function* tfunction);
+  void generate_service_async_skeleton(t_service* tservice);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  std::string suffix = "");
+
+  void generate_deserialize_struct(std::ofstream& out,
+                                   t_struct* tstruct,
+                                   std::string prefix = "",
+                                   bool pointer = false);
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix,
+                                         bool push_back,
+                                         std::string index);
+
+  void generate_serialize_field(std::ofstream& out,
+                                t_field* tfield,
+                                std::string prefix = "",
+                                std::string suffix = "");
+
+  void generate_serialize_struct(std::ofstream& out,
+                                 t_struct* tstruct,
+                                 std::string prefix = "",
+                                 bool pointer = false);
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out, t_map* tmap, std::string iter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_function_call(ostream& out,
+                              t_function* tfunction,
+                              string target,
+                              string iface,
+                              string arg_prefix);
+  /*
+   * Helper rendering functions
+   */
+
+  std::string namespace_prefix(std::string ns);
+  std::string namespace_open(std::string ns);
+  std::string namespace_close(std::string ns);
+  std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false);
+  std::string base_type_name(t_base_type::t_base tbase);
+  std::string declare_field(t_field* tfield,
+                            bool init = false,
+                            bool pointer = false,
+                            bool constant = false,
+                            bool reference = false);
+  std::string function_signature(t_function* tfunction,
+                                 std::string style,
+                                 std::string prefix = "",
+                                 bool name_params = true);
+  std::string cob_function_signature(t_function* tfunction,
+                                     std::string prefix = "",
+                                     bool name_params = true);
+  std::string argument_list(t_struct* tstruct, bool name_params = true, bool start_comma = false);
+  std::string type_to_enum(t_type* ttype);
+
+  void generate_enum_constant_list(std::ofstream& f,
+                                   const vector<t_enum_value*>& constants,
+                                   const char* prefix,
+                                   const char* suffix,
+                                   bool include_values);
+
+  void generate_struct_ostream_operator(std::ofstream& f, t_struct* tstruct);
+  void generate_struct_print_method_decl(std::ofstream& f, t_struct* tstruct);
+  void generate_exception_what_method_decl(std::ofstream& f,
+                                           t_struct* tstruct,
+                                           bool external = false);
+
+  bool is_reference(t_field* tfield) { return tfield->get_reference(); }
+
+  bool is_complex_type(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || (ttype->is_base_type()
+               && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));
+  }
+
+  void set_use_include_prefix(bool use_include_prefix) { use_include_prefix_ = use_include_prefix; }
+
+private:
+  /**
+   * Returns the include prefix to use for a file generated by program, or the
+   * empty string if no include prefix should be used.
+   */
+  std::string get_include_prefix(const t_program& program) const;
+
+  /**
+   * True if we should generate pure enums for Thrift enums, instead of wrapper classes.
+   */
+  bool gen_pure_enums_;
+
+  /**
+   * True if we should generate templatized reader/writer methods.
+   */
+  bool gen_templates_;
+
+  /**
+   * True iff we should generate process function pointers for only templatized
+   * reader/writer methods.
+   */
+  bool gen_templates_only_;
+
+  /**
+   * True if we should generate move constructors & assignment operators.
+   */
+  bool gen_moveable_;
+
+  /**
+   * True iff we should use a path prefix in our #include statements for other
+   * thrift-generated header files.
+   */
+  bool use_include_prefix_;
+
+  /**
+   * True if we should generate "Continuation OBject"-style classes as well.
+   */
+  bool gen_cob_style_;
+
+  /**
+   * True if we should omit calls to completion__() in CobClient class.
+   */
+  bool gen_no_client_completion_;
+
+  /**
+   * True if we should omit generating the default opeartors ==, != and <.
+   */
+  bool gen_no_default_operators_;
+
+  /**
+   * Strings for namespace, computed once up front then used directly
+   */
+
+  std::string ns_open_;
+  std::string ns_close_;
+
+  /**
+   * File streams, stored here to avoid passing them as parameters to every
+   * function.
+   */
+
+  std::ofstream f_types_;
+  std::ofstream f_types_impl_;
+  std::ofstream f_types_tcc_;
+  std::ofstream f_header_;
+  std::ofstream f_service_;
+  std::ofstream f_service_tcc_;
+
+  // The ProcessorGenerator is used to generate parts of the code,
+  // so it needs access to many of our protected members and methods.
+  //
+  // TODO: The code really should be cleaned up so that helper methods for
+  // writing to the output files are separate from the generator classes
+  // themselves.
+  friend class ProcessorGenerator;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ */
+void t_cpp_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  // Make output file
+  string f_types_name = get_out_dir() + program_name_ + "_types.h";
+  f_types_.open(f_types_name.c_str());
+
+  string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp";
+  f_types_impl_.open(f_types_impl_name.c_str());
+
+  if (gen_templates_) {
+    // If we don't open the stream, it appears to just discard data,
+    // which is fine.
+    string f_types_tcc_name = get_out_dir() + program_name_ + "_types.tcc";
+    f_types_tcc_.open(f_types_tcc_name.c_str());
+  }
+
+  // Print header
+  f_types_ << autogen_comment();
+  f_types_impl_ << autogen_comment();
+  f_types_tcc_ << autogen_comment();
+
+  // Start ifndef
+  f_types_ << "#ifndef " << program_name_ << "_TYPES_H" << endl << "#define " << program_name_
+           << "_TYPES_H" << endl << endl;
+  f_types_tcc_ << "#ifndef " << program_name_ << "_TYPES_TCC" << endl << "#define " << program_name_
+               << "_TYPES_TCC" << endl << endl;
+
+  // Include base types
+  f_types_ << "#include <iosfwd>" << endl
+           << endl
+           << "#include <thrift/Thrift.h>" << endl
+           << "#include <thrift/TApplicationException.h>" << endl
+           << "#include <thrift/TBase.h>" << endl
+           << "#include <thrift/protocol/TProtocol.h>" << endl
+           << "#include <thrift/transport/TTransport.h>" << endl
+           << endl;
+  // Include C++xx compatibility header
+  f_types_ << "#include <thrift/cxxfunctional.h>" << endl;
+
+  // Include other Thrift includes
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    f_types_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name()
+             << "_types.h\"" << endl;
+
+    // XXX(simpkins): If gen_templates_ is enabled, we currently assume all
+    // included files were also generated with templates enabled.
+    f_types_tcc_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name()
+                 << "_types.tcc\"" << endl;
+  }
+  f_types_ << endl;
+
+  // Include custom headers
+  const vector<string>& cpp_includes = program_->get_cpp_includes();
+  for (size_t i = 0; i < cpp_includes.size(); ++i) {
+    if (cpp_includes[i][0] == '<') {
+      f_types_ << "#include " << cpp_includes[i] << endl;
+    } else {
+      f_types_ << "#include \"" << cpp_includes[i] << "\"" << endl;
+    }
+  }
+  f_types_ << endl;
+
+  // Include the types file
+  f_types_impl_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
+                << "_types.h\"" << endl << endl;
+  f_types_tcc_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
+               << "_types.h\"" << endl << endl;
+
+  // The swap() code needs <algorithm> for std::swap()
+  f_types_impl_ << "#include <algorithm>" << endl;
+  // for operator<<
+  f_types_impl_ << "#include <ostream>" << endl << endl;
+  f_types_impl_ << "#include <thrift/TToString.h>" << endl << endl;
+
+  // Open namespace
+  ns_open_ = namespace_open(program_->get_namespace("cpp"));
+  ns_close_ = namespace_close(program_->get_namespace("cpp"));
+
+  f_types_ << ns_open_ << endl << endl;
+
+  f_types_impl_ << ns_open_ << endl << endl;
+
+  f_types_tcc_ << ns_open_ << endl << endl;
+}
+
+/**
+ * Closes the output files.
+ */
+void t_cpp_generator::close_generator() {
+  // Close namespace
+  f_types_ << ns_close_ << endl << endl;
+  f_types_impl_ << ns_close_ << endl;
+  f_types_tcc_ << ns_close_ << endl << endl;
+
+  // Include the types.tcc file from the types header file,
+  // so clients don't have to explicitly include the tcc file.
+  // TODO(simpkins): Make this a separate option.
+  if (gen_templates_) {
+    f_types_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
+             << "_types.tcc\"" << endl << endl;
+  }
+
+  // Close ifndef
+  f_types_ << "#endif" << endl;
+  f_types_tcc_ << "#endif" << endl;
+
+  // Close output file
+  f_types_.close();
+  f_types_impl_.close();
+  f_types_tcc_.close();
+}
+
+/**
+ * Generates a typedef. This is just a simple 1-liner in C++
+ *
+ * @param ttypedef The type definition
+ */
+void t_cpp_generator::generate_typedef(t_typedef* ttypedef) {
+  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " "
+           << ttypedef->get_symbolic() << ";" << endl << endl;
+}
+
+void t_cpp_generator::generate_enum_constant_list(std::ofstream& f,
+                                                  const vector<t_enum_value*>& constants,
+                                                  const char* prefix,
+                                                  const char* suffix,
+                                                  bool include_values) {
+  f << " {" << endl;
+  indent_up();
+
+  vector<t_enum_value*>::const_iterator c_iter;
+  bool first = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f << "," << endl;
+    }
+    indent(f) << prefix << (*c_iter)->get_name() << suffix;
+    if (include_values) {
+      f << " = " << (*c_iter)->get_value();
+    }
+  }
+
+  f << endl;
+  indent_down();
+  indent(f) << "};" << endl;
+}
+
+/**
+ * Generates code for an enumerated type. In C++, this is essentially the same
+ * as the thrift definition itself, using the enum keyword in C++.
+ *
+ * @param tenum The enumeration
+ */
+void t_cpp_generator::generate_enum(t_enum* tenum) {
+  vector<t_enum_value*> constants = tenum->get_constants();
+
+  std::string enum_name = tenum->get_name();
+  if (!gen_pure_enums_) {
+    enum_name = "type";
+    f_types_ << indent() << "struct " << tenum->get_name() << " {" << endl;
+    indent_up();
+  }
+  f_types_ << indent() << "enum " << enum_name;
+
+  generate_enum_constant_list(f_types_, constants, "", "", true);
+
+  if (!gen_pure_enums_) {
+    indent_down();
+    f_types_ << "};" << endl;
+  }
+
+  f_types_ << endl;
+
+  /**
+     Generate a character array of enum names for debugging purposes.
+  */
+  std::string prefix = "";
+  if (!gen_pure_enums_) {
+    prefix = tenum->get_name() + "::";
+  }
+
+  f_types_impl_ << indent() << "int _k" << tenum->get_name() << "Values[] =";
+  generate_enum_constant_list(f_types_impl_, constants, prefix.c_str(), "", false);
+
+  f_types_impl_ << indent() << "const char* _k" << tenum->get_name() << "Names[] =";
+  generate_enum_constant_list(f_types_impl_, constants, "\"", "\"", false);
+
+  f_types_ << indent() << "extern const std::map<int, const char*> _" << tenum->get_name()
+           << "_VALUES_TO_NAMES;" << endl << endl;
+
+  f_types_impl_ << indent() << "const std::map<int, const char*> _" << tenum->get_name()
+                << "_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(" << constants.size() << ", _k"
+                << tenum->get_name() << "Values"
+                << ", _k" << tenum->get_name() << "Names), "
+                << "::apache::thrift::TEnumIterator(-1, NULL, NULL));" << endl << endl;
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_cpp_generator::generate_consts(std::vector<t_const*> consts) {
+  string f_consts_name = get_out_dir() + program_name_ + "_constants.h";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp";
+  ofstream f_consts_impl;
+  f_consts_impl.open(f_consts_impl_name.c_str());
+
+  // Print header
+  f_consts << autogen_comment();
+  f_consts_impl << autogen_comment();
+
+  // Start ifndef
+  f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_
+           << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program())
+           << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl;
+
+  f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_
+                << "_constants.h\"" << endl << endl << ns_open_ << endl << endl;
+
+  f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << "  "
+           << program_name_ << "Constants();" << endl << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    t_type* type = (*c_iter)->get_type();
+    f_consts << indent() << type_name(type) << " " << name << ";" << endl;
+  }
+  indent_down();
+  f_consts << "};" << endl;
+
+  f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;"
+                << endl << endl << program_name_ << "Constants::" << program_name_
+                << "Constants() {" << endl;
+  indent_up();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts_impl,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value());
+  }
+  indent_down();
+  indent(f_consts_impl) << "}" << endl;
+
+  f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_
+           << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl;
+  f_consts.close();
+
+  f_consts_impl << endl << ns_close_ << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+void t_cpp_generator::print_const_value(ofstream& out,
+                                        string name,
+                                        t_type* type,
+                                        t_const_value* value) {
+  type = get_true_type(type);
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    indent(out) << name << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    indent(out) << name << " = (" << type_name(type) << ")" << value->get_integer() << ";" << endl
+                << endl;
+  } else if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    bool is_nonrequired_field = false;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      is_nonrequired_field = false;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+          is_nonrequired_field = (*f_iter)->get_req() != t_field::T_REQUIRED;
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << "." << v_iter->first->get_string() << " = " << val << ";" << endl;
+      if (is_nonrequired_field) {
+        indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl;
+      }
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << ".insert(std::make_pair(" << key << ", " << val << "));" << endl;
+    }
+    out << endl;
+  } else if (type->is_list()) {
+    t_type* etype = ((t_list*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << ".push_back(" << val << ");" << endl;
+    }
+    out << endl;
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << ".insert(" << val << ");" << endl;
+    }
+    out << endl;
+  } else {
+    throw "INVALID TYPE IN print_const_value: " + type->get_name();
+  }
+}
+
+/**
+ *
+ */
+string t_cpp_generator::render_const_value(ofstream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value) {
+  (void)name;
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "LL";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << "(" << type_name(type) << ")" << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    indent(out) << type_name(type) << " " << t << ";" << endl;
+    print_const_value(out, t, type, value);
+    render << t;
+  }
+
+  return render.str();
+}
+
+void t_cpp_generator::generate_forward_declaration(t_struct* tstruct) {
+  // Forward declare struct def
+  f_types_ << indent() << "class " << tstruct->get_name() << ";" << endl << endl;
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with data members and a read/write() function, plus a mirroring isset
+ * inner class.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) {
+  generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true);
+  generate_struct_definition(f_types_impl_, f_types_impl_, tstruct);
+
+  std::ofstream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_);
+  generate_struct_reader(out, tstruct);
+  generate_struct_writer(out, tstruct);
+  generate_struct_swap(f_types_impl_, tstruct);
+  generate_copy_constructor(f_types_impl_, tstruct, is_exception);
+  if (gen_moveable_) {
+    generate_move_constructor(f_types_impl_, tstruct, is_exception);
+  }
+  generate_assignment_operator(f_types_impl_, tstruct);
+  if (gen_moveable_) {
+    generate_move_assignment_operator(f_types_impl_, tstruct);
+  }
+  generate_struct_print_method(f_types_impl_, tstruct);
+  if (is_exception) {
+    generate_exception_what_method(f_types_impl_, tstruct);
+  }
+}
+
+void t_cpp_generator::generate_copy_constructor(ofstream& out,
+                                                t_struct* tstruct,
+                                                bool is_exception) {
+  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false);
+}
+
+void t_cpp_generator::generate_move_constructor(ofstream& out,
+                                                t_struct* tstruct,
+                                                bool is_exception) {
+  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true);
+}
+
+namespace {
+// Helper to convert a variable to rvalue, if move is enabled
+std::string maybeMove(std::string const& other, bool move) {
+  if (move) {
+    return "std::move(" + other + ")";
+  }
+  return other;
+}
+}
+
+void t_cpp_generator::generate_constructor_helper(ofstream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_exception,
+                                                  bool is_move) {
+
+  std::string tmp_name = tmp("other");
+
+  indent(out) << tstruct->get_name() << "::" << tstruct->get_name();
+
+  if (is_move) {
+    out << "( " << tstruct->get_name() << "&& ";
+  } else {
+    out << "(const " << tstruct->get_name() << "& ";
+  }
+  out << tmp_name << ") ";
+  if (is_exception)
+    out << ": TException() ";
+  out << "{" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // eliminate compiler unused warning
+  if (members.empty())
+    indent(out) << "(void) " << tmp_name << ";" << endl;
+
+  vector<t_field*>::const_iterator f_iter;
+  bool has_nonrequired_fields = false;
+  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+    if ((*f_iter)->get_req() != t_field::T_REQUIRED)
+      has_nonrequired_fields = true;
+    indent(out) << (*f_iter)->get_name() << " = "
+                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
+  }
+
+  if (has_nonrequired_fields) {
+    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_cpp_generator::generate_assignment_operator(ofstream& out, t_struct* tstruct) {
+  generate_assignment_helper(out, tstruct, /*is_move=*/false);
+}
+
+void t_cpp_generator::generate_move_assignment_operator(ofstream& out, t_struct* tstruct) {
+  generate_assignment_helper(out, tstruct, /*is_move=*/true);
+}
+
+void t_cpp_generator::generate_assignment_helper(ofstream& out, t_struct* tstruct, bool is_move) {
+  std::string tmp_name = tmp("other");
+
+  indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=(";
+
+  if (is_move) {
+    out << tstruct->get_name() << "&& ";
+  } else {
+    out << "const " << tstruct->get_name() << "& ";
+  }
+  out << tmp_name << ") {" << endl;
+
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // eliminate compiler unused warning
+  if (members.empty())
+    indent(out) << "(void) " << tmp_name << ";" << endl;
+
+  vector<t_field*>::const_iterator f_iter;
+  bool has_nonrequired_fields = false;
+  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+    if ((*f_iter)->get_req() != t_field::T_REQUIRED)
+      has_nonrequired_fields = true;
+    indent(out) << (*f_iter)->get_name() << " = "
+                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
+  }
+  if (has_nonrequired_fields) {
+    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
+  }
+
+  indent(out) << "return *this;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+/**
+ * Writes the struct declaration into the header file
+ *
+ * @param out Output stream
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_declaration(ofstream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_exception,
+                                                  bool pointers,
+                                                  bool read,
+                                                  bool write,
+                                                  bool swap,
+                                                  bool is_user_struct) {
+  string extends = "";
+  if (is_exception) {
+    extends = " : public ::apache::thrift::TException";
+  } else {
+    if (is_user_struct && !gen_templates_) {
+      extends = " : public virtual ::apache::thrift::TBase";
+    }
+  }
+
+  // Get members
+  vector<t_field*>::const_iterator m_iter;
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // Write the isset structure declaration outside the class. This makes
+  // the generated code amenable to processing by SWIG.
+  // We only declare the struct if it gets used in the class.
+
+  // Isset struct has boolean fields, but only for non-required fields.
+  bool has_nonrequired_fields = false;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if ((*m_iter)->get_req() != t_field::T_REQUIRED)
+      has_nonrequired_fields = true;
+  }
+
+  if (has_nonrequired_fields && (!pointers || read)) {
+
+    out << indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << endl;
+    indent_up();
+
+    indent(out) << "_" << tstruct->get_name() << "__isset() ";
+    bool first = true;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
+        continue;
+      }
+      string isSet = ((*m_iter)->get_value() != NULL) ? "true" : "false";
+      if (first) {
+        first = false;
+        out << ": " << (*m_iter)->get_name() << "(" << isSet << ")";
+      } else {
+        out << ", " << (*m_iter)->get_name() << "(" << isSet << ")";
+      }
+    }
+    out << " {}" << endl;
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        indent(out) << "bool " << (*m_iter)->get_name() << " :1;" << endl;
+      }
+    }
+
+    indent_down();
+    indent(out) << "} _" << tstruct->get_name() << "__isset;" << endl;
+  }
+
+  out << endl;
+
+  // Open struct def
+  out << indent() << "class " << tstruct->get_name() << extends << " {" << endl << indent()
+      << " public:" << endl << endl;
+  indent_up();
+
+  if (!pointers) {
+    // Copy constructor
+    indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&);" << endl;
+
+    // Move constructor
+    if (gen_moveable_) {
+      indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&);" << endl;
+    }
+
+    // Assignment Operator
+    indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&);"
+                << endl;
+
+    // Move assignment operator
+    if (gen_moveable_) {
+      indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&);" << endl;
+    }
+
+    // Default constructor
+    indent(out) << tstruct->get_name() << "()";
+
+    bool init_ctor = false;
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) {
+        string dval;
+        if (t->is_enum()) {
+          dval += "(" + type_name(t) + ")";
+        }
+        dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0";
+        t_const_value* cv = (*m_iter)->get_value();
+        if (cv != NULL) {
+          dval = render_const_value(out, (*m_iter)->get_name(), t, cv);
+        }
+        if (!init_ctor) {
+          init_ctor = true;
+          out << " : ";
+          out << (*m_iter)->get_name() << "(" << dval << ")";
+        } else {
+          out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
+        }
+      }
+    }
+    out << " {" << endl;
+    indent_up();
+    // TODO(dreiss): When everything else in Thrift is perfect,
+    // do more of these in the initializer list.
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+
+      if (!t->is_base_type()) {
+        t_const_value* cv = (*m_iter)->get_value();
+        if (cv != NULL) {
+          print_const_value(out, (*m_iter)->get_name(), t, cv);
+        }
+      }
+    }
+    scope_down(out);
+  }
+
+  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
+    out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl;
+  }
+
+  // Declare all fields
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << declare_field(*m_iter,
+                                 false,
+                                 (pointers && !(*m_iter)->get_type()->is_xception()),
+                                 !read) << endl;
+  }
+
+  // Add the __isset data member if we need it, using the definition from above
+  if (has_nonrequired_fields && (!pointers || read)) {
+    out << endl << indent() << "_" << tstruct->get_name() << "__isset __isset;" << endl;
+  }
+
+  // Create a setter function for each field
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if (pointers) {
+      continue;
+    }
+    if (is_reference((*m_iter))) {
+      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(boost::shared_ptr<"
+          << type_name((*m_iter)->get_type(), false, false) << ">";
+      out << " val);" << endl;
+    } else {
+      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "("
+          << type_name((*m_iter)->get_type(), false, true);
+      out << " val);" << endl;
+    }
+  }
+  out << endl;
+
+  if (!pointers) {
+    // Should we generate default operators?
+    if (!gen_no_default_operators_) {
+      // Generate an equality testing operator.  Make it inline since the compiler
+      // will do a better job than we would when deciding whether to inline it.
+      out << indent() << "bool operator == (const " << tstruct->get_name() << " & "
+          << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl;
+      scope_up(out);
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        // Most existing Thrift code does not use isset or optional/required,
+        // so we treat "default" fields as required.
+        if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+          out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs."
+              << (*m_iter)->get_name() << "))" << endl << indent() << "  return false;" << endl;
+        } else {
+          out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset."
+              << (*m_iter)->get_name() << ")" << endl << indent() << "  return false;" << endl
+              << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !("
+              << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl
+              << indent() << "  return false;" << endl;
+        }
+      }
+      indent(out) << "return true;" << endl;
+      scope_down(out);
+      out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {"
+          << endl << indent() << "  return !(*this == rhs);" << endl << indent() << "}" << endl
+          << endl;
+
+      // Generate the declaration of a less-than operator.  This must be
+      // implemented by the application developer if they wish to use it.  (They
+      // will get a link error if they try to use it without an implementation.)
+      out << indent() << "bool operator < (const " << tstruct->get_name() << " & ) const;" << endl
+          << endl;
+    }
+  }
+
+  if (read) {
+    if (gen_templates_) {
+      out << indent() << "template <class Protocol_>" << endl << indent()
+          << "uint32_t read(Protocol_* iprot);" << endl;
+    } else {
+      out << indent() << "uint32_t read("
+          << "::apache::thrift::protocol::TProtocol* iprot);" << endl;
+    }
+  }
+  if (write) {
+    if (gen_templates_) {
+      out << indent() << "template <class Protocol_>" << endl << indent()
+          << "uint32_t write(Protocol_* oprot) const;" << endl;
+    } else {
+      out << indent() << "uint32_t write("
+          << "::apache::thrift::protocol::TProtocol* oprot) const;" << endl;
+    }
+  }
+  out << endl;
+
+  if (is_user_struct) {
+    out << indent() << "virtual ";
+    generate_struct_print_method_decl(out, NULL);
+    out << ";" << endl;
+  }
+
+  // std::exception::what()
+  if (is_exception) {
+    out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << endl;
+    out << indent();
+    generate_exception_what_method_decl(out, tstruct, false);
+    out << ";" << endl;
+  }
+
+  indent_down();
+  indent(out) << "};" << endl << endl;
+
+  if (swap) {
+    // Generate a namespace-scope swap() function
+    out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
+        << " &b);" << endl << endl;
+  }
+
+  if (is_user_struct) {
+    generate_struct_ostream_operator(out, tstruct);
+  }
+}
+
+void t_cpp_generator::generate_struct_definition(ofstream& out,
+                                                 ofstream& force_cpp_out,
+                                                 t_struct* tstruct,
+                                                 bool setters) {
+  // Get members
+  vector<t_field*>::const_iterator m_iter;
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // Destructor
+  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
+    force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name()
+                  << "() throw() {" << endl;
+    indent_up();
+
+    indent_down();
+    force_cpp_out << indent() << "}" << endl << endl;
+  }
+
+  // Create a setter function for each field
+  if (setters) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (is_reference((*m_iter))) {
+        std::string type = type_name((*m_iter)->get_type());
+        out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
+            << (*m_iter)->get_name() << "(boost::shared_ptr<"
+            << type_name((*m_iter)->get_type(), false, false) << ">";
+        out << " val) {" << endl;
+      } else {
+        out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
+            << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true);
+        out << " val) {" << endl;
+      }
+      indent_up();
+      out << indent() << "this->" << (*m_iter)->get_name() << " = val;" << endl;
+      indent_down();
+
+      // assume all fields are required except optional fields.
+      // for optional fields change __isset.name to true
+      bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
+      if (is_optional) {
+        out << indent() << indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl;
+      }
+      out << indent() << "}" << endl;
+    }
+  }
+  out << endl;
+}
+
+/**
+ * Makes a helper function to gen a struct reader.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_reader(ofstream& out, t_struct* tstruct, bool pointers) {
+  if (gen_templates_) {
+    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+        << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl;
+  } else {
+    indent(out) << "uint32_t " << tstruct->get_name()
+                << "::read(::apache::thrift::protocol::TProtocol* iprot) {" << endl;
+  }
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables
+  out << endl
+      << indent() << "apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);" << endl
+      << indent() << "uint32_t xfer = 0;" << endl
+      << indent() << "std::string fname;" << endl
+      << indent() << "::apache::thrift::protocol::TType ftype;" << endl
+      << indent() << "int16_t fid;" << endl
+      << endl
+      << indent() << "xfer += iprot->readStructBegin(fname);" << endl
+      << endl
+      << indent() << "using ::apache::thrift::protocol::TProtocolException;" << endl
+      << endl;
+
+  // Required variables aren't in __isset, so we need tmp vars to check them.
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
+      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
+  }
+  out << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "xfer += iprot->readFieldBegin(fname, ftype, fid);" << endl;
+
+  // Check for field STOP marker
+  out << indent() << "if (ftype == ::apache::thrift::protocol::T_STOP) {" << endl << indent()
+      << "  break;" << endl << indent() << "}" << endl;
+
+  if (fields.empty()) {
+    out << indent() << "xfer += iprot->skip(ftype);" << endl;
+  } else {
+    // Switch statement on the field we are reading
+    indent(out) << "switch (fid)" << endl;
+
+    scope_up(out);
+
+    // Generate deserialization code for known cases
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+      indent_up();
+      indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+      indent_up();
+
+      const char* isset_prefix = ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset."
+                                                                               : "isset_";
+
+#if 0
+          // This code throws an exception if the same field is encountered twice.
+          // We've decided to leave it out for performance reasons.
+          // TODO(dreiss): Generate this code and "if" it out to make it easier
+          // for people recompiling thrift to include it.
+          out <<
+            indent() << "if (" << isset_prefix << (*f_iter)->get_name() << ")" << endl <<
+            indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
+#endif
+
+      if (pointers && !(*f_iter)->get_type()->is_xception()) {
+        generate_deserialize_field(out, *f_iter, "(*(this->", "))");
+      } else {
+        generate_deserialize_field(out, *f_iter, "this->");
+      }
+      out << indent() << isset_prefix << (*f_iter)->get_name() << " = true;" << endl;
+      indent_down();
+      out << indent() << "} else {" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl
+          <<
+          // TODO(dreiss): Make this an option when thrift structs
+          // have a common base class.
+          // indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl <<
+          indent() << "}" << endl << indent() << "break;" << endl;
+      indent_down();
+    }
+
+    // In the default case we skip the field
+    out << indent() << "default:" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl
+        << indent() << "  break;" << endl;
+
+    scope_down(out);
+  } //!fields.empty()
+  // Read field end marker
+  indent(out) << "xfer += iprot->readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  out << endl << indent() << "xfer += iprot->readStructEnd();" << endl;
+
+  // Throw if any required fields are missing.
+  // We do this after reading the struct end so that
+  // there might possibly be a chance of continuing.
+  out << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
+      out << indent() << "if (!isset_" << (*f_iter)->get_name() << ')' << endl << indent()
+          << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
+  }
+
+  indent(out) << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates the write function.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_writer(ofstream& out, t_struct* tstruct, bool pointers) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (gen_templates_) {
+    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
+  } else {
+    indent(out) << "uint32_t " << tstruct->get_name()
+                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
+  }
+  indent_up();
+
+  out << indent() << "uint32_t xfer = 0;" << endl;
+
+  indent(out) << "apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);" << endl;
+  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool check_if_set = (*f_iter)->get_req() == t_field::T_OPTIONAL
+                        || (*f_iter)->get_type()->is_xception();
+    if (check_if_set) {
+      out << endl << indent() << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl;
+      indent_up();
+    } else {
+      out << endl;
+    }
+
+    // Write field header
+    out << indent() << "xfer += oprot->writeFieldBegin("
+        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
+        << (*f_iter)->get_key() << ");" << endl;
+    // Write field contents
+    if (pointers && !(*f_iter)->get_type()->is_xception()) {
+      generate_serialize_field(out, *f_iter, "(*(this->", "))");
+    } else {
+      generate_serialize_field(out, *f_iter, "this->");
+    }
+    // Write field closer
+    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
+    if (check_if_set) {
+      indent_down();
+      indent(out) << '}';
+    }
+  }
+
+  out << endl;
+
+  // Write the struct map
+  out << indent() << "xfer += oprot->writeFieldStop();" << endl << indent()
+      << "xfer += oprot->writeStructEnd();" << endl << indent()
+      << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Struct writer for result of a function, which can have only one of its
+ * fields set and does a conditional if else look up into the __isset field
+ * of the struct.
+ *
+ * @param out Output stream
+ * @param tstruct The result struct
+ */
+void t_cpp_generator::generate_struct_result_writer(ofstream& out,
+                                                    t_struct* tstruct,
+                                                    bool pointers) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (gen_templates_) {
+    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
+  } else {
+    indent(out) << "uint32_t " << tstruct->get_name()
+                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
+  }
+  indent_up();
+
+  out << endl << indent() << "uint32_t xfer = 0;" << endl << endl;
+
+  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl;
+
+    indent_up();
+
+    // Write field header
+    out << indent() << "xfer += oprot->writeFieldBegin("
+        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
+        << (*f_iter)->get_key() << ");" << endl;
+    // Write field contents
+    if (pointers) {
+      generate_serialize_field(out, *f_iter, "(*(this->", "))");
+    } else {
+      generate_serialize_field(out, *f_iter, "this->");
+    }
+    // Write field closer
+    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+
+  // Write the struct map
+  out << endl << indent() << "xfer += oprot->writeFieldStop();" << endl << indent()
+      << "xfer += oprot->writeStructEnd();" << endl << indent() << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates the swap function.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_swap(ofstream& out, t_struct* tstruct) {
+  out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
+      << " &b) {" << endl;
+  indent_up();
+
+  // Let argument-dependent name lookup find the correct swap() function to
+  // use based on the argument types.  If none is found in the arguments'
+  // namespaces, fall back to ::std::swap().
+  out << indent() << "using ::std::swap;" << endl;
+
+  bool has_nonrequired_fields = false;
+  const vector<t_field*>& fields = tstruct->get_members();
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* tfield = *f_iter;
+
+    if (tfield->get_req() != t_field::T_REQUIRED) {
+      has_nonrequired_fields = true;
+    }
+
+    out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");"
+        << endl;
+  }
+
+  if (has_nonrequired_fields) {
+    out << indent() << "swap(a.__isset, b.__isset);" << endl;
+  }
+
+  // handle empty structs
+  if (fields.size() == 0) {
+    out << indent() << "(void) a;" << endl;
+    out << indent() << "(void) b;" << endl;
+  }
+
+  scope_down(out);
+  out << endl;
+}
+
+void t_cpp_generator::generate_struct_ostream_operator(std::ofstream& out, t_struct* tstruct) {
+  out << "inline std::ostream& operator<<(std::ostream& out, const "
+      << tstruct->get_name()
+      << "& obj)" << endl;
+  scope_up(out);
+  out << indent() << "obj.printTo(out);" << endl
+      << indent() << "return out;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+void t_cpp_generator::generate_struct_print_method_decl(std::ofstream& out, t_struct* tstruct) {
+  out << "void ";
+  if (tstruct) {
+    out << tstruct->get_name() << "::";
+  }
+  out << "printTo(std::ostream& out) const";
+}
+
+void t_cpp_generator::generate_exception_what_method_decl(std::ofstream& out,
+                                                          t_struct* tstruct,
+                                                          bool external) {
+  out << "const char* ";
+  if (external) {
+    out << tstruct->get_name() << "::";
+  }
+  out << "what() const throw()";
+}
+
+namespace struct_ostream_operator_generator {
+void generate_required_field_value(std::ofstream& out, const t_field* field) {
+  out << " << to_string(" << field->get_name() << ")";
+}
+
+void generate_optional_field_value(std::ofstream& out, const t_field* field) {
+  out << "; (__isset." << field->get_name() << " ? (out";
+  generate_required_field_value(out, field);
+  out << ") : (out << \"<null>\"))";
+}
+
+void generate_field_value(std::ofstream& out, const t_field* field) {
+  if (field->get_req() == t_field::T_OPTIONAL)
+    generate_optional_field_value(out, field);
+  else
+    generate_required_field_value(out, field);
+}
+
+void generate_field_name(std::ofstream& out, const t_field* field) {
+  out << "\"" << field->get_name() << "=\"";
+}
+
+void generate_field(std::ofstream& out, const t_field* field) {
+  generate_field_name(out, field);
+  generate_field_value(out, field);
+}
+
+void generate_fields(std::ofstream& out,
+                     const vector<t_field*>& fields,
+                     const std::string& indent) {
+  const vector<t_field*>::const_iterator beg = fields.begin();
+  const vector<t_field*>::const_iterator end = fields.end();
+
+  for (vector<t_field*>::const_iterator it = beg; it != end; ++it) {
+    out << indent << "out << ";
+
+    if (it != beg) {
+      out << "\", \" << ";
+    }
+
+    generate_field(out, *it);
+    out << ";" << endl;
+  }
+}
+}
+
+/**
+ * Generates operator<<
+ */
+void t_cpp_generator::generate_struct_print_method(std::ofstream& out, t_struct* tstruct) {
+  out << indent();
+  generate_struct_print_method_decl(out, tstruct);
+  out << " {" << endl;
+
+  indent_up();
+
+  out << indent() << "using ::apache::thrift::to_string;" << endl;
+  out << indent() << "out << \"" << tstruct->get_name() << "(\";" << endl;
+  struct_ostream_operator_generator::generate_fields(out, tstruct->get_members(), indent());
+  out << indent() << "out << \")\";" << endl;
+
+  indent_down();
+  out << "}" << endl << endl;
+}
+
+/**
+ * Generates what() method for exceptions
+ */
+void t_cpp_generator::generate_exception_what_method(std::ofstream& out, t_struct* tstruct) {
+  out << indent();
+  generate_exception_what_method_decl(out, tstruct, true);
+  out << " {" << endl;
+
+  indent_up();
+  out << indent() << "try {" << endl;
+
+  indent_up();
+  out << indent() << "std::stringstream ss;" << endl;
+  out << indent() << "ss << \"TException - service has thrown: \" << *this;" << endl;
+  out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << endl;
+  out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << endl;
+  indent_down();
+
+  out << indent() << "} catch (const std::exception&) {" << endl;
+
+  indent_up();
+  out << indent() << "return \"TException - service has thrown: " << tstruct->get_name() << "\";"
+      << endl;
+  indent_down();
+
+  out << indent() << "}" << endl;
+
+  indent_down();
+  out << "}" << endl << endl;
+}
+
+/**
+ * Generates a thrift service. In C++, this comprises an entirely separate
+ * header and source file. The header file defines the methods and includes
+ * the data types defined in the main header file, and the implementation
+ * file contains implementations of the basic printer and default interfaces.
+ *
+ * @param tservice The service definition
+ */
+void t_cpp_generator::generate_service(t_service* tservice) {
+  string svcname = tservice->get_name();
+
+  // Make output files
+  string f_header_name = get_out_dir() + svcname + ".h";
+  f_header_.open(f_header_name.c_str());
+
+  // Print header file includes
+  f_header_ << autogen_comment();
+  f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl
+            << endl;
+  if (gen_cob_style_) {
+    f_header_ << "#include <thrift/transport/TBufferTransports.h>" << endl << // TMemoryBuffer
+        "#include <thrift/cxxfunctional.h>" << endl
+              << "namespace apache { namespace thrift { namespace async {" << endl
+              << "class TAsyncChannel;" << endl << "}}}" << endl;
+  }
+  f_header_ << "#include <thrift/TDispatchProcessor.h>" << endl;
+  if (gen_cob_style_) {
+    f_header_ << "#include <thrift/async/TAsyncDispatchProcessor.h>" << endl;
+  }
+  f_header_ << "#include <thrift/async/TConcurrentClientSyncInfo.h>" << endl;
+  f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\""
+            << endl;
+
+  t_service* extends_service = tservice->get_extends();
+  if (extends_service != NULL) {
+    f_header_ << "#include \"" << get_include_prefix(*(extends_service->get_program()))
+              << extends_service->get_name() << ".h\"" << endl;
+  }
+
+  f_header_ << endl << ns_open_ << endl << endl;
+
+  f_header_ << "#ifdef _WIN32\n"
+               "  #pragma warning( push )\n"
+               "  #pragma warning (disable : 4250 ) //inheriting methods via dominance \n"
+               "#endif\n\n";
+
+  // Service implementation file includes
+  string f_service_name = get_out_dir() + svcname + ".cpp";
+  f_service_.open(f_service_name.c_str());
+  f_service_ << autogen_comment();
+  f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl;
+  if (gen_cob_style_) {
+    f_service_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
+  }
+  if (gen_templates_) {
+    f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\""
+               << endl;
+
+    string f_service_tcc_name = get_out_dir() + svcname + ".tcc";
+    f_service_tcc_.open(f_service_tcc_name.c_str());
+    f_service_tcc_ << autogen_comment();
+    f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\""
+                   << endl;
+
+    f_service_tcc_ << "#ifndef " << svcname << "_TCC" << endl << "#define " << svcname << "_TCC"
+                   << endl << endl;
+
+    if (gen_cob_style_) {
+      f_service_tcc_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
+    }
+  }
+
+  f_service_ << endl << ns_open_ << endl << endl;
+  f_service_tcc_ << endl << ns_open_ << endl << endl;
+
+  // Generate all the components
+  generate_service_interface(tservice, "");
+  generate_service_interface_factory(tservice, "");
+  generate_service_null(tservice, "");
+  generate_service_helpers(tservice);
+  generate_service_client(tservice, "");
+  generate_service_processor(tservice, "");
+  generate_service_multiface(tservice);
+  generate_service_skeleton(tservice);
+  generate_service_client(tservice, "Concurrent");
+
+  // Generate all the cob components
+  if (gen_cob_style_) {
+    generate_service_interface(tservice, "CobCl");
+    generate_service_interface(tservice, "CobSv");
+    generate_service_interface_factory(tservice, "CobSv");
+    generate_service_null(tservice, "CobSv");
+    generate_service_client(tservice, "Cob");
+    generate_service_processor(tservice, "Cob");
+    generate_service_async_skeleton(tservice);
+  }
+
+  f_header_ << "#ifdef _WIN32\n"
+               "  #pragma warning( pop )\n"
+               "#endif\n\n";
+
+  // Close the namespace
+  f_service_ << ns_close_ << endl << endl;
+  f_service_tcc_ << ns_close_ << endl << endl;
+  f_header_ << ns_close_ << endl << endl;
+
+  // TODO(simpkins): Make this a separate option
+  if (gen_templates_) {
+    f_header_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" << endl
+              << "#include \"" << get_include_prefix(*get_program()) << program_name_
+              << "_types.tcc\"" << endl << endl;
+  }
+
+  f_header_ << "#endif" << endl;
+  f_service_tcc_ << "#endif" << endl;
+
+  // Close the files
+  f_service_tcc_.close();
+  f_service_.close();
+  f_header_.close();
+}
+
+/**
+ * Generates helper functions for a service. Basically, this generates types
+ * for all the arguments and results to functions.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    string name_orig = ts->get_name();
+
+    // TODO(dreiss): Why is this stuff not in generate_function_helpers?
+    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
+    generate_struct_declaration(f_header_, ts, false);
+    generate_struct_definition(out, f_service_, ts, false);
+    generate_struct_reader(out, ts);
+    generate_struct_writer(out, ts);
+    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs");
+    generate_struct_declaration(f_header_, ts, false, true, false, true);
+    generate_struct_definition(out, f_service_, ts, false);
+    generate_struct_writer(out, ts, true);
+    ts->set_name(name_orig);
+
+    generate_function_helpers(tservice, *f_iter);
+  }
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_interface(t_service* tservice, string style) {
+
+  string service_if_name = service_name_ + style + "If";
+  if (style == "CobCl") {
+    // Forward declare the client.
+    string client_name = service_name_ + "CobClient";
+    if (gen_templates_) {
+      client_name += "T";
+      service_if_name += "T";
+      indent(f_header_) << "template <class Protocol_>" << endl;
+    }
+    indent(f_header_) << "class " << client_name << ";" << endl << endl;
+  }
+
+  string extends = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "If";
+    if (style == "CobCl" && gen_templates_) {
+      // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
+      // parent services were also generated with templates enabled.
+      extends += "T<Protocol_>";
+    }
+  }
+
+  if (style == "CobCl" && gen_templates_) {
+    f_header_ << "template <class Protocol_>" << endl;
+  }
+  f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    if ((*f_iter)->has_doc())
+      f_header_ << endl;
+    generate_java_doc(f_header_, *f_iter);
+    f_header_ << indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl;
+  }
+  indent_down();
+  f_header_ << "};" << endl << endl;
+
+  if (style == "CobCl" && gen_templates_) {
+    // generate a backwards-compatible typedef for clients that do not
+    // know about the new template-style code
+    f_header_ << "typedef " << service_if_name << "< ::apache::thrift::protocol::TProtocol> "
+              << service_name_ << style << "If;" << endl << endl;
+  }
+}
+
+/**
+ * Generates a service interface factory.
+ *
+ * @param tservice The service to generate an interface factory for.
+ */
+void t_cpp_generator::generate_service_interface_factory(t_service* tservice, string style) {
+  string service_if_name = service_name_ + style + "If";
+
+  // Figure out the name of the upper-most parent class.
+  // Getting everything to work out properly with inheritance is annoying.
+  // Here's what we're doing for now:
+  //
+  // - All handlers implement getHandler(), but subclasses use covariant return
+  //   types to return their specific service interface class type.  We have to
+  //   use raw pointers because of this; shared_ptr<> can't be used for
+  //   covariant return types.
+  //
+  // - Since we're not using shared_ptr<>, we also provide a releaseHandler()
+  //   function that must be called to release a pointer to a handler obtained
+  //   via getHandler().
+  //
+  //   releaseHandler() always accepts a pointer to the upper-most parent class
+  //   type.  This is necessary since the parent versions of releaseHandler()
+  //   may accept any of the parent types, not just the most specific subclass
+  //   type.  Implementations can use dynamic_cast to cast the pointer to the
+  //   subclass type if desired.
+  t_service* base_service = tservice;
+  while (base_service->get_extends() != NULL) {
+    base_service = base_service->get_extends();
+  }
+  string base_if_name = type_name(base_service) + style + "If";
+
+  // Generate the abstract factory class
+  string factory_name = service_if_name + "Factory";
+  string extends;
+  if (tservice->get_extends() != NULL) {
+    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "IfFactory";
+  }
+
+  f_header_ << "class " << factory_name << extends << " {" << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << "typedef " << service_if_name << " Handler;" << endl << endl << indent()
+            << "virtual ~" << factory_name << "() {}" << endl << endl << indent() << "virtual "
+            << service_if_name << "* getHandler("
+            << "const ::apache::thrift::TConnectionInfo& connInfo) = 0;" << endl << indent()
+            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) = 0;" << endl;
+
+  indent_down();
+  f_header_ << "};" << endl << endl;
+
+  // Generate the singleton factory class
+  string singleton_factory_name = service_if_name + "SingletonFactory";
+  f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {"
+            << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << singleton_factory_name << "(const boost::shared_ptr<" << service_if_name
+            << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~"
+            << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual "
+            << service_if_name << "* getHandler("
+            << "const ::apache::thrift::TConnectionInfo&) {" << endl << indent()
+            << "  return iface_.get();" << endl << indent() << "}" << endl << indent()
+            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) {}" << endl;
+
+  f_header_ << endl << " protected:" << endl << indent() << "boost::shared_ptr<" << service_if_name
+            << "> iface_;" << endl;
+
+  indent_down();
+  f_header_ << "};" << endl << endl;
+}
+
+/**
+ * Generates a null implementation of the service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_null(t_service* tservice, string style) {
+  string extends = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " , virtual public " + type_name(tservice->get_extends()) + style + "Null";
+  }
+  f_header_ << "class " << service_name_ << style << "Null : virtual public " << service_name_
+            << style << "If" << extends << " {" << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << "virtual ~" << service_name_ << style << "Null() {}" << endl;
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_header_ << indent() << function_signature(*f_iter, style, "", false) << " {" << endl;
+    indent_up();
+
+    t_type* returntype = (*f_iter)->get_returntype();
+    t_field returnfield(returntype, "_return");
+
+    if (style == "") {
+      if (returntype->is_void() || is_complex_type(returntype)) {
+        f_header_ << indent() << "return;" << endl;
+      } else {
+        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent()
+                  << "return _return;" << endl;
+      }
+    } else if (style == "CobSv") {
+      if (returntype->is_void()) {
+        f_header_ << indent() << "return cob();" << endl;
+      } else {
+        t_field returnfield(returntype, "_return");
+        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent()
+                  << "return cob(_return);" << endl;
+      }
+
+    } else {
+      throw "UNKNOWN STYLE";
+    }
+
+    indent_down();
+    f_header_ << indent() << "}" << endl;
+  }
+  indent_down();
+  f_header_ << "};" << endl << endl;
+}
+
+void t_cpp_generator::generate_function_call(ostream& out,
+                                             t_function* tfunction,
+                                             string target,
+                                             string iface,
+                                             string arg_prefix) {
+  bool first = true;
+  t_type* ret_type = get_true_type(tfunction->get_returntype());
+  out << indent();
+  if (!tfunction->is_oneway() && !ret_type->is_void()) {
+    if (is_complex_type(ret_type)) {
+      first = false;
+      out << iface << "->" << tfunction->get_name() << "(" << target;
+    } else {
+      out << target << " = " << iface << "->" << tfunction->get_name() << "(";
+    }
+  } else {
+    out << iface << "->" << tfunction->get_name() << "(";
+  }
+  const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      out << ", ";
+    }
+    out << arg_prefix << (*f_iter)->get_name();
+  }
+  out << ");" << endl;
+}
+
+void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) {
+  string svcname = tservice->get_name();
+
+  // Service implementation file includes
+  string f_skeleton_name = get_out_dir() + svcname + "_async_server.skeleton.cpp";
+
+  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
+
+  ofstream f_skeleton;
+  f_skeleton.open(f_skeleton_name.c_str());
+  f_skeleton << "// This autogenerated skeleton file illustrates one way to adapt a synchronous"
+             << endl << "// interface into an asynchronous interface. You should copy it to another"
+             << endl
+             << "// filename to avoid overwriting it and rewrite as asynchronous any functions"
+             << endl << "// that would otherwise introduce unwanted latency." << endl << endl
+             << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl
+             << "#include <thrift/protocol/TBinaryProtocol.h>" << endl << endl
+             << "using namespace ::apache::thrift;" << endl
+             << "using namespace ::apache::thrift::protocol;" << endl
+             << "using namespace ::apache::thrift::transport;" << endl
+             << "using namespace ::apache::thrift::async;" << endl << endl
+             << "using boost::shared_ptr;" << endl << endl;
+
+  // the following code would not compile:
+  // using namespace ;
+  // using namespace ::;
+  if ((!ns.empty()) && (ns.compare(" ::") != 0)) {
+    f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl;
+  }
+
+  f_skeleton << "class " << svcname << "AsyncHandler : "
+             << "public " << svcname << "CobSvIf {" << endl << " public:" << endl;
+  indent_up();
+  f_skeleton << indent() << svcname << "AsyncHandler() {" << endl << indent()
+             << "  syncHandler_ = std::auto_ptr<" << svcname << "Handler>(new " << svcname
+             << "Handler);" << endl << indent() << "  // Your initialization goes here" << endl
+             << indent() << "}" << endl;
+  f_skeleton << indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_skeleton << endl << indent() << function_signature(*f_iter, "CobSv", "", true) << " {"
+               << endl;
+    indent_up();
+
+    t_type* returntype = (*f_iter)->get_returntype();
+    t_field returnfield(returntype, "_return");
+
+    string target = returntype->is_void() ? "" : "_return";
+    if (!returntype->is_void()) {
+      f_skeleton << indent() << declare_field(&returnfield, true) << endl;
+    }
+    generate_function_call(f_skeleton, *f_iter, target, "syncHandler_", "");
+    f_skeleton << indent() << "return cob(" << target << ");" << endl;
+
+    scope_down(f_skeleton);
+  }
+  f_skeleton << endl << " protected:" << endl << indent() << "std::auto_ptr<" << svcname
+             << "Handler> syncHandler_;" << endl;
+  indent_down();
+  f_skeleton << "};" << endl << endl;
+}
+
+/**
+ * Generates a multiface, which is a single server that just takes a set
+ * of objects implementing the interface and calls them all, returning the
+ * value of the last one to be called.
+ *
+ * @param tservice The service to generate a multiserver for.
+ */
+void t_cpp_generator::generate_service_multiface(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_multiface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_multiface = ", public " + extends + "Multiface";
+  }
+
+  string list_type = string("std::vector<boost::shared_ptr<") + service_name_ + "If> >";
+
+  // Generate the header portion
+  f_header_ << "class " << service_name_ << "Multiface : "
+            << "virtual public " << service_name_ << "If" << extends_multiface << " {" << endl
+            << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << service_name_ << "Multiface(" << list_type
+            << "& ifaces) : ifaces_(ifaces) {" << endl;
+  if (!extends.empty()) {
+    f_header_ << indent()
+              << "  std::vector<boost::shared_ptr<" + service_name_ + "If> >::iterator iter;"
+              << endl << indent() << "  for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {"
+              << endl << indent() << "    " << extends << "Multiface::add(*iter);" << endl
+              << indent() << "  }" << endl;
+  }
+  f_header_ << indent() << "}" << endl << indent() << "virtual ~" << service_name_
+            << "Multiface() {}" << endl;
+  indent_down();
+
+  // Protected data members
+  f_header_ << " protected:" << endl;
+  indent_up();
+  f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_
+            << "Multiface() {}" << endl << indent() << "void add(boost::shared_ptr<"
+            << service_name_ << "If> iface) {" << endl;
+  if (!extends.empty()) {
+    f_header_ << indent() << "  " << extends << "Multiface::add(iface);" << endl;
+  }
+  f_header_ << indent() << "  ifaces_.push_back(iface);" << endl << indent() << "}" << endl;
+  indent_down();
+
+  f_header_ << indent() << " public:" << endl;
+  indent_up();
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arglist = (*f_iter)->get_arglist();
+    const vector<t_field*>& args = arglist->get_members();
+    vector<t_field*>::const_iterator a_iter;
+
+    string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "(";
+    bool first = true;
+    if (is_complex_type((*f_iter)->get_returntype())) {
+      call += "_return";
+      first = false;
+    }
+    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+      if (first) {
+        first = false;
+      } else {
+        call += ", ";
+      }
+      call += (*a_iter)->get_name();
+    }
+    call += ")";
+
+    f_header_ << indent() << function_signature(*f_iter, "") << " {" << endl;
+    indent_up();
+    f_header_ << indent() << "size_t sz = ifaces_.size();" << endl << indent() << "size_t i = 0;"
+              << endl << indent() << "for (; i < (sz - 1); ++i) {" << endl;
+    indent_up();
+    f_header_ << indent() << call << ";" << endl;
+    indent_down();
+    f_header_ << indent() << "}" << endl;
+
+    if (!(*f_iter)->get_returntype()->is_void()) {
+      if (is_complex_type((*f_iter)->get_returntype())) {
+        f_header_ << indent() << call << ";" << endl << indent() << "return;" << endl;
+      } else {
+        f_header_ << indent() << "return " << call << ";" << endl;
+      }
+    } else {
+      f_header_ << indent() << call << ";" << endl;
+    }
+
+    indent_down();
+    f_header_ << indent() << "}" << endl << endl;
+  }
+
+  indent_down();
+  f_header_ << indent() << "};" << endl << endl;
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_cpp_generator::generate_service_client(t_service* tservice, string style) {
+  string ifstyle;
+  if (style == "Cob") {
+    ifstyle = "CobCl";
+  }
+
+  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+  string template_header, template_suffix, short_suffix, protocol_type, _this;
+  string const prot_factory_type = "::apache::thrift::protocol::TProtocolFactory";
+  if (gen_templates_) {
+    template_header = "template <class Protocol_>\n";
+    short_suffix = "T";
+    template_suffix = "T<Protocol_>";
+    protocol_type = "Protocol_";
+    _this = "this->";
+  } else {
+    protocol_type = "::apache::thrift::protocol::TProtocol";
+  }
+  string prot_ptr = "boost::shared_ptr< " + protocol_type + ">";
+  string client_suffix = "Client" + template_suffix;
+  string if_suffix = "If";
+  if (style == "Cob") {
+    if_suffix += template_suffix;
+  }
+
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
+    // parent services were also generated with templates enabled.
+    extends = type_name(tservice->get_extends());
+    extends_client = ", public " + extends + style + client_suffix;
+  }
+
+  // Generate the header portion
+  if (style == "Concurrent") {
+    f_header_ << "// The \'concurrent\' client is a thread safe client that correctly handles\n"
+                 "// out of order responses.  It is slower than the regular client, so should\n"
+                 "// only be used when you need to share a connection among multiple threads\n";
+  }
+  f_header_ << template_header << "class " << service_name_ << style << "Client" << short_suffix
+            << " : "
+            << "virtual public " << service_name_ << ifstyle << if_suffix << extends_client << " {"
+            << endl << " public:" << endl;
+
+  indent_up();
+  if (style != "Cob") {
+    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr
+              << " prot) ";
+
+    if (extends.empty()) {
+      f_header_ << "{" << endl;
+      f_header_ << indent() << "  setProtocol" << short_suffix << "(prot);" << endl << indent()
+                << "}" << endl;
+    } else {
+      f_header_ << ":" << endl;
+      f_header_ << indent() << "  " << extends << style << client_suffix << "(prot, prot) {}"
+                << endl;
+    }
+
+    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr
+              << " iprot, " << prot_ptr << " oprot) ";
+    if (extends.empty()) {
+      f_header_ << "{" << endl;
+      f_header_ << indent() << "  setProtocol" << short_suffix << "(iprot,oprot);" << endl
+                << indent() << "}" << endl;
+    } else {
+      f_header_ << ":" << indent() << "  " << extends << style << client_suffix
+                << "(iprot, oprot) {}" << endl;
+    }
+
+    // create the setProtocol methods
+    if (extends.empty()) {
+      f_header_ << " private:" << endl;
+      // 1: one parameter
+      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " prot) {"
+                << endl;
+      f_header_ << indent() << "setProtocol" << short_suffix << "(prot,prot);" << endl;
+      f_header_ << indent() << "}" << endl;
+      // 2: two parameter
+      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " iprot, "
+                << prot_ptr << " oprot) {" << endl;
+
+      f_header_ << indent() << "  piprot_=iprot;" << endl << indent() << "  poprot_=oprot;" << endl
+                << indent() << "  iprot_ = iprot.get();" << endl << indent()
+                << "  oprot_ = oprot.get();" << endl;
+
+      f_header_ << indent() << "}" << endl;
+      f_header_ << " public:" << endl;
+    }
+
+    // Generate getters for the protocols.
+    // Note that these are not currently templated for simplicity.
+    // TODO(simpkins): should they be templated?
+    f_header_ << indent()
+              << "boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {"
+              << endl << indent() << "  return " << _this << "piprot_;" << endl << indent() << "}"
+              << endl;
+
+    f_header_ << indent()
+              << "boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {"
+              << endl << indent() << "  return " << _this << "poprot_;" << endl << indent() << "}"
+              << endl;
+
+  } else /* if (style == "Cob") */ {
+    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "("
+              << "boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, "
+              << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl;
+    if (extends.empty()) {
+      f_header_ << indent() << "  channel_(channel)," << endl << indent()
+                << "  itrans_(new ::apache::thrift::transport::TMemoryBuffer())," << endl
+                << indent() << "  otrans_(new ::apache::thrift::transport::TMemoryBuffer()),"
+                << endl;
+      if (gen_templates_) {
+        // TProtocolFactory classes return generic TProtocol pointers.
+        // We have to dynamic cast to the Protocol_ type we are expecting.
+        f_header_ << indent() << "  piprot_(boost::dynamic_pointer_cast<Protocol_>("
+                  << "protocolFactory->getProtocol(itrans_)))," << endl << indent()
+                  << "  poprot_(boost::dynamic_pointer_cast<Protocol_>("
+                  << "protocolFactory->getProtocol(otrans_))) {" << endl;
+        // Throw a TException if either dynamic cast failed.
+        f_header_ << indent() << "  if (!piprot_ || !poprot_) {" << endl << indent()
+                  << "    throw ::apache::thrift::TException(\""
+                  << "TProtocolFactory returned unexpected protocol type in " << service_name_
+                  << style << "Client" << short_suffix << " constructor\");" << endl << indent()
+                  << "  }" << endl;
+      } else {
+        f_header_ << indent() << "  piprot_(protocolFactory->getProtocol(itrans_))," << endl
+                  << indent() << "  poprot_(protocolFactory->getProtocol(otrans_)) {" << endl;
+      }
+      f_header_ << indent() << "  iprot_ = piprot_.get();" << endl << indent()
+                << "  oprot_ = poprot_.get();" << endl << indent() << "}" << endl;
+    } else {
+      f_header_ << indent() << "  " << extends << style << client_suffix
+                << "(channel, protocolFactory) {}" << endl;
+    }
+  }
+
+  if (style == "Cob") {
+    f_header_ << indent()
+              << "boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl
+              << indent() << "  return " << _this << "channel_;" << endl << indent() << "}" << endl;
+    if (!gen_no_client_completion_) {
+      f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl;
+    }
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent(f_header_) << function_signature(*f_iter, ifstyle) << ";" << endl;
+    // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style.
+    if (style == "Concurrent" && !(*f_iter)->is_oneway()) {
+      // concurrent clients need to move the seqid from the send function to the
+      // recv function.  Oneway methods don't have a recv function, so we don't need to
+      // mo

<TRUNCATED>

[19/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_csharp_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc
new file mode 100644
index 0000000..ae3c48b
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc
@@ -0,0 +1,3202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <cassert>
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+struct member_mapping_scope {
+  void* scope_member;
+  std::map<std::string, std::string> mapping_table;
+};
+
+class t_csharp_generator : public t_oop_generator {
+public:
+  t_csharp_generator(t_program* program,
+                     const std::map<std::string, std::string>& parsed_options,
+                     const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+
+    std::map<std::string, std::string>::const_iterator iter;
+
+    async_ = false;
+    nullable_ = false;
+    hashcode_ = false;
+    union_ = false;
+    serialize_ = false;
+    wcf_ = false;
+    wcf_namespace_.clear();
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("async") == 0) {
+        async_ = true;
+      } else if( iter->first.compare("nullable") == 0) {
+        nullable_ = true;
+      } else if( iter->first.compare("hashcode") == 0) {
+        hashcode_ = true;
+      } else if( iter->first.compare("union") == 0) {
+        union_ = true;
+      } else if( iter->first.compare("serial") == 0) {
+        serialize_ = true;
+        wcf_namespace_ = iter->second; // since there can be only one namespace
+      } else if( iter->first.compare("wcf") == 0) {
+        wcf_ = true;
+        wcf_namespace_ = iter->second;
+      } else {
+        throw "unknown option csharp:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-csharp";
+  }
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_union(t_struct* tunion);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+  void generate_property(ofstream& out, t_field* tfield, bool isPublic, bool generateIsset);
+  void generate_csharp_property(ofstream& out,
+                                t_field* tfield,
+                                bool isPublic,
+                                bool includeIsset = true,
+                                std::string fieldPrefix = "");
+  bool print_const_value(std::ofstream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false,
+                         bool needtype = false);
+  std::string render_const_value(std::ofstream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+  void print_const_constructor(std::ofstream& out, std::vector<t_const*> consts);
+  void print_const_def_value(std::ofstream& out,
+                             std::string name,
+                             t_type* type,
+                             t_const_value* value);
+
+  void generate_csharp_struct(t_struct* tstruct, bool is_exception);
+  void generate_csharp_union(t_struct* tunion);
+  void generate_csharp_struct_definition(std::ofstream& out,
+                                         t_struct* tstruct,
+                                         bool is_xception = false,
+                                         bool in_class = false,
+                                         bool is_result = false);
+  void generate_csharp_union_definition(std::ofstream& out, t_struct* tunion);
+  void generate_csharp_union_class(std::ofstream& out, t_struct* tunion, t_field* tfield);
+  void generate_csharp_wcffault(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_struct_tostring(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_struct_equals(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_struct_hashcode(std::ofstream& out, t_struct* tstruct);
+  void generate_csharp_union_reader(std::ofstream& out, t_struct* tunion);
+
+  void generate_function_helpers(t_function* tfunction);
+  void generate_service_interface(t_service* tservice);
+  void generate_separate_service_interfaces(t_service* tservice);
+  void generate_sync_service_interface(t_service* tservice);
+  void generate_async_service_interface(t_service* tservice);
+  void generate_combined_service_interface(t_service* tservice);
+  void generate_silverlight_async_methods(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_service_server_sync(t_service* tservice);
+  void generate_service_server_async(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* function);
+  void generate_process_function_async(t_service* tservice, t_function* function);
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool is_propertyless = false);
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_list_element(std::ofstream& out, t_list* list, std::string prefix = "");
+  void generate_serialize_field(std::ofstream& out,
+                                t_field* tfield,
+                                std::string prefix = "",
+                                bool is_element = false,
+                                bool is_propertyless = false);
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_csharp_doc(std::ofstream& out, t_field* field);
+  void generate_csharp_doc(std::ofstream& out, t_doc* tdoc);
+  void generate_csharp_doc(std::ofstream& out, t_function* tdoc);
+  void generate_csharp_docstring_comment(std::ofstream& out, string contents);
+
+  void start_csharp_namespace(std::ofstream& out);
+  void end_csharp_namespace(std::ofstream& out);
+
+  std::string csharp_type_usings();
+  std::string csharp_thrift_usings();
+
+  std::string type_name(t_type* ttype,
+                        bool in_countainer = false,
+                        bool in_init = false,
+                        bool in_param = false,
+                        bool is_required = false);
+  std::string base_type_name(t_base_type* tbase,
+                             bool in_container = false,
+                             bool in_param = false,
+                             bool is_required = false);
+  std::string declare_field(t_field* tfield, bool init = false, std::string prefix = "");
+  std::string function_signature_async_begin(t_function* tfunction, std::string prefix = "");
+  std::string function_signature_async_end(t_function* tfunction, std::string prefix = "");
+  std::string function_signature_async(t_function* tfunction, std::string prefix = "");
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string prop_name(t_field* tfield, bool suppress_mapping = false);
+  std::string get_enum_class_name(t_type* type);
+
+  bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; }
+
+  bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; }
+
+  bool type_can_be_null(t_type* ttype) {
+    while (ttype->is_typedef()) {
+      ttype = ((t_typedef*)ttype)->get_type();
+    }
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+private:
+  std::string namespace_name_;
+  std::ofstream f_service_;
+  std::string namespace_dir_;
+  bool async_;
+  bool nullable_;
+  bool union_;
+  bool hashcode_;
+  bool serialize_;
+  bool wcf_;
+  std::string wcf_namespace_;
+
+  std::map<std::string, int> csharp_keywords;
+  std::vector<member_mapping_scope>  member_mapping_scopes;
+
+  void init_keywords();
+  std::string normalize_name(std::string name);
+  std::string make_valid_csharp_identifier(std::string const& fromName);
+  void prepare_member_name_mapping(t_struct* tstruct);
+  void prepare_member_name_mapping(void* scope,
+                                   const vector<t_field*>& members,
+                                   const string& structname);
+  void cleanup_member_name_mapping(void* scope);
+  string get_mapped_member_name(string oldname);
+};
+
+void t_csharp_generator::init_generator() {
+  MKDIR(get_out_dir().c_str());
+  namespace_name_ = program_->get_namespace("csharp");
+
+  string dir = namespace_name_;
+  string subdir = get_out_dir().c_str();
+  string::size_type loc;
+
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  namespace_dir_ = subdir;
+  init_keywords();
+
+  while( ! member_mapping_scopes.empty()) {
+    cleanup_member_name_mapping( member_mapping_scopes.back().scope_member);
+  }
+
+  pverbose("C# options:\n");
+  pverbose("- async ...... %s\n", (async_ ? "ON" : "off"));
+  pverbose("- nullable ... %s\n", (nullable_ ? "ON" : "off"));
+  pverbose("- union ...... %s\n", (union_ ? "ON" : "off"));
+  pverbose("- hashcode ... %s\n", (hashcode_ ? "ON" : "off"));
+  pverbose("- serialize .. %s\n", (serialize_ ? "ON" : "off"));
+  pverbose("- wcf ........ %s\n", (wcf_ ? "ON" : "off"));
+}
+
+std::string t_csharp_generator::normalize_name(std::string name) {
+  string tmp(name);
+  std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
+
+  // un-conflict keywords by prefixing with "@"
+  if (csharp_keywords.find(tmp) != csharp_keywords.end()) {
+    return "@" + name;
+  }
+
+  // no changes necessary
+  return name;
+}
+
+void t_csharp_generator::init_keywords() {
+  csharp_keywords.clear();
+
+  // C# keywords
+  csharp_keywords["abstract"] = 1;
+  csharp_keywords["as"] = 1;
+  csharp_keywords["base"] = 1;
+  csharp_keywords["bool"] = 1;
+  csharp_keywords["break"] = 1;
+  csharp_keywords["byte"] = 1;
+  csharp_keywords["case"] = 1;
+  csharp_keywords["catch"] = 1;
+  csharp_keywords["char"] = 1;
+  csharp_keywords["checked"] = 1;
+  csharp_keywords["class"] = 1;
+  csharp_keywords["const"] = 1;
+  csharp_keywords["continue"] = 1;
+  csharp_keywords["decimal"] = 1;
+  csharp_keywords["default"] = 1;
+  csharp_keywords["delegate"] = 1;
+  csharp_keywords["do"] = 1;
+  csharp_keywords["double"] = 1;
+  csharp_keywords["else"] = 1;
+  csharp_keywords["enum"] = 1;
+  csharp_keywords["event"] = 1;
+  csharp_keywords["explicit"] = 1;
+  csharp_keywords["extern"] = 1;
+  csharp_keywords["false"] = 1;
+  csharp_keywords["finally"] = 1;
+  csharp_keywords["fixed"] = 1;
+  csharp_keywords["float"] = 1;
+  csharp_keywords["for"] = 1;
+  csharp_keywords["foreach"] = 1;
+  csharp_keywords["goto"] = 1;
+  csharp_keywords["if"] = 1;
+  csharp_keywords["implicit"] = 1;
+  csharp_keywords["in"] = 1;
+  csharp_keywords["int"] = 1;
+  csharp_keywords["interface"] = 1;
+  csharp_keywords["internal"] = 1;
+  csharp_keywords["is"] = 1;
+  csharp_keywords["lock"] = 1;
+  csharp_keywords["long"] = 1;
+  csharp_keywords["namespace"] = 1;
+  csharp_keywords["new"] = 1;
+  csharp_keywords["null"] = 1;
+  csharp_keywords["object"] = 1;
+  csharp_keywords["operator"] = 1;
+  csharp_keywords["out"] = 1;
+  csharp_keywords["override"] = 1;
+  csharp_keywords["params"] = 1;
+  csharp_keywords["private"] = 1;
+  csharp_keywords["protected"] = 1;
+  csharp_keywords["public"] = 1;
+  csharp_keywords["readonly"] = 1;
+  csharp_keywords["ref"] = 1;
+  csharp_keywords["return"] = 1;
+  csharp_keywords["sbyte"] = 1;
+  csharp_keywords["sealed"] = 1;
+  csharp_keywords["short"] = 1;
+  csharp_keywords["sizeof"] = 1;
+  csharp_keywords["stackalloc"] = 1;
+  csharp_keywords["static"] = 1;
+  csharp_keywords["string"] = 1;
+  csharp_keywords["struct"] = 1;
+  csharp_keywords["switch"] = 1;
+  csharp_keywords["this"] = 1;
+  csharp_keywords["throw"] = 1;
+  csharp_keywords["true"] = 1;
+  csharp_keywords["try"] = 1;
+  csharp_keywords["typeof"] = 1;
+  csharp_keywords["uint"] = 1;
+  csharp_keywords["ulong"] = 1;
+  csharp_keywords["unchecked"] = 1;
+  csharp_keywords["unsafe"] = 1;
+  csharp_keywords["ushort"] = 1;
+  csharp_keywords["using"] = 1;
+  csharp_keywords["virtual"] = 1;
+  csharp_keywords["void"] = 1;
+  csharp_keywords["volatile"] = 1;
+  csharp_keywords["while"] = 1;
+
+  // C# contextual keywords
+  csharp_keywords["add"] = 1;
+  csharp_keywords["alias"] = 1;
+  csharp_keywords["ascending"] = 1;
+  csharp_keywords["async"] = 1;
+  csharp_keywords["await"] = 1;
+  csharp_keywords["descending"] = 1;
+  csharp_keywords["dynamic"] = 1;
+  csharp_keywords["from"] = 1;
+  csharp_keywords["get"] = 1;
+  csharp_keywords["global"] = 1;
+  csharp_keywords["group"] = 1;
+  csharp_keywords["into"] = 1;
+  csharp_keywords["join"] = 1;
+  csharp_keywords["let"] = 1;
+  csharp_keywords["orderby"] = 1;
+  csharp_keywords["partial"] = 1;
+  csharp_keywords["remove"] = 1;
+  csharp_keywords["select"] = 1;
+  csharp_keywords["set"] = 1;
+  csharp_keywords["value"] = 1;
+  csharp_keywords["var"] = 1;
+  csharp_keywords["where"] = 1;
+  csharp_keywords["yield"] = 1;
+}
+
+void t_csharp_generator::start_csharp_namespace(ofstream& out) {
+  if (!namespace_name_.empty()) {
+    out << "namespace " << namespace_name_ << "\n";
+    scope_up(out);
+  }
+}
+
+void t_csharp_generator::end_csharp_namespace(ofstream& out) {
+  if (!namespace_name_.empty()) {
+    scope_down(out);
+  }
+}
+
+string t_csharp_generator::csharp_type_usings() {
+  return string() + "using System;\n" + "using System.Collections;\n"
+         + "using System.Collections.Generic;\n" + "using System.Text;\n" + "using System.IO;\n"
+         + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n"
+         + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "")
+         + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "")
+         + ((serialize_ || wcf_) ? "#endif\n" : "") + (wcf_ ? "//using System.ServiceModel;\n" : "")
+         + "using System.Runtime.Serialization;\n";
+}
+
+string t_csharp_generator::csharp_thrift_usings() {
+  return string() + "using Thrift.Protocol;\n" + "using Thrift.Transport;\n";
+}
+
+void t_csharp_generator::close_generator() {
+}
+void t_csharp_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+void t_csharp_generator::generate_enum(t_enum* tenum) {
+  string f_enum_name = namespace_dir_ + "/" + (tenum->get_name()) + ".cs";
+  ofstream f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  f_enum << autogen_comment() << endl;
+
+  start_csharp_namespace(f_enum);
+
+  generate_csharp_doc(f_enum, tenum);
+
+  indent(f_enum) << "public enum " << tenum->get_name() << "\n";
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    generate_csharp_doc(f_enum, *c_iter);
+
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << (*c_iter)->get_name() << " = " << value << "," << endl;
+  }
+
+  scope_down(f_enum);
+
+  end_csharp_namespace(f_enum);
+
+  f_enum.close();
+}
+
+void t_csharp_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+  string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs";
+  ofstream f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  f_consts << autogen_comment() << csharp_type_usings() << endl;
+
+  start_csharp_namespace(f_consts);
+
+  indent(f_consts) << "public static class " << make_valid_csharp_identifier(program_name_)
+                   << "Constants" << endl;
+  scope_up(f_consts);
+
+  vector<t_const*>::iterator c_iter;
+  bool need_static_constructor = false;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    generate_csharp_doc(f_consts, (*c_iter));
+    if (print_const_value(f_consts,
+                          (*c_iter)->get_name(),
+                          (*c_iter)->get_type(),
+                          (*c_iter)->get_value(),
+                          false)) {
+      need_static_constructor = true;
+    }
+  }
+
+  if (need_static_constructor) {
+    print_const_constructor(f_consts, consts);
+  }
+
+  scope_down(f_consts);
+  end_csharp_namespace(f_consts);
+  f_consts.close();
+}
+
+void t_csharp_generator::print_const_def_value(std::ofstream& out,
+                                               string name,
+                                               t_type* type,
+                                               t_const_value* value) {
+  if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    prepare_member_name_mapping((t_struct*)type);
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_field* field = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field = (*f_iter);
+        }
+      }
+      if (field == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      t_type* field_type = field->get_type();
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << "." << prop_name(field) << " = " << val << ";" << endl;
+    }
+    cleanup_member_name_mapping((t_struct*)type);
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << "[" << key << "]"
+                  << " = " << val << ";" << endl;
+    }
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << ".Add(" << val << ");" << endl;
+    }
+  }
+}
+
+void t_csharp_generator::print_const_constructor(std::ofstream& out, std::vector<t_const*> consts) {
+  indent(out) << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()"
+              << endl;
+  scope_up(out);
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    t_type* type = (*c_iter)->get_type();
+    t_const_value* value = (*c_iter)->get_value();
+
+    print_const_def_value(out, name, type, value);
+  }
+  scope_down(out);
+}
+
+// it seems like all that methods that call this are using in_static to be the opposite of what it
+// would imply
+bool t_csharp_generator::print_const_value(std::ofstream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value,
+                                           bool in_static,
+                                           bool defval,
+                                           bool needtype) {
+  indent(out);
+  bool need_static_construction = !in_static;
+  while (type->is_typedef()) {
+    type = ((t_typedef*)type)->get_type();
+  }
+
+  if (!defval || needtype) {
+    out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ")
+        << type_name(type) << " ";
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    out << name << " = " << v2 << ";" << endl;
+    need_static_construction = false;
+  } else if (type->is_enum()) {
+    out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name()
+        << ";" << endl;
+    need_static_construction = false;
+  } else if (type->is_struct() || type->is_xception()) {
+    out << name << " = new " << type_name(type) << "();" << endl;
+  } else if (type->is_map()) {
+    out << name << " = new " << type_name(type, true, true) << "();" << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name << " = new " << type_name(type) << "();" << endl;
+  }
+
+  if (defval && !type->is_base_type() && !type->is_enum()) {
+    print_const_def_value(out, name, type, value);
+  }
+
+  return need_static_construction;
+}
+
+std::string t_csharp_generator::render_const_value(ofstream& out,
+                                                   string name,
+                                                   t_type* type,
+                                                   t_const_value* value) {
+  (void)name;
+  std::ostringstream render;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << type->get_name() << "." << value->get_identifier_name();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true, true, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+void t_csharp_generator::generate_struct(t_struct* tstruct) {
+  if (union_ && tstruct->is_union()) {
+    generate_csharp_union(tstruct);
+  } else {
+    generate_csharp_struct(tstruct, false);
+  }
+}
+
+void t_csharp_generator::generate_xception(t_struct* txception) {
+  generate_csharp_struct(txception, true);
+}
+
+void t_csharp_generator::generate_csharp_struct(t_struct* tstruct, bool is_exception) {
+  string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs";
+  ofstream f_struct;
+
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
+
+  generate_csharp_struct_definition(f_struct, tstruct, is_exception);
+
+  f_struct.close();
+}
+
+void t_csharp_generator::generate_csharp_struct_definition(ofstream& out,
+                                                           t_struct* tstruct,
+                                                           bool is_exception,
+                                                           bool in_class,
+                                                           bool is_result) {
+
+  if (!in_class) {
+    start_csharp_namespace(out);
+  }
+
+  out << endl;
+
+  generate_csharp_doc(out, tstruct);
+  prepare_member_name_mapping(tstruct);
+
+  indent(out) << "#if !SILVERLIGHT" << endl;
+  indent(out) << "[Serializable]" << endl;
+  indent(out) << "#endif" << endl;
+  if ((serialize_ || wcf_) && !is_exception) {
+    indent(out) << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]"
+                << endl; // do not make exception classes directly WCF serializable, we provide a
+                         // separate "fault" for that
+  }
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+
+  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class "
+              << normalize_name(tstruct->get_name()) << " : ";
+
+  if (is_exception) {
+    out << "TException, ";
+  }
+  out << "TBase";
+
+  out << endl;
+
+  scope_up(out);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // make private members with public Properties
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    // if the field is requied, then we use auto-properties
+    if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) {
+      indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
+    }
+  }
+  out << endl;
+
+  bool has_non_required_fields = false;
+  bool has_non_required_default_value_fields = false;
+  bool has_required_fields = false;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_csharp_doc(out, *m_iter);
+    generate_property(out, *m_iter, true, true);
+    bool is_required = field_is_required((*m_iter));
+    bool has_default = field_has_default((*m_iter));
+    if (is_required) {
+      has_required_fields = true;
+    } else {
+      if (has_default) {
+        has_non_required_default_value_fields = true;
+      }
+      has_non_required_fields = true;
+    }
+  }
+
+  bool generate_isset = (nullable_ && has_non_required_default_value_fields)
+                        || (!nullable_ && has_non_required_fields);
+  if (generate_isset) {
+    out << endl;
+    if (serialize_ || wcf_) {
+      out << indent() << "[XmlIgnore] // XmlSerializer" << endl << indent()
+          << "[DataMember(Order = 1)]  // XmlObjectSerializer, DataContractJsonSerializer, etc."
+          << endl;
+    }
+    out << indent() << "public Isset __isset;" << endl << indent() << "#if !SILVERLIGHT" << endl
+        << indent() << "[Serializable]" << endl << indent() << "#endif" << endl;
+    if (serialize_ || wcf_) {
+      indent(out) << "[DataContract]" << endl;
+    }
+    indent(out) << "public struct Isset {" << endl;
+    indent_up();
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      bool is_required = field_is_required((*m_iter));
+      bool has_default = field_has_default((*m_iter));
+      // if it is required, don't need Isset for that variable
+      // if it is not required, if it has a default value, we need to generate Isset
+      // if we are not nullable, then we generate Isset
+      if (!is_required && (!nullable_ || has_default)) {
+        if (serialize_ || wcf_) {
+          indent(out) << "[DataMember]" << endl;
+        }
+        indent(out) << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl;
+      }
+    }
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    if (generate_isset && (serialize_ || wcf_)) {
+      indent(out) << "#region XmlSerializer support" << endl << endl;
+
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        bool is_required = field_is_required((*m_iter));
+        bool has_default = field_has_default((*m_iter));
+        // if it is required, don't need Isset for that variable
+        // if it is not required, if it has a default value, we need to generate Isset
+        // if we are not nullable, then we generate Isset
+        if (!is_required && (!nullable_ || has_default)) {
+          indent(out) << "public bool ShouldSerialize" << prop_name((*m_iter)) << "()" << endl;
+          indent(out) << "{" << endl;
+          indent_up();
+          indent(out) << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl;
+          indent_down();
+          indent(out) << "}" << endl << endl;
+        }
+      }
+
+      indent(out) << "#endregion XmlSerializer support" << endl << endl;
+    }
+  }
+
+  // We always want a default, no argument constructor for Reading
+  indent(out) << "public " << normalize_name(tstruct->get_name()) << "() {" << endl;
+  indent_up();
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = (*m_iter)->get_type();
+    while (t->is_typedef()) {
+      t = ((t_typedef*)t)->get_type();
+    }
+    if ((*m_iter)->get_value() != NULL) {
+      if (field_is_required((*m_iter))) {
+        print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true);
+      } else {
+        print_const_value(out,
+                          "this._" + (*m_iter)->get_name(),
+                          t,
+                          (*m_iter)->get_value(),
+                          true,
+                          true);
+        // Optionals with defaults are marked set
+        indent(out) << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;"
+                    << endl;
+      }
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  if (has_required_fields) {
+    indent(out) << "public " << tstruct->get_name() << "(";
+    bool first = true;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (field_is_required((*m_iter))) {
+        if (first) {
+          first = false;
+        } else {
+          out << ", ";
+        }
+        out << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
+      }
+    }
+    out << ") : this() {" << endl;
+    indent_up();
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (field_is_required((*m_iter))) {
+        indent(out) << "this." << prop_name((*m_iter)) << " = " << (*m_iter)->get_name() << ";"
+                    << endl;
+      }
+    }
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+
+  generate_csharp_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_csharp_struct_result_writer(out, tstruct);
+  } else {
+    generate_csharp_struct_writer(out, tstruct);
+  }
+  if (hashcode_) {
+    generate_csharp_struct_equals(out, tstruct);
+    generate_csharp_struct_hashcode(out, tstruct);
+  }
+  generate_csharp_struct_tostring(out, tstruct);
+  scope_down(out);
+  out << endl;
+
+  // generate a corresponding WCF fault to wrap the exception
+  if ((serialize_ || wcf_) && is_exception) {
+    generate_csharp_wcffault(out, tstruct);
+  }
+
+  cleanup_member_name_mapping(tstruct);
+  if (!in_class) {
+    end_csharp_namespace(out);
+  }
+}
+
+void t_csharp_generator::generate_csharp_wcffault(ofstream& out, t_struct* tstruct) {
+  out << endl;
+  indent(out) << "#if !SILVERLIGHT" << endl;
+  indent(out) << "[Serializable]" << endl;
+  indent(out) << "#endif" << endl;
+  indent(out) << "[DataContract]" << endl;
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+
+  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name()
+              << "Fault" << endl;
+
+  scope_up(out);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // make private members with public Properties
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
+  }
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_property(out, *m_iter, true, false);
+  }
+
+  scope_down(out);
+  out << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_reader(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public void Read (TProtocol iprot)" << endl;
+  scope_up(out);
+
+  out << indent() << "iprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Required variables aren't in __isset, so we need tmp vars to check them
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (field_is_required((*f_iter))) {
+      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
+    }
+  }
+
+  indent(out) << "TField field;" << endl << indent() << "iprot.ReadStructBegin();" << endl;
+
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  indent(out) << "field = iprot.ReadFieldBegin();" << endl;
+
+  indent(out) << "if (field.Type == TType.Stop) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent(out) << "switch (field.ID)" << endl;
+
+  scope_up(out);
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool is_required = field_is_required((*f_iter));
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter);
+    if (is_required) {
+      indent(out) << "isset_" << (*f_iter)->get_name() << " = true;" << endl;
+    }
+
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
+        << endl << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default: " << endl;
+  indent_up();
+  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl;
+  indent(out) << "break;" << endl;
+  indent_down();
+
+  scope_down(out);
+
+  indent(out) << "iprot.ReadFieldEnd();" << endl;
+
+  scope_down(out);
+
+  indent(out) << "iprot.ReadStructEnd();" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (field_is_required((*f_iter))) {
+      indent(out) << "if (!isset_" << (*f_iter)->get_name() << ")" << endl;
+      indent_up();
+      indent(out) << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl;
+      indent_down();
+    }
+  }
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "iprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_writer(ofstream& out, t_struct* tstruct) {
+  out << indent() << "public void Write(TProtocol oprot) {" << endl;
+  indent_up();
+
+  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl;
+  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
+
+  if (fields.size() > 0) {
+    indent(out) << "TField field = new TField();" << endl;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      bool is_required = field_is_required((*f_iter));
+      bool has_default = field_has_default((*f_iter));
+      if (nullable_ && !has_default && !is_required) {
+        indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl;
+        indent_up();
+      } else if (!is_required) {
+        bool null_allowed = type_can_be_null((*f_iter)->get_type());
+        if (null_allowed) {
+          indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset."
+                      << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+          indent_up();
+        } else {
+          indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+          indent_up();
+        }
+      }
+      indent(out) << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl;
+      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
+      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl;
+      indent(out) << "oprot.WriteFieldBegin(field);" << endl;
+
+      generate_serialize_field(out, *f_iter);
+
+      indent(out) << "oprot.WriteFieldEnd();" << endl;
+      if (!is_required) {
+        indent_down();
+        indent(out) << "}" << endl;
+      }
+    }
+  }
+
+  indent(out) << "oprot.WriteFieldStop();" << endl;
+  indent(out) << "oprot.WriteStructEnd();" << endl;
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_result_writer(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public void Write(TProtocol oprot) {" << endl;
+  indent_up();
+
+  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl;
+  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
+
+  if (fields.size() > 0) {
+    indent(out) << "TField field = new TField();" << endl;
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+        out << endl << indent() << "if ";
+      } else {
+        out << " else if ";
+      }
+
+      if (nullable_) {
+        out << "(this." << prop_name((*f_iter)) << " != null) {" << endl;
+      } else {
+        out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+      }
+      indent_up();
+
+      bool null_allowed = !nullable_ && type_can_be_null((*f_iter)->get_type());
+      if (null_allowed) {
+        indent(out) << "if (" << prop_name(*f_iter) << " != null) {" << endl;
+        indent_up();
+      }
+
+      indent(out) << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl;
+      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
+      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl;
+      indent(out) << "oprot.WriteFieldBegin(field);" << endl;
+
+      generate_serialize_field(out, *f_iter);
+
+      indent(out) << "oprot.WriteFieldEnd();" << endl;
+
+      if (null_allowed) {
+        indent_down();
+        indent(out) << "}" << endl;
+      }
+
+      indent_down();
+      indent(out) << "}";
+    }
+  }
+
+  out << endl << indent() << "oprot.WriteFieldStop();" << endl << indent()
+      << "oprot.WriteStructEnd();" << endl;
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_tostring(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public override string ToString() {" << endl;
+  indent_up();
+
+  indent(out) << "StringBuilder __sb = new StringBuilder(\"" << tstruct->get_name() << "(\");"
+              << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  bool useFirstFlag = false;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (!field_is_required((*f_iter))) {
+      indent(out) << "bool __first = true;" << endl;
+      useFirstFlag = true;
+    }
+    break;
+  }
+
+  bool had_required = false; // set to true after first required field has been processed
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool is_required = field_is_required((*f_iter));
+    bool has_default = field_has_default((*f_iter));
+    if (nullable_ && !has_default && !is_required) {
+      indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl;
+      indent_up();
+    } else if (!is_required) {
+      bool null_allowed = type_can_be_null((*f_iter)->get_type());
+      if (null_allowed) {
+        indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset."
+                    << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+        indent_up();
+      } else {
+        indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+        indent_up();
+      }
+    }
+
+    if (useFirstFlag && (!had_required)) {
+      indent(out) << "if(!__first) { __sb.Append(\", \"); }" << endl;
+      if (!is_required) {
+        indent(out) << "__first = false;" << endl;
+      }
+      indent(out) << "__sb.Append(\"" << prop_name((*f_iter)) << ": \");" << endl;
+    } else {
+      indent(out) << "__sb.Append(\", " << prop_name((*f_iter)) << ": \");" << endl;
+    }
+
+    t_type* ttype = (*f_iter)->get_type();
+    if (ttype->is_xception() || ttype->is_struct()) {
+      indent(out) << "__sb.Append(" << prop_name((*f_iter))
+                  << "== null ? \"<null>\" : " << prop_name((*f_iter)) << ".ToString());" << endl;
+    } else {
+      indent(out) << "__sb.Append(" << prop_name((*f_iter)) << ");" << endl;
+    }
+
+    if (!is_required) {
+      indent_down();
+      indent(out) << "}" << endl;
+    } else {
+      had_required = true; // now __first must be false, so we don't need to check it anymore
+    }
+  }
+
+  indent(out) << "__sb.Append(\")\");" << endl;
+  indent(out) << "return __sb.ToString();" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_union(t_struct* tunion) {
+  string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs";
+  ofstream f_union;
+
+  f_union.open(f_union_name.c_str());
+
+  f_union << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
+
+  generate_csharp_union_definition(f_union, tunion);
+
+  f_union.close();
+}
+
+void t_csharp_generator::generate_csharp_union_definition(std::ofstream& out, t_struct* tunion) {
+  // Let's define the class first
+  start_csharp_namespace(out);
+
+  indent(out) << "public abstract partial class " << tunion->get_name() << " : TAbstractBase {"
+              << endl;
+
+  indent_up();
+
+  indent(out) << "public abstract void Write(TProtocol protocol);" << endl;
+  indent(out) << "public readonly bool Isset;" << endl;
+  indent(out) << "public abstract object Data { get; }" << endl;
+
+  indent(out) << "protected " << tunion->get_name() << "(bool isset) {" << endl;
+  indent_up();
+  indent(out) << "Isset = isset;" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "public class ___undefined : " << tunion->get_name() << " {" << endl;
+  indent_up();
+
+  indent(out) << "public override object Data { get { return null; } }" << endl;
+
+  indent(out) << "public ___undefined() : base(false) {}" << endl << endl;
+
+  indent(out) << "public override void Write(TProtocol protocol) {" << endl;
+  indent_up();
+  indent(out) << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist "
+                 "an union type which is not set.\");" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  const vector<t_field*>& fields = tunion->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    generate_csharp_union_class(out, tunion, (*f_iter));
+  }
+
+  generate_csharp_union_reader(out, tunion);
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  end_csharp_namespace(out);
+}
+
+void t_csharp_generator::generate_csharp_union_class(std::ofstream& out,
+                                                     t_struct* tunion,
+                                                     t_field* tfield) {
+  indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {"
+              << endl;
+  indent_up();
+  indent(out) << "private " << type_name(tfield->get_type()) << " _data;" << endl;
+  indent(out) << "public override object Data { get { return _data; } }" << endl;
+  indent(out) << "public " << tfield->get_name() << "(" << type_name(tfield->get_type())
+              << " data) : base(true) {" << endl;
+  indent_up();
+  indent(out) << "this._data = data;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+  indent(out) << "public override void Write(TProtocol oprot) {" << endl;
+  indent_up();
+
+  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  indent(out) << "TStruct struc = new TStruct(\"" << tunion->get_name() << "\");" << endl;
+  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
+
+  indent(out) << "TField field = new TField();" << endl;
+  indent(out) << "field.Name = \"" << tfield->get_name() << "\";" << endl;
+  indent(out) << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl;
+  indent(out) << "field.ID = " << tfield->get_key() << ";" << endl;
+  indent(out) << "oprot.WriteFieldBegin(field);" << endl;
+
+  generate_serialize_field(out, tfield, "_data", true, true);
+
+  indent(out) << "oprot.WriteFieldEnd();" << endl;
+  indent(out) << "oprot.WriteFieldStop();" << endl;
+  indent(out) << "oprot.WriteStructEnd();" << endl;
+  indent_down();
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_equals(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public override bool Equals(object that) {" << endl;
+  indent_up();
+
+  indent(out) << "var other = that as " << type_name(tstruct) << ";" << endl;
+  indent(out) << "if (other == null) return false;" << endl;
+  indent(out) << "if (ReferenceEquals(this, other)) return true;" << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  bool first = true;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      indent(out) << "return ";
+      indent_up();
+    } else {
+      out << endl;
+      indent(out) << "&& ";
+    }
+    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) {
+      out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset."
+          << normalize_name((*f_iter)->get_name()) << ") && ((!__isset."
+          << normalize_name((*f_iter)->get_name()) << ") || (";
+    }
+    t_type* ttype = (*f_iter)->get_type();
+    if (ttype->is_container() || (ttype->is_base_type() && (((t_base_type*)ttype)->is_binary()))) {
+      out << "TCollections.Equals(";
+    } else {
+      out << "System.Object.Equals(";
+    }
+    out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")";
+    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) {
+      out << ")))";
+    }
+  }
+  if (first) {
+    indent(out) << "return true;" << endl;
+  } else {
+    out << ";" << endl;
+    indent_down();
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_hashcode(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public override int GetHashCode() {" << endl;
+  indent_up();
+
+  indent(out) << "int hashcode = 0;" << endl;
+  indent(out) << "unchecked {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_type* ttype = (*f_iter)->get_type();
+    indent(out) << "hashcode = (hashcode * 397) ^ ";
+    if (field_is_required((*f_iter))) {
+      out << "(";
+    } else if (nullable_) {
+      out << "(" << prop_name((*f_iter)) << " == null ? 0 : ";
+    } else {
+      out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : ";
+    }
+    if (ttype->is_container()) {
+      out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))";
+    } else {
+      out << "(" << prop_name((*f_iter)) << ".GetHashCode())";
+    }
+    out << ");" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl;
+  indent(out) << "return hashcode;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_service(t_service* tservice) {
+  string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
+
+  start_csharp_namespace(f_service_);
+
+  indent(f_service_) << "public partial class " << normalize_name(service_name_) << " {" << endl;
+  indent_up();
+
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+
+  indent_down();
+
+  indent(f_service_) << "}" << endl;
+  end_csharp_namespace(f_service_);
+  f_service_.close();
+}
+
+void t_csharp_generator::generate_service_interface(t_service* tservice) {
+  generate_separate_service_interfaces(tservice);
+}
+
+void t_csharp_generator::generate_separate_service_interfaces(t_service* tservice) {
+  generate_sync_service_interface(tservice);
+
+  if (async_) {
+    generate_async_service_interface(tservice);
+  }
+
+  generate_combined_service_interface(tservice);
+}
+
+void t_csharp_generator::generate_sync_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_iface = " : " + extends + ".ISync";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  if (wcf_) {
+    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+  }
+  indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl;
+
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_csharp_doc(f_service_, *f_iter);
+
+    // if we're using WCF, add the corresponding attributes
+    if (wcf_) {
+      indent(f_service_) << "[OperationContract]" << endl;
+
+      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        indent(f_service_) << "[FaultContract(typeof("
+          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
+      }
+    }
+
+    indent(f_service_) << function_signature(*f_iter) << ";" << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_async_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_iface = " : " + extends + ".IAsync";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  if (wcf_) {
+    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+  }
+  indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl;
+
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_csharp_doc(f_service_, *f_iter);
+
+    // if we're using WCF, add the corresponding attributes
+    if (wcf_) {
+      indent(f_service_) << "[OperationContract]" << endl;
+
+      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        indent(f_service_) << "[FaultContract(typeof("
+          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
+      }
+    }
+
+    indent(f_service_) << function_signature_async(*f_iter) << ";" << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_combined_service_interface(t_service* tservice) {
+  string extends_iface = " : ISync";
+
+  if (async_) {
+    extends_iface += ", IAsync";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  if (wcf_) {
+    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+  }
+
+  indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl;
+
+  indent_up();
+
+  // We need to generate extra old style async methods for silverlight. Since
+  // this isn't something you'd want to implement server-side, just put them into
+  // the main Iface interface.
+  generate_silverlight_async_methods(tservice);
+
+  indent_down();
+
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_silverlight_async_methods(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_csharp_doc(f_service_, *f_iter);
+
+    // For backwards compatibility, include the Begin_, End_ methods if we're generating
+    // with the async flag. I'm not sure this is necessary, so someone with more knowledge
+    // can maybe remove these checks if they know it's safe.
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+
+    indent(f_service_) << function_signature_async_begin(*f_iter, "Begin_") << ";" << endl;
+    indent(f_service_) << function_signature_async_end(*f_iter, "End_") << ";" << endl;
+
+    if (!async_) {
+      indent(f_service_) << "#endif" << endl;
+    }
+  }
+}
+
+void t_csharp_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_csharp_struct_definition(f_service_, ts, false, true);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+void t_csharp_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = extends + ".Client, ";
+  } else {
+    extends_client = "IDisposable, ";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  indent(f_service_) << "public class Client : " << extends_client << "Iface {" << endl;
+  indent_up();
+  indent(f_service_) << "public Client(TProtocol prot) : this(prot, prot)" << endl;
+  scope_up(f_service_);
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)";
+  if (!extends.empty()) {
+    f_service_ << " : base(iprot, oprot)";
+  }
+  f_service_ << endl;
+
+  scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl;
+  }
+  scope_down(f_service_);
+
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent()
+               << "protected TProtocol oprot_;" << endl << indent() << "protected int seqid_;"
+               << endl << endl;
+
+    f_service_ << indent() << "public TProtocol InputProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "get { return iprot_; }" << endl;
+    scope_down(f_service_);
+
+    f_service_ << indent() << "public TProtocol OutputProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "get { return oprot_; }" << endl;
+    scope_down(f_service_);
+    f_service_ << endl << endl;
+
+    indent(f_service_) << "#region \" IDisposable Support \"" << endl;
+    indent(f_service_) << "private bool _IsDisposed;" << endl << endl;
+    indent(f_service_) << "// IDisposable" << endl;
+    indent(f_service_) << "public void Dispose()" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "Dispose(true);" << endl;
+    scope_down(f_service_);
+    indent(f_service_) << endl << endl;
+    indent(f_service_) << "protected virtual void Dispose(bool disposing)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "if (!_IsDisposed)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "if (disposing)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "if (iprot_ != null)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "((IDisposable)iprot_).Dispose();" << endl;
+    scope_down(f_service_);
+    indent(f_service_) << "if (oprot_ != null)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "((IDisposable)oprot_).Dispose();" << endl;
+    scope_down(f_service_);
+    scope_down(f_service_);
+    scope_down(f_service_);
+    indent(f_service_) << "_IsDisposed = true;" << endl;
+    scope_down(f_service_);
+    indent(f_service_) << "#endregion" << endl;
+    f_service_ << endl << endl;
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    indent(f_service_) << endl;
+
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+    // Begin_
+    indent(f_service_) << "public " << function_signature_async_begin(*f_iter, "Begin_") << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return "
+                       << "send_" << funname << "(callback, state";
+
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    prepare_member_name_mapping(arg_struct);
+
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", ";
+      f_service_ << normalize_name((*fld_iter)->get_name());
+    }
+    f_service_ << ");" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // End
+    indent(f_service_) << "public " << function_signature_async_end(*f_iter, "End_") << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "oprot_.Transport.EndFlush(asyncResult);" << endl;
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "recv_" << funname << "();" << endl;
+    }
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // async
+    bool first;
+    if (async_) {
+      indent(f_service_) << "public async " << function_signature_async(*f_iter, "") << endl;
+      scope_up(f_service_);
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << type_name((*f_iter)->get_returntype()) << " retval;" << endl;
+        indent(f_service_) << "retval = ";
+      } else {
+        indent(f_service_);
+      }
+      f_service_ << "await Task.Run(() =>" << endl;
+      scope_up(f_service_);
+      indent(f_service_);
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << funname << "(";
+      first = true;
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        if (first) {
+          first = false;
+        } else {
+          f_service_ << ", ";
+        }
+        f_service_ << (*fld_iter)->get_name();
+      }
+      f_service_ << ");" << endl;
+      indent_down();
+      indent(f_service_) << "});" << endl;
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return retval;" << endl;
+      }
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+
+    if (!async_) {
+      indent(f_service_) << "#endif" << endl << endl;
+    }
+
+    // "Normal" Synchronous invoke
+    generate_csharp_doc(f_service_, *f_iter);
+    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
+    scope_up(f_service_);
+
+    if (!async_) {
+      indent(f_service_) << "#if !SILVERLIGHT" << endl;
+      indent(f_service_) << "send_" << funname << "(";
+
+      first = true;
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        if (first) {
+          first = false;
+        } else {
+          f_service_ << ", ";
+        }
+        f_service_ << normalize_name((*fld_iter)->get_name());
+      }
+      f_service_ << ");" << endl;
+
+      if (!(*f_iter)->is_oneway()) {
+        f_service_ << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          f_service_ << "return ";
+        }
+        f_service_ << "recv_" << funname << "();" << endl;
+      }
+      f_service_ << endl;
+
+      indent(f_service_) << "#else" << endl;
+    }
+
+    // Silverlight synchronous invoke
+    indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null";
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", " << normalize_name((*fld_iter)->get_name());
+    }
+    f_service_ << ");" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "End_" << funname << "(asyncResult);" << endl;
+    }
+    f_service_ << endl;
+
+    if (!async_) {
+      indent(f_service_) << "#endif" << endl;
+    }
+    scope_down(f_service_);
+
+    // Send
+    t_function send_function(g_type_void,
+                             string("send_") + (*f_iter)->get_name(),
+                             (*f_iter)->get_arglist());
+
+    string argsname = (*f_iter)->get_name() + "_args";
+
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+    indent(f_service_) << "public " << function_signature_async_begin(&send_function) << endl;
+    if (!async_) {
+      indent(f_service_) << "#else" << endl;
+      indent(f_service_) << "public " << function_signature(&send_function) << endl;
+      indent(f_service_) << "#endif" << endl;
+    }
+    scope_up(f_service_);
+
+    f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call")
+               << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname
+               << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << prop_name(*fld_iter) << " = "
+                 << normalize_name((*fld_iter)->get_name()) << ";" << endl;
+    }
+
+    f_service_ << indent() << "args.Write(oprot_);" << endl << indent()
+               << "oprot_.WriteMessageEnd();" << endl;
+    ;
+
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+    indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl;
+    if (!async_) {
+      indent(f_service_) << "#else" << endl;
+      indent(f_service_) << "oprot_.Transport.Flush();" << endl;
+      indent(f_service_) << "#endif" << endl;
+    }
+
+    cleanup_member_name_mapping(arg_struct);
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      string resultname = (*f_iter)->get_name() + "_result";
+
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      indent(f_service_) << "public " << function_signature(&recv_function) << endl;
+      scope_up(f_service_);
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      prepare_member_name_mapping(xs, xs->get_members(), resultname);
+
+      f_service_ << indent() << "TMessage msg = iprot_.ReadMessageBegin();" << endl << indent()
+                 << "if (msg.Type == TMessageType.Exception) {" << endl;
+      indent_up();
+      f_service_ << indent() << "TApplicationException x = TApplicationException.Read(iprot_);"
+                 << endl << indent() << "iprot_.ReadMessageEnd();" << endl << indent() << "throw x;"
+                 << endl;
+      indent_down();
+      f_service_ << indent() << "}" << endl << indent() << resultname << " result = new "
+                 << resultname << "();" << endl << indent() << "result.Read(iprot_);" << endl
+                 << indent() << "iprot_.ReadMessageEnd();" << endl;
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        if (nullable_) {
+          if (type_can_be_null((*f_iter)->get_returntype())) {
+            f_service_ << indent() << "if (result.Success != null) {" << endl << indent()
+                       << "  return result.Success;" << endl << indent() << "}" << endl;
+          } else {
+            f_service_ << indent() << "if (result.Success.HasValue) {" << endl << indent()
+                       << "  return result.Success.Value;" << endl << indent() << "}" << endl;
+          }
+        } else {
+          f_service_ << indent() << "if (result.__isset.success) {" << endl << indent()
+                     << "  return result.Success;" << endl << indent() << "}" << endl;
+        }
+      }
+
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        if (nullable_) {
+          f_service_ << indent() << "if (result." << prop_name(*x_iter) << " != null) {" << endl
+                     << indent() << "  throw result." << prop_name(*x_iter) << ";" << endl
+                     << indent() << "}" << endl;
+        } else {
+          f_service_ << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name())
+                     << ") {" << endl << indent() << "  throw result." << prop_name(*x_iter) << ";"
+                     << endl << indent() << "}" << endl;
+        }
+      }
+
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return;" << endl;
+      } else {
+        f_service_ << indent()
+                   << "throw new "
+                      "TApplicationException(TApplicationException.ExceptionType.MissingResult, \""
+                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
+      }
+
+      cleanup_member_name_mapping((*f_iter)->get_xceptions());
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl;
+}
+
+void t_csharp_generator::generate_service_server(t_service* tservice) {
+  if (async_) {
+    generate_service_server_async(tservice);
+    generate_service_server_sync(tservice);
+  }
+  else {
+    generate_service_server_sync(tservice);
+  }
+}
+
+void t_csharp_generator::generate_service_server_sync(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = extends + ".Processor, ";
+  }
+
+  indent(f_service_) << "public class Processor : " << extends_processor << "TProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public Processor(ISync iface)";
+
+  if (!extends.empty()) {
+    f_service_ << " : base(iface)";
+  }
+  f_service_ << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name()
+      << "\"] = " << (*f_iter)->get_name() << "_Process;" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_
+      << indent()
+      << "protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);"
+      << endl;
+  }
+
+  f_service_ << indent() << "private ISync iface_;" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new "
+      "Dictionary<string, ProcessFunction>();" << endl;
+  }
+
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    indent(f_service_) << "public bool Process(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  else {
+    indent(f_service_) << "public new bool Process(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  scope_up(f_service_);
+
+  f_service_ << indent() << "try" << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl;
+
+  f_service_
+    << indent() << "ProcessFunction fn;" << endl << indent()
+    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {"
+    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent()
+    << "  iprot.ReadMessageEnd();" << endl << indent()
+    << "  TApplicationException x = new TApplicationException "
+    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + "
+    "msg.Name + \"'\");" << endl << indent()
+    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));"
+    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();"
+    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;"
+    << endl << indent() << "}" << endl << indent() << "fn(msg.SeqID, iprot, oprot);" << endl;
+
+  scope_down(f_service_);
+
+  f_service_ << indent() << "catch (IOException)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "return false;" << endl;
+  scope_down(f_service_);
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_service_server_async(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = extends + ".Processor, ";
+  }
+
+  indent(f_service_) << "public class AsyncProcessor : " << extends_processor << "TAsyncProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public AsyncProcessor(IAsync iface)";
+  if (!extends.empty()) {
+    f_service_ << " : base(iface)";
+  }
+  f_service_ << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name()
+      << "\"] = " << (*f_iter)->get_name() << "_ProcessAsync;" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_
+      << indent()
+      << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);"
+      << endl;
+  }
+
+  f_service_ << indent() << "private IAsync iface_;" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new "
+      "Dictionary<string, ProcessFunction>();" << endl;
+  }
+
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    indent(f_service_) << "public async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  else {
+    indent(f_service_) << "public new async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  scope_up(f_service_);
+
+  f_service_ << indent() << "try" << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl;
+
+  f_service_
+    << indent() << "ProcessFunction fn;" << endl << indent()
+    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {"
+    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent()
+    << "  iprot.ReadMessageEnd();" << endl << indent()
+    << "  TApplicationException x = new TApplicationException "
+    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + "
+    "msg.Name + \"'\");" << endl << indent()
+    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));"
+    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();"
+    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;"
+    << endl << indent() << "}" << endl << indent() << "await fn(msg.SeqID, iprot, oprot);" << endl;
+
+  scope_down(f_service_);
+
+  f_service_ << indent() << "catch (IOException)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "return false;" << endl;
+  scope_down(f_service_);
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function_async(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  t_struct result(program_, tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_csharp_struct_definition(f_service_, &result, false, true, true);
+}
+
+void t_csharp_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  indent(f_service_) << "public void " << tfunction->get_name()
+                     << "_Process(int seqid, TProtocol iprot, TProtocol oprot)" << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl
+             << indent() << "args.Read(iprot);" << endl
+             << indent() << "iprot.ReadMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
+  }
+
+  f_service_ << indent() << "try" << endl
+             << indent() << "{" << endl;
+  indent_up();
+
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try" << endl
+               << indent() << "{" << endl;
+    indent_up();
+  }
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result.Success = ";
+  }
+  f_service_ << "iface_." << normalize_name(tfunction->get_name()) << "(";
+  bool first = true;
+  prepare_member_name_mapping(arg_struct);
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << prop_name(*f_iter);
+    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) {
+      f_service_ << ".Value";
+    }
+  }
+  cleanup_member_name_mapping(arg_struct);
+  f_service_ << ");" << endl;
+
+  prepare_member_name_mapping(xs, xs->get_members(), resultname);
+  if (xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " "
+                 << (*x_iter)->get_name() << ")" << endl
+                 << indent() << "{" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name()
+                   << ";" << endl;
+        indent_down();
+      }
+      f_service_ << indent() << "}" << endl;
+    }
+  }
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.Reply, seqid)); " << endl;
+    f_service_ << indent() << "result.Write(oprot);" << endl;
+  }
+  indent_down();
+
+  cleanup_member_name_mapping(xs);
+
+  f_service_ << indent() << "}" << endl
+             << indent() << "catch (TTransportException)" << endl
+             << indent() << "{" << endl
+             << indent() << "  throw;" << endl
+             << indent() << "}" << endl
+             << indent() << "catch (Exception ex)" << endl
+             << indent() << "{" << endl
+             << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl
+             << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl;
+
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "}" << endl;
+  } else {
+    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent()
+               << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");"
+               << endl
+               << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.Exception, seqid));" << endl
+               << indent() << "  x.Write(oprot);" << endl
+               << indent() << "}" << endl;
+    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl
+               << indent() << "oprot.Transport.Flush();" << endl;
+  }
+
+  scope_down(f_service_);
+
+  f_service_ << endl;
+}
+
+void t_csharp_generator::generate_process_function_async(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  indent(f_service_) << "public async Task " << tfunction->get_name()
+    << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot)" << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl
+    << indent() << "args.Read(iprot);" << endl
+    << indent() << "iprot.ReadMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
+  }
+
+  f_service_ << indent() << "try" << endl
+    << indent() << "{" << endl;
+  indent_up();
+
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try" << endl
+      << indent() << "{" << endl;
+    indent_up();
+  }
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result.Success = ";
+  }
+  f_service_ << "await iface_." << normalize_name(tfunction->get_name()) << "Async(";
+  bool first = true;
+  prepare_member_name_mapping(arg_struct);
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    }
+    else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << prop_name(*f_iter);
+    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) {
+      f_service_ << ".Value";
+    }
+  }
+  cleanup_member_name_mapping(arg_struct);
+  f_service_ << ");" << endl;
+
+  prepare_member_name_mapping(xs, xs->get_members(), resultname);
+  if (xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " "
+        << (*x_iter)->get_name() << ")" << endl
+        << indent() << "{" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name()
+          << ";" << endl;
+        indent_down();
+      }
+      f_service_ << indent() << "}" << endl;
+    }
+  }
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+      << "\", TMessageType.Reply, seqid)); " << endl;
+    f_service_ << indent() << "result.Write(oprot);" << endl;
+  }
+  indent_down();
+
+  cleanup_member_name_mapping(xs);
+
+  f_service_ << indent() << "}" << endl
+    << indent() << "catch (TTransportException)" << endl
+    << indent() << "{" << endl
+    << indent() << "  throw;" << endl
+    << indent() << "}" << endl
+    << indent() << "catch (Exception ex)" << endl
+    << indent() << "{" << endl
+    << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl
+    << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl;
+
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "}" << endl;
+  }
+  else {
+    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent()
+      << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");"
+      << endl
+      << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+      << "\", TMessageType.Exception, seqid));" << endl
+      << indent() << "  x.Write(oprot);" << endl
+      << indent() << "}" << endl;
+    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl
+      << indent() << "oprot.Transport.Flush();" << endl;
+  }
+
+  scope_down(f_service_);
+
+  f_service_ << endl;
+}
+
+void t_csharp_generator::generate_csharp_union_reader(std::ofstream& out, t_struct* tunion) {
+  // Thanks to THRIFT-1768, we don't need to check for required fields in the union
+  const vector<t_field*>& fields = tunion->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "public static " << tunion->get_name() << " Read(TProtocol iprot)" << endl;
+  scope_up(out);
+
+  out << indent() << "iprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  indent(out) << tunion->get_name() << " retval;" << endl;
+  indent(out) << "iprot.ReadStructBegin();" << endl;
+  indent(out) << "TField field = iprot.ReadFieldBegin();" << endl;
+  // we cannot have the first field be a stop -- we must have a single field defined
+  indent(out) << "if (field.Type == TType.Stop)" << endl;
+  scope_up(out);
+  indent(out) << "iprot.ReadFieldEnd();" << endl;
+  indent(out) << "retval = new ___undefined();" << endl;
+  scope_down(out);
+  indent(out) << "else" << endl;
+  scope_up(out);
+  indent(out) << "switch (field.ID)" << endl;
+  scope_up(out);
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    indent(out) << type_name((*f_iter)->get_type()) << " temp;" << endl;
+    generate_deserialize_field(out, (*f_iter), "temp", true);
+    indent(out) << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl;
+
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
+        << endl << indent() << "  retval = new ___undefined();" << endl << indent() << "}" << endl
+        << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default: " << endl;
+  indent_up();
+  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl << indent()
+              << "retval = new ___undefined();" << endl;
+  indent(out) << "break;" << endl;
+  indent_down();
+
+  scope_down(out);
+
+  indent(out) << "i

<TRUNCATED>

[36/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_java_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
deleted file mode 100644
index 2db8cb8..0000000
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ /dev/null
@@ -1,5323 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <cassert>
-#include <ctime>
-
-#include <sstream>
-#include <string>
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <vector>
-#include <cctype>
-
-#include <sys/stat.h>
-#include <stdexcept>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::setfill;
-using std::setw;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * Java code generator.
- *
- */
-class t_java_generator : public t_oop_generator {
-public:
-  t_java_generator(t_program* program,
-                   const std::map<std::string, std::string>& parsed_options,
-                   const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    bean_style_ = false;
-    android_style_ = false;
-    private_members_ = false;
-    nocamel_style_ = false;
-    fullcamel_style_ = false;
-    android_legacy_ = false;
-    sorted_containers_ = false;
-    java5_ = false;
-    reuse_objects_ = false;
-    use_option_type_ = false;
-    undated_generated_annotations_  = false;
-    suppress_generated_annotations_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("beans") == 0) {
-        bean_style_ = true;
-      } else if( iter->first.compare("android") == 0) {
-        android_style_ = true;
-      } else if( iter->first.compare("private-members") == 0) {
-        private_members_ = true;
-      } else if( iter->first.compare("nocamel") == 0) {
-        nocamel_style_ = true;
-      } else if( iter->first.compare("fullcamel") == 0) {
-        fullcamel_style_ = true;
-      } else if( iter->first.compare("android_legacy") == 0) {
-        android_legacy_ = true;
-      } else if( iter->first.compare("sorted_containers") == 0) {
-        sorted_containers_ = true;
-      } else if( iter->first.compare("java5") == 0) {
-        java5_ = true;
-      } else if( iter->first.compare("reuse-objects") == 0) {
-        reuse_objects_ = true;
-      } else if( iter->first.compare("option_type") == 0) {
-        use_option_type_ = true;
-      } else if( iter->first.compare("generated_annotations") == 0) {
-        if( iter->second.compare("undated") == 0) {
-          undated_generated_annotations_  = true;
-        } else if(iter->second.compare("suppress") == 0) {
-          suppress_generated_annotations_ = true;
-        } else {
-          throw "unknown option java:" + iter->first + "=" + iter->second; 
-        }
-      } else {
-        throw "unknown option java:" + iter->first; 
-      }
-    }
-
-    if (java5_) {
-      android_legacy_ = true;
-    }
-
-    out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  void generate_consts(std::vector<t_const*> consts);
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_struct(t_struct* tstruct);
-  void generate_union(t_struct* tunion);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  void print_const_value(std::ofstream& out,
-                         std::string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool in_static,
-                         bool defval = false);
-  std::string render_const_value(std::ofstream& out, t_type* type, t_const_value* value);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_java_struct(t_struct* tstruct, bool is_exception);
-
-  void generate_java_struct_definition(std::ofstream& out,
-                                       t_struct* tstruct,
-                                       bool is_xception = false,
-                                       bool in_class = false,
-                                       bool is_result = false);
-  void generate_java_struct_parcelable(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_java_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_write_object(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_read_object(std::ofstream& out, t_struct* tstruct);
-  void generate_java_meta_data_map(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
-  std::string get_java_type_string(t_type* type);
-  void generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct);
-  void generate_reflection_setters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_reflection_getters(std::ostringstream& out,
-                                   t_type* type,
-                                   std::string field_name,
-                                   std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
-
-  void generate_function_helpers(t_function* tfunction);
-  std::string as_camel_case(std::string name, bool ucfirst = true);
-  std::string get_rpc_method_name(std::string name);
-  std::string get_cap_name(std::string name);
-  std::string generate_isset_check(t_field* field);
-  std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field, std::string prefix);
-  std::string isset_field_id(t_field* field);
-
-  void generate_service_interface(t_service* tservice);
-  void generate_service_async_interface(t_service* tservice);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_async_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_service_async_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-  void generate_process_async_function(t_service* tservice, t_function* tfunction);
-
-  void generate_java_union(t_struct* tstruct);
-  void generate_union_constructor(ofstream& out, t_struct* tstruct);
-  void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
-  void generate_union_is_set_methods(ofstream& out, t_struct* tstruct);
-  void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
-  void generate_check_type(ofstream& out, t_struct* tstruct);
-  void generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct);
-  void generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct);
-  void generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct);
-  void generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct);
-  void generate_get_field_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_field_name(ofstream& out, t_struct* tstruct);
-
-  void generate_union_comparisons(ofstream& out, t_struct* tstruct);
-  void generate_union_hashcode(ofstream& out, t_struct* tstruct);
-
-  void generate_scheme_map(ofstream& out, t_struct* tstruct);
-  void generate_standard_writer(ofstream& out, t_struct* tstruct, bool is_result);
-  void generate_standard_reader(ofstream& out, t_struct* tstruct);
-  void generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct, bool is_result);
-
-  void generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct);
-
-  void generate_java_scheme_lookup(ofstream& out);
-
-  void generate_javax_generated_annotation(ofstream& out);
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out,
-                                  t_field* tfield,
-                                  std::string prefix = "",
-                                  bool has_metadata = true);
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_deserialize_container(std::ofstream& out,
-                                      t_type* ttype,
-                                      std::string prefix = "",
-                                      bool has_metadata = true);
-
-  void generate_deserialize_set_element(std::ofstream& out,
-                                        t_set* tset,
-                                        std::string prefix = "",
-                                        std::string obj = "",
-                                        bool has_metadata = true);
-
-  void generate_deserialize_map_element(std::ofstream& out,
-                                        t_map* tmap,
-                                        std::string prefix = "",
-                                        std::string obj = "",
-                                        bool has_metadata = true);
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "",
-                                         std::string obj = "",
-                                         bool has_metadata = true);
-
-  void generate_serialize_field(std::ofstream& out,
-                                t_field* tfield,
-                                std::string prefix = "",
-                                bool has_metadata = true);
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out,
-                                    t_type* ttype,
-                                    std::string prefix = "",
-                                    bool has_metadata = true);
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string iter,
-                                      std::string map,
-                                      bool has_metadata = true);
-
-  void generate_serialize_set_element(std::ofstream& out,
-                                      t_set* tmap,
-                                      std::string iter,
-                                      bool has_metadata = true);
-
-  void generate_serialize_list_element(std::ofstream& out,
-                                       t_list* tlist,
-                                       std::string iter,
-                                       bool has_metadata = true);
-
-  void generate_deep_copy_container(std::ofstream& out,
-                                    std::string source_name_p1,
-                                    std::string source_name_p2,
-                                    std::string result_name,
-                                    t_type* type);
-  void generate_deep_copy_non_container(std::ofstream& out,
-                                        std::string source_name,
-                                        std::string dest_name,
-                                        t_type* type);
-
-  enum isset_type { ISSET_NONE, ISSET_PRIMITIVE, ISSET_BITSET };
-  isset_type needs_isset(t_struct* tstruct, std::string* outPrimitiveType = NULL);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string java_package();
-  std::string java_type_imports();
-  std::string java_suppressions();
-  std::string type_name(t_type* ttype,
-                        bool in_container = false,
-                        bool in_init = false,
-                        bool skip_generic = false,
-                        bool force_namespace = false);
-  std::string base_type_name(t_base_type* tbase, bool in_container = false);
-  std::string declare_field(t_field* tfield, bool init = false, bool comment = false);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string function_signature_async(t_function* tfunction,
-                                       bool use_base_method = false,
-                                       std::string prefix = "");
-  std::string argument_list(t_struct* tstruct, bool include_types = true);
-  std::string async_function_call_arglist(t_function* tfunc,
-                                          bool use_base_method = true,
-                                          bool include_types = true);
-  std::string async_argument_list(t_function* tfunct,
-                                  t_struct* tstruct,
-                                  t_type* ttype,
-                                  bool include_types = false);
-  std::string type_to_enum(t_type* ttype);
-  void generate_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_field_descs(ofstream& out, t_struct* tstruct);
-  void generate_field_name_constants(ofstream& out, t_struct* tstruct);
-
-  std::string make_valid_java_filename(std::string const& fromName);
-  std::string make_valid_java_identifier(std::string const& fromName);
-
-  bool type_can_be_null(t_type* ttype) {
-    ttype = get_true_type(ttype);
-
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()
-           || ttype->is_enum();
-  }
-
-  bool is_deprecated(const std::map<std::string, std::string>& annotations) {
-    return annotations.find("deprecated") != annotations.end();
-  }
-
-  std::string constant_name(std::string name);
-
-private:
-  /**
-   * File streams
-   */
-
-  std::string package_name_;
-  std::ofstream f_service_;
-  std::string package_dir_;
-
-  bool bean_style_;
-  bool android_style_;
-  bool private_members_;
-  bool nocamel_style_;
-  bool fullcamel_style_;
-  bool android_legacy_;
-  bool java5_;
-  bool sorted_containers_;
-  bool reuse_objects_;
-  bool use_option_type_;
-  bool undated_generated_annotations_;
-  bool suppress_generated_annotations_;
-  
-};
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_java_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  package_name_ = program_->get_namespace("java");
-
-  string dir = package_name_;
-  string subdir = get_out_dir();
-  string::size_type loc;
-  while ((loc = dir.find(".")) != string::npos) {
-    subdir = subdir + "/" + dir.substr(0, loc);
-    MKDIR(subdir.c_str());
-    dir = dir.substr(loc + 1);
-  }
-  if (dir.size() > 0) {
-    subdir = subdir + "/" + dir;
-    MKDIR(subdir.c_str());
-  }
-
-  package_dir_ = subdir;
-}
-
-/**
- * Packages the generated file
- *
- * @return String of the package, i.e. "package org.apache.thriftdemo;"
- */
-string t_java_generator::java_package() {
-  if (!package_name_.empty()) {
-    return string("package ") + package_name_ + ";\n\n";
-  }
-  return "";
-}
-
-/**
- * Prints standard java imports
- *
- * @return List of imports for Java types that are used in here
- */
-string t_java_generator::java_type_imports() {
-  string hash_builder;
-  string tree_set_and_map;
-  string annotation_generated;
-
-  string option;
-  if (sorted_containers_) {
-    tree_set_and_map = string() + "import java.util.TreeSet;\n" + "import java.util.TreeMap;\n";
-  }
-
-  if (use_option_type_) {
-    option = string() + "import org.apache.thrift.Option;\n";
-  }
-
-  // android does not support @Generated Annotation
-  if (!suppress_generated_annotations_) {
-    annotation_generated = string() + "import javax.annotation.Generated;\n";
-  }
-
-  return string() + hash_builder + "import org.apache.thrift.scheme.IScheme;\n"
-         + "import org.apache.thrift.scheme.SchemeFactory;\n"
-         + "import org.apache.thrift.scheme.StandardScheme;\n\n"
-         + "import org.apache.thrift.scheme.TupleScheme;\n"
-         + "import org.apache.thrift.protocol.TTupleProtocol;\n"
-         + "import org.apache.thrift.protocol.TProtocolException;\n"
-         + "import org.apache.thrift.EncodingUtils;\n"
-         + option
-         + "import org.apache.thrift.server.AbstractNonblockingServer.*;\n"
-         + "import java.util.List;\n" + "import java.util.ArrayList;\n" + "import java.util.Map;\n"
-         + "import java.util.HashMap;\n" + "import java.util.EnumMap;\n" + "import java.util.Set;\n"
-         + "import java.util.HashSet;\n" + "import java.util.EnumSet;\n" + tree_set_and_map
-         + "import java.util.Collections;\n" + "import java.util.BitSet;\n"
-         + "import java.nio.ByteBuffer;\n"
-         + "import java.util.Arrays;\n" + annotation_generated
-         + "import org.slf4j.Logger;\n" + "import org.slf4j.LoggerFactory;\n\n";
-}
-
-string t_java_generator::java_suppressions() {
-  return "@SuppressWarnings({\"cast\", \"rawtypes\", \"serial\", \"unchecked\", \"unused\"})\n";
-}
-
-/**
- * Nothing in Java
- */
-void t_java_generator::close_generator() {
-}
-
-/**
- * Generates a typedef. This is not done in Java, since it does
- * not support arbitrary name replacements, and it'd be a wacky waste
- * of overhead to make wrapper classes.
- *
- * @param ttypedef The type definition
- */
-void t_java_generator::generate_typedef(t_typedef* ttypedef) {
-  (void)ttypedef;
-}
-
-/**
- * Enums are a class with a set of static constants.
- *
- * @param tenum The enumeration
- */
-void t_java_generator::generate_enum(t_enum* tenum) {
-  bool is_deprecated = this->is_deprecated(tenum->annotations_);
-  // Make output file
-  string f_enum_name = package_dir_ + "/" + make_valid_java_filename(tenum->get_name()) + ".java";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
-
-  // Comment and package it
-  f_enum << autogen_comment() << java_package() << endl;
-
-  // Add java imports
-  f_enum << string() + "import java.util.Map;\n" + "import java.util.HashMap;\n"
-            + "import org.apache.thrift.TEnum;" << endl << endl;
-
-  generate_java_doc(f_enum, tenum);
-  if (is_deprecated) {
-    indent(f_enum) << "@Deprecated" << endl;
-  }
-  indent(f_enum) << "public enum " << tenum->get_name() << " implements org.apache.thrift.TEnum ";
-  scope_up(f_enum);
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  bool first = true;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-
-    if (first) {
-      first = false;
-    } else {
-      f_enum << "," << endl;
-    }
-
-    generate_java_doc(f_enum, *c_iter);
-    if (this->is_deprecated((*c_iter)->annotations_)) {
-      indent(f_enum) << "@Deprecated" << endl;
-    }
-    indent(f_enum) << (*c_iter)->get_name() << "(" << value << ")";
-  }
-  f_enum << ";" << endl << endl;
-
-  // Field for thriftCode
-  indent(f_enum) << "private final int value;" << endl << endl;
-
-  indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl;
-  indent(f_enum) << "  this.value = value;" << endl;
-  indent(f_enum) << "}" << endl << endl;
-
-  indent(f_enum) << "/**" << endl;
-  indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL."
-                 << endl;
-  indent(f_enum) << " */" << endl;
-  indent(f_enum) << "public int getValue() {" << endl;
-  indent(f_enum) << "  return value;" << endl;
-  indent(f_enum) << "}" << endl << endl;
-
-  indent(f_enum) << "/**" << endl;
-  indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL."
-                 << endl;
-  indent(f_enum) << " * @return null if the value is not found." << endl;
-  indent(f_enum) << " */" << endl;
-  indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl;
-
-  indent_up();
-
-  indent(f_enum) << "switch (value) {" << endl;
-  indent_up();
-
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    indent(f_enum) << "case " << value << ":" << endl;
-    indent(f_enum) << "  return " << (*c_iter)->get_name() << ";" << endl;
-  }
-
-  indent(f_enum) << "default:" << endl;
-  indent(f_enum) << "  return null;" << endl;
-
-  indent_down();
-
-  indent(f_enum) << "}" << endl;
-
-  indent_down();
-
-  indent(f_enum) << "}" << endl;
-
-  scope_down(f_enum);
-
-  f_enum.close();
-}
-
-/**
- * Generates a class that holds all the constants.
- */
-void t_java_generator::generate_consts(std::vector<t_const*> consts) {
-  if (consts.empty()) {
-    return;
-  }
-
-  string f_consts_name = package_dir_ + '/' + make_valid_java_filename(program_name_)
-                         + "Constants.java";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
-
-  // Print header
-  f_consts << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
-
-  f_consts << "public class " << make_valid_java_identifier(program_name_) << "Constants {" << endl
-           << endl;
-  indent_up();
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    generate_java_doc(f_consts, (*c_iter));
-    print_const_value(f_consts,
-                      (*c_iter)->get_name(),
-                      (*c_iter)->get_type(),
-                      (*c_iter)->get_value(),
-                      false);
-  }
-  indent_down();
-  indent(f_consts) << "}" << endl;
-  f_consts.close();
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-void t_java_generator::print_const_value(std::ofstream& out,
-                                         string name,
-                                         t_type* type,
-                                         t_const_value* value,
-                                         bool in_static,
-                                         bool defval) {
-  type = get_true_type(type);
-
-  indent(out);
-  if (!defval) {
-    out << (in_static ? "" : "public static final ") << type_name(type) << " ";
-  }
-  if (type->is_base_type()) {
-    string v2 = render_const_value(out, type, value);
-    out << name << " = " << v2 << ";" << endl << endl;
-  } else if (type->is_enum()) {
-    out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl;
-  } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    out << name << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "static {" << endl;
-      indent_up();
-    }
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string val = render_const_value(out, field_type, v_iter->second);
-      indent(out) << name << ".";
-      std::string cap_name = get_cap_name(v_iter->first->get_string());
-      out << "set" << cap_name << "(" << val << ");" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_map()) {
-    out << name << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "static {" << endl;
-      indent_up();
-    }
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, ktype, v_iter->first);
-      string val = render_const_value(out, vtype, v_iter->second);
-      indent(out) << name << ".put(" << key << ", " << val << ");" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else if (type->is_list() || type->is_set()) {
-    out << name << " = new " << type_name(type, false, true) << "();" << endl;
-    if (!in_static) {
-      indent(out) << "static {" << endl;
-      indent_up();
-    }
-    t_type* etype;
-    if (type->is_list()) {
-      etype = ((t_list*)type)->get_elem_type();
-    } else {
-      etype = ((t_set*)type)->get_elem_type();
-    }
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, etype, *v_iter);
-      indent(out) << name << ".add(" << val << ");" << endl;
-    }
-    if (!in_static) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-    out << endl;
-  } else {
-    throw "compiler error: no const of type " + type->get_name();
-  }
-}
-
-string t_java_generator::render_const_value(ofstream& out, t_type* type, t_const_value* value) {
-  type = get_true_type(type);
-  std::ostringstream render;
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() > 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-      render << "(byte)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I16:
-      render << "(short)" << value->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << value->get_integer() << "L";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << "(double)" << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    std::string namespace_prefix = type->get_program()->get_namespace("java");
-    if (namespace_prefix.length() > 0) {
-      namespace_prefix += ".";
-    }
-    render << namespace_prefix << value->get_identifier_with_parent();
-  } else {
-    string t = tmp("tmp");
-    print_const_value(out, t, type, value, true);
-    render << t;
-  }
-
-  return render.str();
-}
-
-/**
- * Generates a struct definition for a thrift data type. This will be a org.apache.thrift.TBase
- * implementor.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_struct(t_struct* tstruct) {
-  if (tstruct->is_union()) {
-    generate_java_union(tstruct);
-  } else {
-    generate_java_struct(tstruct, false);
-  }
-}
-
-/**
- * Exceptions are structs, but they inherit from Exception
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_xception(t_struct* txception) {
-  generate_java_struct(txception, true);
-}
-
-/**
- * Java struct definition.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_struct(t_struct* tstruct, bool is_exception) {
-  // Make output file
-  string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name())
-                         + ".java";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
-
-  generate_java_struct_definition(f_struct, tstruct, is_exception);
-  f_struct.close();
-}
-
-/**
- * Java union definition.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_union(t_struct* tstruct) {
-  // Make output file
-  string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name())
-                         + ".java";
-  ofstream f_struct;
-  f_struct.open(f_struct_name.c_str());
-
-  f_struct << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
-
-  generate_java_doc(f_struct, tstruct);
-
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-  bool is_deprecated = this->is_deprecated(tstruct->annotations_);
-
-  if (is_deprecated) {
-    indent(f_struct) << "@Deprecated" << endl;
-  }
-  indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
-                   << " extends org.apache.thrift.TUnion<" << tstruct->get_name() << ", "
-                   << tstruct->get_name() << "._Fields> ";
-
-  scope_up(f_struct);
-
-  generate_struct_desc(f_struct, tstruct);
-  generate_field_descs(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_field_name_constants(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_java_meta_data_map(f_struct, tstruct);
-
-  generate_union_constructor(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_abstract_methods(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_java_struct_field_by_id(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_getters_and_setters(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_is_set_methods(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_comparisons(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_union_hashcode(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_java_struct_write_object(f_struct, tstruct);
-
-  f_struct << endl;
-
-  generate_java_struct_read_object(f_struct, tstruct);
-
-  f_struct << endl;
-
-  scope_down(f_struct);
-
-  f_struct.close();
-}
-
-void t_java_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  indent(out) << "public " << type_name(tstruct) << "() {" << endl;
-  indent_up();
-  bool default_value = false;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* type = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL) {
-      indent(out) << "super(_Fields." << constant_name((*m_iter)->get_name()) << ", "
-                  << render_const_value(out, type, (*m_iter)->get_value()) << ");" << endl;
-      default_value = true;
-      break;
-    }
-  }
-  if (default_value == false) {
-    indent(out) << "super();" << endl;
-  }
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  indent(out) << "public " << type_name(tstruct) << "(_Fields setField, Object value) {" << endl;
-  indent(out) << "  super(setField, value);" << endl;
-  indent(out) << "}" << endl << endl;
-
-  indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {"
-              << endl;
-  indent(out) << "  super(other);" << endl;
-  indent(out) << "}" << endl;
-
-  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
-  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
-  indent(out) << "}" << endl << endl;
-
-  // generate "constructors" for each field
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* type = (*m_iter)->get_type();
-    indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "("
-                << type_name(type) << " value) {" << endl;
-    indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl;
-    indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl;
-    indent(out) << "  return x;" << endl;
-    indent(out) << "}" << endl << endl;
-
-    if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
-      indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name()
-                  << "(byte[] value) {" << endl;
-      indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();"
-                  << endl;
-      indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name())
-                  << "(ByteBuffer.wrap(Arrays.copyOf(value, value.length)));" << endl;
-      indent(out) << "  return x;" << endl;
-      indent(out) << "}" << endl << endl;
-    }
-  }
-}
-
-void t_java_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  bool first = true;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (first) {
-      first = false;
-    } else {
-      out << endl;
-    }
-
-    t_field* field = (*m_iter);
-    t_type* type = field->get_type();
-    std::string cap_name = get_cap_name(field->get_name());
-    bool is_deprecated = this->is_deprecated(field->annotations_);
-
-    generate_java_doc(out, field);
-    if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
-      if (is_deprecated) {
-        indent(out) << "@Deprecated" << endl;
-      }
-      indent(out) << "public byte[] get" << cap_name << "() {" << endl;
-      indent(out) << "  set" << cap_name << "(org.apache.thrift.TBaseHelper.rightSize(buffer"
-                  << get_cap_name("for") << cap_name << "()));" << endl;
-      indent(out) << "  ByteBuffer b = buffer" << get_cap_name("for") << cap_name << "();" << endl;
-      indent(out) << "  return b == null ? null : b.array();" << endl;
-      indent(out) << "}" << endl;
-
-      out << endl;
-
-      indent(out) << "public ByteBuffer buffer" << get_cap_name("for")
-                  << get_cap_name(field->get_name()) << "() {" << endl;
-      indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
-                  << endl;
-      indent(out)
-          << "    return org.apache.thrift.TBaseHelper.copyBinary((ByteBuffer)getFieldValue());"
-          << endl;
-      indent(out) << "  } else {" << endl;
-      indent(out) << "    throw new RuntimeException(\"Cannot get field '" << field->get_name()
-                  << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
-                  << endl;
-      indent(out) << "  }" << endl;
-      indent(out) << "}" << endl;
-    } else {
-      if (is_deprecated) {
-        indent(out) << "@Deprecated" << endl;
-      }
-      indent(out) << "public " << type_name(field->get_type()) << " get"
-                  << get_cap_name(field->get_name()) << "() {" << endl;
-      indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
-                  << endl;
-      indent(out) << "    return (" << type_name(field->get_type(), true) << ")getFieldValue();"
-                  << endl;
-      indent(out) << "  } else {" << endl;
-      indent(out) << "    throw new RuntimeException(\"Cannot get field '" << field->get_name()
-                  << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
-                  << endl;
-      indent(out) << "  }" << endl;
-      indent(out) << "}" << endl;
-    }
-
-    out << endl;
-
-    generate_java_doc(out, field);
-    if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
-      if (is_deprecated) {
-        indent(out) << "@Deprecated" << endl;
-      }
-      indent(out) << "public void set" << get_cap_name(field->get_name()) << "(byte[] value) {"
-                  << endl;
-      indent(out) << "  set" << get_cap_name(field->get_name())
-                  << "(ByteBuffer.wrap(Arrays.copyOf(value, value.length)));" << endl;
-      indent(out) << "}" << endl;
-
-      out << endl;
-    }
-    if (is_deprecated) {
-      indent(out) << "@Deprecated" << endl;
-    }
-    indent(out) << "public void set" << get_cap_name(field->get_name()) << "("
-                << type_name(field->get_type()) << " value) {" << endl;
-    if (type_can_be_null(field->get_type())) {
-      indent(out) << "  if (value == null) throw new NullPointerException();" << endl;
-    }
-    indent(out) << "  setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl;
-    indent(out) << "  value_ = value;" << endl;
-    indent(out) << "}" << endl;
-  }
-}
-
-void t_java_generator::generate_union_is_set_methods(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  bool first = true;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (first) {
-      first = false;
-    } else {
-      out << endl;
-    }
-
-    std::string field_name = (*m_iter)->get_name();
-
-    indent(out) << "public boolean is" << get_cap_name("set") << get_cap_name(field_name) << "() {"
-                << endl;
-    indent_up();
-    indent(out) << "return setField_ == _Fields." << constant_name(field_name) << ";" << endl;
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-}
-
-void t_java_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
-  generate_check_type(out, tstruct);
-  out << endl;
-  generate_standard_scheme_read_value(out, tstruct);
-  out << endl;
-  generate_standard_scheme_write_value(out, tstruct);
-  out << endl;
-  generate_tuple_scheme_read_value(out, tstruct);
-  out << endl;
-  generate_tuple_scheme_write_value(out, tstruct);
-  out << endl;
-  generate_get_field_desc(out, tstruct);
-  out << endl;
-  generate_get_struct_desc(out, tstruct);
-  out << endl;
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected _Fields enumForId(short id) {" << endl;
-  indent(out) << "  return _Fields.findByThriftIdOrThrow(id);" << endl;
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out)
-      << "protected void checkType(_Fields setField, Object value) throws ClassCastException {"
-      << endl;
-  indent_up();
-
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent(out) << "  if (value instanceof " << type_name(field->get_type(), true, false, true)
-                << ") {" << endl;
-    indent(out) << "    break;" << endl;
-    indent(out) << "  }" << endl;
-    indent(out) << "  throw new ClassCastException(\"Was expecting value of type "
-                << type_name(field->get_type(), true, false) << " for field '" << field->get_name()
-                << "', but got \" + value.getClass().getSimpleName());" << endl;
-    // do the real check here
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol "
-                 "iprot, org.apache.thrift.protocol.TField field) throws "
-                 "org.apache.thrift.TException {" << endl;
-
-  indent_up();
-
-  indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl;
-  indent(out) << "if (setField != null) {" << endl;
-  indent_up();
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {"
-                << endl;
-    indent_up();
-    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";"
-                << endl;
-    generate_deserialize_field(out, field, "");
-    indent(out) << "return " << field->get_name() << ";" << endl;
-    indent_down();
-    indent(out) << "} else {" << endl;
-    indent(out) << "  org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl;
-    indent(out) << "  return null;" << endl;
-    indent(out) << "}" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalStateException(\"setField wasn't null, but didn't match any "
-                 "of the case statements!\");" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "} else {" << endl;
-  indent_up();
-  indent(out) << "org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl;
-  indent(out) << "return null;" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected void standardSchemeWriteValue(org.apache.thrift.protocol.TProtocol "
-                 "oprot) throws org.apache.thrift.TException {" << endl;
-
-  indent_up();
-
-  indent(out) << "switch (setField_) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = ("
-                << type_name(field->get_type(), true, false) << ")value_;" << endl;
-    generate_serialize_field(out, field, "");
-    indent(out) << "return;" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + "
-                 "setField_);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected Object tupleSchemeReadValue(org.apache.thrift.protocol.TProtocol "
-                 "iprot, short fieldID) throws org.apache.thrift.TException {" << endl;
-
-  indent_up();
-
-  indent(out) << "_Fields setField = _Fields.findByThriftId(fieldID);" << endl;
-  indent(out) << "if (setField != null) {" << endl;
-  indent_up();
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";"
-                << endl;
-    generate_deserialize_field(out, field, "");
-    indent(out) << "return " << field->get_name() << ";" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalStateException(\"setField wasn't null, but didn't match any "
-                 "of the case statements!\");" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "} else {" << endl;
-  indent_up();
-  indent(out) << "throw new TProtocolException(\"Couldn't find a field with field id \" + fieldID);"
-              << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected void tupleSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) "
-                 "throws org.apache.thrift.TException {" << endl;
-
-  indent_up();
-
-  indent(out) << "switch (setField_) {" << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = ("
-                << type_name(field->get_type(), true, false) << ")value_;" << endl;
-    generate_serialize_field(out, field, "");
-    indent(out) << "return;" << endl;
-    indent_down();
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalStateException(\"Cannot write union with unknown field \" + "
-                 "setField_);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {"
-              << endl;
-  indent_up();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  indent(out) << "switch (setField) {" << endl;
-  indent_up();
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent(out) << "  return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl;
-  }
-
-  indent(out) << "default:" << endl;
-  indent(out) << "  throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "@Override" << endl;
-  indent(out) << "protected org.apache.thrift.protocol.TStruct getStructDesc() {" << endl;
-  indent(out) << "  return STRUCT_DESC;" << endl;
-  indent(out) << "}" << endl;
-}
-
-void t_java_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
-  // equality
-  indent(out) << "public boolean equals(Object other) {" << endl;
-  indent(out) << "  if (other instanceof " << tstruct->get_name() << ") {" << endl;
-  indent(out) << "    return equals((" << tstruct->get_name() << ")other);" << endl;
-  indent(out) << "  } else {" << endl;
-  indent(out) << "    return false;" << endl;
-  indent(out) << "  }" << endl;
-  indent(out) << "}" << endl;
-
-  out << endl;
-
-  indent(out) << "public boolean equals(" << tstruct->get_name() << " other) {" << endl;
-  indent(out) << "  return other != null && getSetField() == other.getSetField() && "
-                 "getFieldValue().equals(other.getFieldValue());" << endl;
-  indent(out) << "}" << endl;
-  out << endl;
-
-  indent(out) << "@Override" << endl;
-  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
-  indent(out) << "  int lastComparison = org.apache.thrift.TBaseHelper.compareTo(getSetField(), "
-                 "other.getSetField());" << endl;
-  indent(out) << "  if (lastComparison == 0) {" << endl;
-  indent(out) << "    return org.apache.thrift.TBaseHelper.compareTo(getFieldValue(), "
-                 "other.getFieldValue());" << endl;
-  indent(out) << "  }" << endl;
-  indent(out) << "  return lastComparison;" << endl;
-  indent(out) << "}" << endl;
-  out << endl;
-}
-
-void t_java_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "@Override" << endl;
-  indent(out) << "public int hashCode() {" << endl;
-  indent(out) << "  List<Object> list = new ArrayList<Object>();" << endl;
-  indent(out) << "  list.add(this.getClass().getName());" << endl;
-  indent(out) << "  org.apache.thrift.TFieldIdEnum setField = getSetField();" << endl;
-  indent(out) << "  if (setField != null) {" << endl;
-  indent(out) << "    list.add(setField.getThriftFieldId());" << endl;
-  indent(out) << "    Object value = getFieldValue();" << endl;
-  indent(out) << "    if (value instanceof org.apache.thrift.TEnum) {" << endl;
-  indent(out) << "      list.add(((org.apache.thrift.TEnum)getFieldValue()).getValue());" << endl;
-  indent(out) << "    } else {" << endl;
-  indent(out) << "      list.add(value);" << endl;
-  indent(out) << "    }" << endl;
-  indent(out) << "  }" << endl;
-  indent(out) << "  return list.hashCode();" << endl;
-  indent(out) << "}";
-}
-
-/**
- * Java struct definition. This has various parameters, as it could be
- * generated standalone or inside another class as a helper. If it
- * is a helper than it is a static class.
- *
- * @param tstruct      The struct definition
- * @param is_exception Is this an exception?
- * @param in_class     If inside a class, needs to be static class
- * @param is_result    If this is a result it needs a different writer
- */
-void t_java_generator::generate_java_struct_definition(ofstream& out,
-                                                       t_struct* tstruct,
-                                                       bool is_exception,
-                                                       bool in_class,
-                                                       bool is_result) {
-  generate_java_doc(out, tstruct);
-
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
-  bool is_deprecated = this->is_deprecated(tstruct->annotations_);
-
-  if (!in_class && !suppress_generated_annotations_) {
-    generate_javax_generated_annotation(out);
-  }
-
-  if (is_deprecated) {
-    indent(out) << "@Deprecated" << endl;
-  }
-  indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class "
-              << tstruct->get_name() << " ";
-
-  if (is_exception) {
-    out << "extends org.apache.thrift.TException ";
-  }
-  out << "implements org.apache.thrift.TBase<" << tstruct->get_name() << ", " << tstruct->get_name()
-      << "._Fields>, java.io.Serializable, Cloneable, Comparable<" << tstruct->get_name() << ">";
-
-  if (android_style_) {
-    out << ", android.os.Parcelable";
-  }
-
-  out << " ";
-
-  scope_up(out);
-
-  generate_struct_desc(out, tstruct);
-
-  // Members are public for -java, private for -javabean
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  out << endl;
-
-  generate_field_descs(out, tstruct);
-
-  out << endl;
-
-  generate_scheme_map(out, tstruct);
-
-  out << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (bean_style_ || private_members_) {
-      indent(out) << "private ";
-    } else {
-      generate_java_doc(out, *m_iter);
-      indent(out) << "public ";
-    }
-    out << declare_field(*m_iter, false, true) << endl;
-  }
-
-  out << endl;
-
-  if (android_style_) {
-    generate_java_struct_parcelable(out, tstruct);
-  }
-
-  generate_field_name_constants(out, tstruct);
-
-  // isset data
-  if (members.size() > 0) {
-    out << endl;
-
-    indent(out) << "// isset id assignments" << endl;
-
-    int i = 0;
-    int optionals = 0;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
-        optionals++;
-      }
-      if (!type_can_be_null((*m_iter)->get_type())) {
-        indent(out) << "private static final int " << isset_field_id(*m_iter) << " = " << i << ";"
-                    << endl;
-        i++;
-      }
-    }
-
-    std::string primitiveType;
-    switch (needs_isset(tstruct, &primitiveType)) {
-    case ISSET_NONE:
-      break;
-    case ISSET_PRIMITIVE:
-      indent(out) << "private " << primitiveType << " __isset_bitfield = 0;" << endl;
-      break;
-    case ISSET_BITSET:
-      indent(out) << "private BitSet __isset_bit_vector = new BitSet(" << i << ");" << endl;
-      break;
-    }
-
-    if (optionals > 0) {
-      std::string output_string = "private static final _Fields optionals[] = {";
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
-          output_string = output_string + "_Fields." + constant_name((*m_iter)->get_name()) + ",";
-        }
-      }
-      indent(out) << output_string.substr(0, output_string.length() - 1) << "};" << endl;
-    }
-  }
-
-  generate_java_meta_data_map(out, tstruct);
-
-  bool all_optional_members = true;
-
-  // Default constructor
-  indent(out) << "public " << tstruct->get_name() << "() {" << endl;
-  indent_up();
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    if ((*m_iter)->get_value() != NULL) {
-      print_const_value(out,
-                        "this." + (*m_iter)->get_name(),
-                        t,
-                        (*m_iter)->get_value(),
-                        true,
-                        true);
-    }
-    if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-      all_optional_members = false;
-    }
-  }
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  if (!members.empty() && !all_optional_members) {
-    // Full constructor for all fields
-    indent(out) << "public " << tstruct->get_name() << "(" << endl;
-    indent_up();
-    bool first = true;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-        if (!first) {
-          out << "," << endl;
-        }
-        first = false;
-        indent(out) << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
-      }
-    }
-    out << ")" << endl;
-    indent_down();
-    indent(out) << "{" << endl;
-    indent_up();
-    indent(out) << "this();" << endl;
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
-        t_type* type = get_true_type((*m_iter)->get_type());
-        if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
-          indent(out) << "this." << (*m_iter)->get_name()
-                      << " = org.apache.thrift.TBaseHelper.copyBinary(" << (*m_iter)->get_name()
-                      << ");" << endl;
-        } else {
-          indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";"
-                      << endl;
-        }
-        generate_isset_set(out, (*m_iter), "");
-      }
-    }
-
-    indent_down();
-    indent(out) << "}" << endl << endl;
-  }
-
-  // copy constructor
-  indent(out) << "/**" << endl;
-  indent(out) << " * Performs a deep copy on <i>other</i>." << endl;
-  indent(out) << " */" << endl;
-  indent(out) << "public " << tstruct->get_name() << "(" << tstruct->get_name() << " other) {"
-              << endl;
-  indent_up();
-
-  switch (needs_isset(tstruct)) {
-  case ISSET_NONE:
-    break;
-  case ISSET_PRIMITIVE:
-    indent(out) << "__isset_bitfield = other.__isset_bitfield;" << endl;
-    break;
-  case ISSET_BITSET:
-    indent(out) << "__isset_bit_vector.clear();" << endl;
-    indent(out) << "__isset_bit_vector.or(other.__isset_bit_vector);" << endl;
-    break;
-  }
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = (*m_iter);
-    std::string field_name = field->get_name();
-    t_type* type = field->get_type()->get_true_type();
-    bool can_be_null = type_can_be_null(type);
-
-    if (can_be_null) {
-      indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl;
-      indent_up();
-    }
-
-    if (type->is_container()) {
-      generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type);
-      indent(out) << "this." << field_name << " = __this__" << field_name << ";" << endl;
-    } else {
-      indent(out) << "this." << field_name << " = ";
-      generate_deep_copy_non_container(out, "other." + field_name, field_name, type);
-      out << ";" << endl;
-    }
-
-    if (can_be_null) {
-      indent_down();
-      indent(out) << "}" << endl;
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-
-  // clone method, so that you can deep copy an object when you don't know its class.
-  indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
-  indent(out) << "  return new " << tstruct->get_name() << "(this);" << endl;
-  indent(out) << "}" << endl << endl;
-
-  generate_java_struct_clear(out, tstruct);
-
-  generate_java_bean_boilerplate(out, tstruct);
-  generate_generic_field_getters_setters(out, tstruct);
-  generate_generic_isset_method(out, tstruct);
-
-  generate_java_struct_equality(out, tstruct);
-  generate_java_struct_compare_to(out, tstruct);
-  generate_java_struct_field_by_id(out, tstruct);
-
-  generate_java_struct_reader(out, tstruct);
-  if (is_result) {
-    generate_java_struct_result_writer(out, tstruct);
-  } else {
-    generate_java_struct_writer(out, tstruct);
-  }
-  generate_java_struct_tostring(out, tstruct);
-  generate_java_validator(out, tstruct);
-
-  generate_java_struct_write_object(out, tstruct);
-  generate_java_struct_read_object(out, tstruct);
-
-  generate_java_struct_standard_scheme(out, tstruct, is_result);
-  generate_java_struct_tuple_scheme(out, tstruct);
-  generate_java_scheme_lookup(out);
-
-  scope_down(out);
-  out << endl;
-}
-
-/**
- * generates parcelable interface implementation
- */
-void t_java_generator::generate_java_struct_parcelable(ofstream& out, t_struct* tstruct) {
-  string tname = tstruct->get_name();
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-
-  out << indent() << "@Override" << endl << indent()
-      << "public void writeToParcel(android.os.Parcel out, int flags) {" << endl;
-  indent_up();
-  string bitsetPrimitiveType = "";
-  switch (needs_isset(tstruct, &bitsetPrimitiveType)) {
-  case ISSET_NONE:
-    break;
-  case ISSET_PRIMITIVE:
-    indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl;
-    if (bitsetPrimitiveType == "byte") {
-      indent(out) << "out.writeByte(__isset_bitfield);" << endl;
-    } else if (bitsetPrimitiveType == "short") {
-      indent(out) << "out.writeInt(new Short(__isset_bitfield).intValue());" << endl;
-    } else if (bitsetPrimitiveType == "int") {
-      indent(out) << "out.writeInt(__isset_bitfield);" << endl;
-    } else if (bitsetPrimitiveType == "long") {
-      indent(out) << "out.writeLong(__isset_bitfield);" << endl;
-    }
-    out << endl;
-    break;
-  case ISSET_BITSET:
-    indent(out) << "//BitSet" << endl;
-    indent(out) << "out.writeSerializable(__isset_bit_vector);" << endl;
-    out << endl;
-    break;
-  }
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    string name = (*m_iter)->get_name();
-
-    if (t->is_struct()) {
-      indent(out) << "out.writeParcelable(" << name << ", flags);" << endl;
-    } else if (type_name(t) == "float") {
-      indent(out) << "out.writeFloat(" << name << ");" << endl;
-    } else if (t->is_enum()) {
-      indent(out) << "out.writeInt(" << name << " != null ? " << name << ".getValue() : -1);" << endl;
-    } else if (t->is_list()) {
-      if (((t_list*)t)->get_elem_type()->get_true_type()->is_struct()) {
-        indent(out) << "out.writeTypedList(" << name << ");" << endl;
-      } else {
-        indent(out) << "out.writeList(" << name << ");" << endl;
-      }
-    } else if (t->is_map()) {
-      indent(out) << "out.writeMap(" << name << ");" << endl;
-    } else if (t->is_base_type()) {
-      if (((t_base_type*)t)->is_binary()) {
-        indent(out) << "out.writeInt(" << name << "!=null ? 1 : 0);" << endl;
-        indent(out) << "if(" << name << " != null) { " << endl;
-        indent_up();
-        indent(out) << "out.writeByteArray(" << name << ".array(), " << name << ".position() + "
-                    << name << ".arrayOffset(), " << name << ".limit() - " << name
-                    << ".position() );" << endl;
-        scope_down(out);
-      } else {
-        switch (((t_base_type*)t)->get_base()) {
-        case t_base_type::TYPE_I16:
-          indent(out) << "out.writeInt(new Short(" << name << ").intValue());" << endl;
-          break;
-        case t_base_type::TYPE_I32:
-          indent(out) << "out.writeInt(" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_I64:
-          indent(out) << "out.writeLong(" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_BOOL:
-          indent(out) << "out.writeInt(" << name << " ? 1 : 0);" << endl;
-          break;
-        case t_base_type::TYPE_I8:
-          indent(out) << "out.writeByte(" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_DOUBLE:
-          indent(out) << "out.writeDouble(" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_STRING:
-          indent(out) << "out.writeString(" << name << ");" << endl;
-          break;
-        case t_base_type::TYPE_VOID:
-          break;
-        }
-      }
-    }
-  }
-  scope_down(out);
-  out << endl;
-
-  out << indent() << "@Override" << endl << indent() << "public int describeContents() {" << endl;
-  indent_up();
-  out << indent() << "return 0;" << endl;
-  scope_down(out);
-  out << endl;
-
-  indent(out) << "public " << tname << "(android.os.Parcel in) {" << endl;
-  indent_up();
-  // read in the required bitfield
-  switch (needs_isset(tstruct, &bitsetPrimitiveType)) {
-  case ISSET_NONE:
-    break;
-  case ISSET_PRIMITIVE:
-    indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl;
-    if (bitsetPrimitiveType == "byte") {
-      indent(out) << "__isset_bitfield = in.readByte();" << endl;
-    } else if (bitsetPrimitiveType == "short") {
-      indent(out) << "__isset_bitfield = (short) in.readInt();" << endl;
-    } else if (bitsetPrimitiveType == "int") {
-      indent(out) << "__isset_bitfield = in.readInt();" << endl;
-    } else if (bitsetPrimitiveType == "long") {
-      indent(out) << "__isset_bitfield = in.readLong();" << endl;
-    }
-    out << endl;
-    break;
-  case ISSET_BITSET:
-    indent(out) << "//BitSet" << endl;
-    indent(out) << "__isset_bit_vector = (BitSet) in.readSerializable();" << endl;
-    out << endl;
-    break;
-  }
-  // read all the fields
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
-    string name = (*m_iter)->get_name();
-    string prefix = "this." + name;
-
-    if (t->is_struct()) {
-      indent(out) << prefix << "= in.readParcelable(" << tname << ".class.getClassLoader());"
-                  << endl;
-    } else if (t->is_enum()) {
-      indent(out) << prefix << " = " << type_name(t) << ".findByValue(in.readInt());" << endl;
-    } else if (t->is_list()) {
-      t_list* list = (t_list*)t;
-      indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl;
-      if (list->get_elem_type()->get_true_type()->is_struct()) {
-        indent(out) << "in.readTypedList(" << prefix << ", " << type_name(list->get_elem_type())
-                    << ".CREATOR);" << endl;
-      } else {
-        indent(out) << "in.readList(" << prefix << ", " << tname << ".class.getClassLoader());"
-                    << endl;
-      }
-    } else if (t->is_map()) {
-      indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl;
-      indent(out) << " in.readMap(" << prefix << ", " << tname << ".class.getClassLoader());"
-                  << endl;
-    } else if (type_name(t) == "float") {
-      indent(out) << prefix << " = in.readFloat();" << endl;
-    } else if (t->is_base_type()) {
-      t_base_type* bt = (t_base_type*)t;
-      if (bt->is_binary()) {
-        indent(out) << "if(in.readInt()==1) {" << endl;
-        indent_up();
-        indent(out) << prefix << " = ByteBuffer.wrap(in.createByteArray());" << endl;
-        scope_down(out);
-      } else {
-        switch (bt->get_base()) {
-        case t_base_type::TYPE_I16:
-          indent(out) << prefix << " = (short) in.readInt();" << endl;
-          break;
-        case t_base_type::TYPE_I32:
-          indent(out) << prefix << " = in.readInt();" << endl;
-          break;
-        case t_base_type::TYPE_I64:
-          indent(out) << prefix << " = in.readLong();" << endl;
-          break;
-        case t_base_type::TYPE_BOOL:
-          indent(out) << prefix << " = (in.readInt()==1);" << endl;
-          break;
-        case t_base_type::TYPE_I8:
-          indent(out) << prefix << " = in.readByte();" << endl;
-          break;
-        case t_base_type::TYPE_DOUBLE:
-          indent(out) << prefix << " = in.readDouble();" << endl;
-          break;
-        case t_base_type::TYPE_STRING:
-          indent(out) << prefix << "= in.readString();" << endl;
-          break;
-        case t_base_type::TYPE_VOID:
-          break;
-        }
-      }
-    }
-  }
-
-  scope_down(out);
-  out << endl;
-
-  indent(out) << "public static final android.os.Parcelable.Creator<" << tname
-              << "> CREATOR = new android.os.Parcelable.Creator<" << tname << ">() {" << endl;
-  indent_up();
-
-  indent(out) << "@Override" << endl << indent() << "public " << tname << "[] newArray(int size) {"
-              << endl;
-  indent_up();
-  indent(out) << "return new " << tname << "[size];" << endl;
-  scope_down(out);
-  out << endl;
-
-  indent(out) << "@Override" << endl << indent() << "public " << tname
-              << " createFromParcel(android.os.Parcel in) {" << endl;
-  indent_up();
-  indent(out) << "return new " << tname << "(in);" << endl;
-  scope_down(out);
-
-  indent_down();
-  indent(out) << "};" << endl;
-  out << endl;
-}
-
-/**
- * Generates equals methods and a hashCode method for a structure.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_struct_equality(ofstream& out, t_struct* tstruct) {
-  out << indent() << "@Override" << endl << indent() << "public boolean equals(Object that) {"
-      << endl;
-  indent_up();
-  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl
-      << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent()
-      << "  return this.equals((" << tstruct->get_name() << ")that);" << endl << indent()
-      << "return false;" << endl;
-  scope_down(out);
-  out << endl;
-
-  out << indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl;
-  indent_up();
-  out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    out << endl;
-
-    t_type* t = get_true_type((*m_iter)->get_type());
-    // Most existing Thrift code does not use isset or optional/required,
-    // so we treat "default" fields as required.
-    bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
-    bool can_be_null = type_can_be_null(t);
-    string name = (*m_iter)->get_name();
-
-    string this_present = "true";
-    string that_present = "true";
-    string unequal;
-
-    if (is_optional || can_be_null) {
-      this_present += " && this." + generate_isset_check(*m_iter);
-      that_present += " && that." + generate_isset_check(*m_iter);
-    }
-
-    out << indent() << "boolean this_present_" << name << " = " << this_present << ";" << endl
-        << indent() << "boolean that_present_" << name << " = " << that_present << ";" << endl
-        << indent() << "if ("
-        << "this_present_" << name << " || that_present_" << name << ") {" << endl;
-    indent_up();
-    out << indent() << "if (!("
-        << "this_present_" << name << " && that_present_" << name << "))" << endl << indent()
-        << "  return false;" << endl;
-
-    if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
-      unequal = "!this." + name + ".equals(that." + name + ")";
-    } else if (can_be_null) {
-      unequal = "!this." + name + ".equals(that." + name + ")";
-    } else {
-      unequal = "this." + name + " != that." + name;
-    }
-
-    out << indent() << "if (" << unequal << ")" << endl << indent() << "  return false;" << endl;
-
-    scope_down(out);
-  }
-  out << endl;
-  indent(out) << "return true;" << endl;
-  scope_down(out);
-  out << endl;
-
-  const int MUL = 8191; // HashCode multiplier
-  const int B_YES = 131071;
-  const int B_NO = 524287;
-  out << indent() << "@Override" << endl << indent() << "public int hashCode() {" << endl;
-  indent_up();
-  indent(out) << "int hashCode = 1;" << endl;
-
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    out << endl;
-
-    t_type* t = get_true_type((*m_iter)->get_type());
-    bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
-    bool can_be_null = type_can_be_null(t);
-    string name = (*m_iter)->get_name();
-
-    if (is_optional || can_be_null) {
-      indent(out) << "hashCode = hashCode * " << MUL << " + ((" << generate_isset_check(*m_iter)
-                  << ") ? " << B_YES << " : " << B_NO << ");" << endl;
-    }
-
-    if (is_optional || can_be_null) {
-      indent(out) << "if (" + generate_isset_check(*m_iter) + ")" << endl;
-      indent_up();
-    }
-
-    if (t->is_enum()) {
-      indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".getValue();" << endl;
-    } else if (t->is_base_type()) {
-      switch(((t_base_type*)t)->get_base()) {
-      case t_base_type::TYPE_STRING:
-        indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".hashCode();" << endl;
-        break;
-      case t_base_type::TYPE_BOOL:
-        indent(out) << "hashCode = hashCode * " << MUL << " + ((" << name << ") ? "
-                    << B_YES << " : " << B_NO << ");" << endl;
-        break;
-      case t_base_type::TYPE_I8:
-        indent(out) << "hashCode = hashCode * " << MUL << " + (int) (" << name << ");" << endl;
-        break;
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-        indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ";" << endl;
-        break;
-      case t_base_type::TYPE_I64:
-      case t_base_type::TYPE_DOUBLE:
-        indent(out) << "hashCode = hashCode * " << MUL << " + org.apache.thrift.TBaseHelper.hashCode(" << name << ");" << endl;
-        break;
-      case t_base_type::TYPE_VOID:
-        throw std::logic_error("compiler error: a struct field cannot be void");
-      default:
-        throw std::logic_error("compiler error: the following base type has no hashcode generator: " +
-               t_base_type::t_base_name(((t_base_type*)t)->get_base()));
-      }
-    } else {
-      indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".hashCode();" << endl;
-    }
-
-    if (is_optional || can_be_null) {
-      indent_down();
-    }
-  }
-
-  out << endl;
-  indent(out) << "return hashCode;" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-void t_java_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
-  indent(out) << "@Override" << endl;
-  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
-  indent_up();
-
-  indent(out) << "if (!getClass().equals(other.getClass())) {" << endl;
-  indent(out) << "  return getClass().getName().compareTo(other.getClass().getName());" << endl;
-  indent(out) << "}" << endl;
-  out << endl;
-
-  indent(out) << "int lastComparison = 0;" << endl;
-  out << endl;
-
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_field* field = *m_iter;
-    indent(out) << "lastComparison = Boolean.valueOf(" << generate_isset_check(field)
-                << ").compareTo(other." << generate_isset_check(field) << ");" << endl;
-    indent(out) << "if (lastComparison != 0) {" << endl;
-    indent(out) << "  return lastComparison;" << endl;
-    indent(out) << "}" << endl;
-
-    indent(out) << "if (" << generate_isset_check(field) << ") {" << endl;
-    indent(out) << "  lastComparison = org.apache.thrift.TBaseHelper.compareTo(this."
-                << field->get_name() << ", other." << field->get_name() << ");" << endl;
-    indent(out) << "  if (lastComparison != 0) {" << endl;
-    indent(out) << "    return lastComparison;" << endl;
-    indent(out) << "  }" << endl;
-    indent(out) << "}" << endl;
-  }
-
-  indent(out) << "return 0;" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to read all the fields of the struct.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_struct_reader(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws "
-                 "org.apache.thrift.TException {" << endl;
-  indent_up();
-  indent(out) << "scheme(iprot).read(iprot, this);" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-// generates java method to perform various checks
-// (e.g. check that all required fields are set)
-void t_java_generator::generate_java_validator(ofstream& out, t_struct* tstruct) {
-  indent(out) << "public void validate() throws org.apache.thrift.TException {" << endl;
-  indent_up();
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  out << indent() << "// check for required fields" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      if (bean_style_) {
-        out << indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl << indent()
-            << "  throw new org.apache.thrift.protocol.TProtocolException(\"Required field '"
-            << (*f_iter)->get_name() << "' is unset! Struct:\" + toString());" << endl << indent()
-            << "}" << endl << endl;
-      } else {
-        if (type_can_be_null((*f_iter)->get_type())) {
-          indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
-          indent(out)
-              << "  throw new org.apache.thrift.protocol.TProtocolException(\"Required field '"
-              << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl;
-          indent(out) << "}" << endl;
-        } else {
-          indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
-                      << "' because it's a primitive and you chose the non-beans generator."
-                      << endl;
-        }
-      }
-    }
-  }
-
-  out << indent() << "// check for sub-struct validity" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_type* type = (*f_iter)->get_type();
-    if (type->is_struct() && !((t_struct*)type)->is_union()) {
-      out << indent() << "if (" << (*f_iter)->get_name() << " != null) {" << endl;
-      out << indent() << "  " << (*f_iter)->get_name() << ".validate();" << endl;
-      out << indent() << "}" << endl;
-    }
-  }
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_struct_writer(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws "
-                 "org.apache.thrift.TException {" << endl;
-  indent_up();
-  indent(out) << "scheme(oprot).write(oprot, this);" << endl;
-
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a function to write all the fields of the struct,
- * which is a function result. These fields are only written
- * if they are set in the Isset array, and only one of them
- * can be set at a time.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_struct_result_writer(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws "
-                 "org.apache.thrift.TException {" << endl;
-  indent_up();
-  indent(out) << "scheme(oprot).write(oprot, this);" << endl;
-
-  indent_down();
-  indent(out) << "  }" << endl << endl;
-}
-
-void t_java_generator::generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct) {
-  (void)tstruct;
-  indent(out) << "public _Fields fieldForId(int fieldId) {" << endl;
-  indent(out) << "  return _Fields.findByThriftId(fieldId);" << endl;
-  indent(out) << "}" << endl << endl;
-}
-
-void t_java_generator::generate_reflection_getters(ostringstream& out,
-                                                   t_type* type,
-                                                   string field_name,
-                                                   string cap_name) {
-  indent(out) << "case " << constant_name(field_name) << ":" << endl;
-  indent_up();
-  indent(out) << "return " << (type->is_bool() ? "is" : "get") << cap_name << "();" << endl << endl;
-  indent_down();
-}
-
-void t_java_generator::generate_reflection_setters(ostringstream& out,
-                                                   t_type* type,
-                                                   string field_name,
-                                                   string cap_name) {
-  const bool is_binary = type->is_base_type() && ((t_base_type*)type)->is_binary();
-  indent(out) << "case " << constant_name(field_name) << ":" << endl;
-  indent_up();
-  indent(out) << "if (value == null) {" << endl;
-  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
-  indent(out) << "} else {" << endl;
-  if (is_binary) {
-    indent_up();
-    indent(out) << "if (value instanceof byte[]) {" << endl;
-    indent(out) << "  set" << cap_name << "((byte[])value);" << endl;
-    indent(out) << "} else {" << endl;
-  }
-  indent(out) << "  set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl;
-  if (is_binary) {
-    indent(out) << "}" << endl;
-    indent_down();
-  }
-  indent(out) << "}" << endl;
-  indent(out) << "break;" << endl << endl;
-
-  indent_down();
-}
-
-void t_java_generator::generate_generic_field_getters_setters(std::ofstream& out,
-                                                              t_struct* tstruct) {
-  std::ostringstream getter_stream;
-  std::ostringstream setter_stream;
-
-  // build up the bodies of both the getter and setter at once
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-
-    indent_up();
-    generate_reflection_setters(setter_stream, type, field_name, cap_name);
-    generate_reflection_getters(getter_stream, type, field_name, cap_name);
-    indent_down();
-  }
-
-  // create the setter
-
-  indent(out) << "public void setFieldValue(_Fields field, Object value) {" << endl;
-  indent(out) << "  switch (field) {" << endl;
-  out << setter_stream.str();
-  indent(out) << "  }" << endl;
-  indent(out) << "}" << endl << endl;
-
-  // create the getter
-  indent(out) << "public Object getFieldValue(_Fields field) {" << endl;
-  indent_up();
-  indent(out) << "switch (field) {" << endl;
-  out << getter_stream.str();
-  indent(out) << "}" << endl;
-  indent(out) << "throw new IllegalStateException();" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-// Creates a generic isSet method that takes the field number as argument
-void t_java_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  // create the isSet method
-  indent(out) << "/** Returns true if field corresponding to fieldID is set (has been assigned a "
-                 "value) and false otherwise */" << endl;
-  indent(out) << "public boolean isSet(_Fields field) {" << endl;
-  indent_up();
-  indent(out) << "if (field == null) {" << endl;
-  indent(out) << "  throw new IllegalArgumentException();" << endl;
-  indent(out) << "}" << endl << endl;
-
-  indent(out) << "switch (field) {" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
-    indent_up();
-    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
-    indent_down();
-  }
-
-  indent(out) << "}" << endl;
-  indent(out) << "throw new IllegalStateException();" << endl;
-  indent_down();
-  indent(out) << "}" << endl << endl;
-}
-
-/**
- * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
- * for the given struct.
- *
- * @param tstruct The struct definition
- */
-void t_java_generator::generate_java_bean_boilerplate(ofstream& out, t_struct* tstruct) {
-  isset_type issetType = needs_isset(tstruct);
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* field = *f_iter;
-    t_type* type = get_true_type(field->get_type());
-    std::string field_name = field->get_name();
-    std::string cap_name = get_cap_name(field_name);
-    bool optional = use_option_type_ && field->get_req() == t_field::T_OPTIONAL;
-    bool is_deprecated = this->is_deprecated(field->annotations_);
-
-    if (type->is_container()) {
-      // Method to return the size of the collection
-      if (optional) {
-        if (is_deprecated) {
-          indent(out) << "@Deprecated" << endl;
-        }
-        indent(out) << "public Option<Integer> get" << cap_name;
-        out << get_cap_name("size() {") << endl;
-
-        indent_up();
-        indent(out) << "if (this." << field_name << " == null) {" << endl;
-        indent_up();
-        indent(out) << "return Option.none();" << endl;
-        indent_down();
-        indent(out) << "} else {" << endl;
-        indent_up();
-        indent(out) << "return Option.some(this." << field_name << ".size());" << endl;
-        indent_down();
-        indent(out) << "}" << endl;
-        indent_down();
-        indent(out) << "}" << endl << endl;
-      } else {
-        if (is_deprecated) {
-          indent(out) << "@Deprecated" << endl;
-        }
-        indent(out) << "public int get" << cap_name;
-        out << get_cap_name("size() {") << endl;
-
-        indent_up();
-        indent(out) << "return (this." << field_name << " == null) ? 0 : "
-                    << "this." << field_name << ".size();" << endl;
-        indent_down();
-        indent(out) << "}" << endl << endl;
-      }
-    }
-
-    if (type->is_set() || type->is_list()) {
-      t_type* element_type;
-      if (type->is_set()) {
-        element_type = ((t_set*)type)->get_elem_type();
-      } else {
-        element_type = ((t_list*)type)->get_elem_type();
-      }
-
-      // Iterator getter for sets and lists
-      if (optional) {
-        if (is_deprecated) {
-          indent(out) << "@Deprecated" << endl;
-        }
-        indent(out) << "public Option<java.util.Iterator<" << type_name(element_type, true, false)
-                    << ">> get" << cap_name;
-        out << get_cap_name("iterator() {") << endl;
-
-        indent_up();
-        indent(out) << "if (this." << field_name << " == null) {" << endl;
-        indent_up();
-        indent(out) << "return Option.none();" << endl;
-        indent_down();
-        indent(out) << "} else {" << endl;
-        indent_up();
-        indent(out) << "return Option.some(this." << field_name << ".iterator());" << endl;
-        indent_down();
-        indent(out) << "}" << endl;
-        indent_down();
-        indent(out) << "}" << endl << endl;
-      } else {
-        if (is_deprecated) {
-          indent(out) << "@Deprecated" << endl;
-        }
-        indent(out) << "public java.util.Iterator<" << type_name(element_type, true, false)
-                    << "> get" << cap_name;
-        out << get_cap_name("iterator() {") << endl;
-
-        indent_up();
-        indent(out) << "return (this." << field_name << " == null) ? null : "
-                    << "this." << field_name << ".iterator();" << endl;
-        indent_down();
-        indent(out) << "}" << endl << endl;
-      }
-
-      // Add to set or list, create if the set/list is null
-      if (is_deprecated) {
-        indent(out) << "@Deprecated" << endl;
-      }
-      indent(out) << "public void add" << get_cap_name("to");
-      out << cap_name << "(" << type_name(element_type) << " elem) {" << endl;
-
-      indent_up();
-      indent(out) << "if (this." << field_name << " == null) {" << endl;
-      indent_up();
-      indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();"
-                  << endl;
-      indent_down();
-      indent(out) << "}" << endl;
-      indent(out) << "this." << field_name << ".add(elem);" << endl;

<TRUNCATED>

[37/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_html_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_html_generator.cc b/compiler/cpp/src/generate/t_html_generator.cc
deleted file mode 100644
index 9594d39..0000000
--- a/compiler/cpp/src/generate/t_html_generator.cc
+++ /dev/null
@@ -1,1088 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <map>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sstream>
-#include "t_generator.h"
-#include "t_html_generator.h"
-#include "platform.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::pair;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-enum input_type { INPUT_UNKNOWN, INPUT_UTF8, INPUT_PLAIN };
-
-/**
- * HTML code generator
- *
- * mostly copy/pasting/tweaking from mcslee's work.
- */
-class t_html_generator : public t_generator {
-public:
-  t_html_generator(t_program* program,
-                   const std::map<std::string, std::string>& parsed_options,
-                   const std::string& option_string)
-    : t_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    standalone_ = false;
-    unsafe_ = false;
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      if( iter->first.compare("standalone") == 0) {
-        standalone_ = true;
-      } else if( iter->first.compare("noescape") == 0) {
-        unsafe_ = true;
-      } else {
-        throw "unknown option html:" + iter->first; 
-      }
-    }
-
-
-    out_dir_base_ = "gen-html";
-    input_type_ = INPUT_UNKNOWN;
-
-    escape_.clear();
-    escape_['&'] = "&amp;";
-    escape_['<'] = "&lt;";
-    escape_['>'] = "&gt;";
-    escape_['"'] = "&quot;";
-    escape_['\''] = "&apos;";
-
-    init_allowed__markup();
-  }
-
-  void generate_program();
-  void generate_program_toc();
-  void generate_program_toc_row(t_program* tprog);
-  void generate_program_toc_rows(t_program* tprog, std::vector<t_program*>& finished);
-  void generate_index();
-  std::string escape_html(std::string const& str);
-  std::string escape_html_tags(std::string const& str);
-  void generate_css();
-  void generate_css_content(std::ofstream& f_target);
-  void generate_style_tag();
-  std::string make_file_link(std::string name);
-  bool is_utf8_sequence(std::string const& str, size_t firstpos);
-  void detect_input_encoding(std::string const& str, size_t firstpos);
-  void init_allowed__markup();
-
-  /**
-   * Program-level generation functions
-   */
-
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_service(t_service* tservice);
-  void generate_xception(t_struct* txception);
-
-  void print_doc(t_doc* tdoc);
-  int print_type(t_type* ttype);
-  void print_const_value(t_type* type, t_const_value* tvalue);
-  void print_fn_args_doc(t_function* tfunction);
-
-private:
-  std::ofstream f_out_;
-  std::string current_file_;
-  input_type input_type_;
-  std::map<std::string, int> allowed_markup;
-  bool standalone_;
-  bool unsafe_;
-};
-
-/**
- * Emits the Table of Contents links at the top of the module's page
- */
-void t_html_generator::generate_program_toc() {
-  f_out_ << "<table class=\"table-bordered table-striped "
-            "table-condensed\"><thead><th>Module</th><th>Services</th>"
-         << "<th>Data types</th><th>Constants</th></thead>" << endl;
-  generate_program_toc_row(program_);
-  f_out_ << "</table>" << endl;
-}
-
-/**
- * Recurses through from the provided program and generates a ToC row
- * for each discovered program exactly once by maintaining the list of
- * completed rows in 'finished'
- */
-void t_html_generator::generate_program_toc_rows(t_program* tprog,
-                                                 std::vector<t_program*>& finished) {
-  for (vector<t_program*>::iterator iter = finished.begin(); iter != finished.end(); iter++) {
-    if (tprog->get_path() == (*iter)->get_path()) {
-      return;
-    }
-  }
-  finished.push_back(tprog);
-  generate_program_toc_row(tprog);
-  vector<t_program*> includes = tprog->get_includes();
-  for (vector<t_program*>::iterator iter = includes.begin(); iter != includes.end(); iter++) {
-    generate_program_toc_rows(*iter, finished);
-  }
-}
-
-/**
- * Emits the Table of Contents links at the top of the module's page
- */
-void t_html_generator::generate_program_toc_row(t_program* tprog) {
-  string fname = tprog->get_name() + ".html";
-  f_out_ << "<tr>" << endl << "<td>" << tprog->get_name() << "</td><td>";
-  if (!tprog->get_services().empty()) {
-    vector<t_service*> services = tprog->get_services();
-    vector<t_service*>::iterator sv_iter;
-    for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-      string name = get_service_name(*sv_iter);
-      f_out_ << "<a href=\"" << make_file_link(fname) << "#Svc_" << name << "\">" << name
-             << "</a><br/>" << endl;
-      f_out_ << "<ul>" << endl;
-      map<string, string> fn_html;
-      vector<t_function*> functions = (*sv_iter)->get_functions();
-      vector<t_function*>::iterator fn_iter;
-      for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
-        string fn_name = (*fn_iter)->get_name();
-        string html = "<li><a href=\"" + make_file_link(fname) + "#Fn_" + name + "_" + fn_name
-                      + "\">" + fn_name + "</a></li>";
-        fn_html.insert(pair<string, string>(fn_name, html));
-      }
-      for (map<string, string>::iterator html_iter = fn_html.begin(); html_iter != fn_html.end();
-           html_iter++) {
-        f_out_ << html_iter->second << endl;
-      }
-      f_out_ << "</ul>" << endl;
-    }
-  }
-  f_out_ << "</td>" << endl << "<td>";
-  map<string, string> data_types;
-  if (!tprog->get_enums().empty()) {
-    vector<t_enum*> enums = tprog->get_enums();
-    vector<t_enum*>::iterator en_iter;
-    for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-      string name = (*en_iter)->get_name();
-      // f_out_ << "<a href=\"" << make_file_link(fname) << "#Enum_" << name << "\">" << name
-      // <<  "</a><br/>" << endl;
-      string html = "<a href=\"" + make_file_link(fname) + "#Enum_" + name + "\">" + name + "</a>";
-      data_types.insert(pair<string, string>(name, html));
-    }
-  }
-  if (!tprog->get_typedefs().empty()) {
-    vector<t_typedef*> typedefs = tprog->get_typedefs();
-    vector<t_typedef*>::iterator td_iter;
-    for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-      string name = (*td_iter)->get_symbolic();
-      // f_out_ << "<a href=\"" << make_file_link(fname) << "#Typedef_" << name << "\">" << name
-      // << "</a><br/>" << endl;
-      string html = "<a href=\"" + make_file_link(fname) + "#Typedef_" + name + "\">" + name
-                    + "</a>";
-      data_types.insert(pair<string, string>(name, html));
-    }
-  }
-  if (!tprog->get_objects().empty()) {
-    vector<t_struct*> objects = tprog->get_objects();
-    vector<t_struct*>::iterator o_iter;
-    for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-      string name = (*o_iter)->get_name();
-      // f_out_ << "<a href=\"" << make_file_link(fname) << "#Struct_" << name << "\">" << name
-      //<< "</a><br/>" << endl;
-      string html = "<a href=\"" + make_file_link(fname) + "#Struct_" + name + "\">" + name
-                    + "</a>";
-      data_types.insert(pair<string, string>(name, html));
-    }
-  }
-  for (map<string, string>::iterator dt_iter = data_types.begin(); dt_iter != data_types.end();
-       dt_iter++) {
-    f_out_ << dt_iter->second << "<br/>" << endl;
-  }
-  f_out_ << "</td>" << endl << "<td>";
-  if (!tprog->get_consts().empty()) {
-    map<string, string> const_html;
-    vector<t_const*> consts = tprog->get_consts();
-    vector<t_const*>::iterator con_iter;
-    for (con_iter = consts.begin(); con_iter != consts.end(); ++con_iter) {
-      string name = (*con_iter)->get_name();
-      string html = "<code><a href=\"" + make_file_link(fname) + "#Const_" + name + "\">" + name
-                    + "</a></code>";
-      const_html.insert(pair<string, string>(name, html));
-    }
-    for (map<string, string>::iterator con_iter = const_html.begin(); con_iter != const_html.end();
-         con_iter++) {
-      f_out_ << con_iter->second << "<br/>" << endl;
-    }
-  }
-  f_out_ << "</code></td>" << endl << "</tr>";
-}
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * stream.
- */
-void t_html_generator::generate_program() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-  current_file_ = program_->get_name() + ".html";
-  string fname = get_out_dir() + current_file_;
-  f_out_.open(fname.c_str());
-  f_out_ << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" << endl;
-  f_out_ << "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" << endl;
-  f_out_ << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl;
-  f_out_ << "<head>" << endl;
-  f_out_ << "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />" << endl;
-  generate_style_tag();
-  f_out_ << "<title>Thrift module: " << program_->get_name() << "</title></head><body>" << endl
-         << "<div class=\"container-fluid\">" << endl
-         << "<h1>Thrift module: " << program_->get_name() << "</h1>" << endl;
-
-  print_doc(program_);
-
-  generate_program_toc();
-
-  if (!program_->get_consts().empty()) {
-    f_out_ << "<hr/><h2 id=\"Constants\">Constants</h2>" << endl;
-    vector<t_const*> consts = program_->get_consts();
-    f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
-    f_out_ << "<thead><th>Constant</th><th>Type</th><th>Value</th></thead>" << endl;
-    generate_consts(consts);
-    f_out_ << "</table>";
-  }
-
-  if (!program_->get_enums().empty()) {
-    f_out_ << "<hr/><h2 id=\"Enumerations\">Enumerations</h2>" << endl;
-    // Generate enums
-    vector<t_enum*> enums = program_->get_enums();
-    vector<t_enum*>::iterator en_iter;
-    for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-      generate_enum(*en_iter);
-    }
-  }
-
-  if (!program_->get_typedefs().empty()) {
-    f_out_ << "<hr/><h2 id=\"Typedefs\">Type declarations</h2>" << endl;
-    // Generate typedefs
-    vector<t_typedef*> typedefs = program_->get_typedefs();
-    vector<t_typedef*>::iterator td_iter;
-    for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-      generate_typedef(*td_iter);
-    }
-  }
-
-  if (!program_->get_objects().empty()) {
-    f_out_ << "<hr/><h2 id=\"Structs\">Data structures</h2>" << endl;
-    // Generate structs and exceptions in declared order
-    vector<t_struct*> objects = program_->get_objects();
-    vector<t_struct*>::iterator o_iter;
-    for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
-      if ((*o_iter)->is_xception()) {
-        generate_xception(*o_iter);
-      } else {
-        generate_struct(*o_iter);
-      }
-    }
-  }
-
-  if (!program_->get_services().empty()) {
-    f_out_ << "<hr/><h2 id=\"Services\">Services</h2>" << endl;
-    // Generate services
-    vector<t_service*> services = program_->get_services();
-    vector<t_service*>::iterator sv_iter;
-    for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-      service_name_ = get_service_name(*sv_iter);
-      generate_service(*sv_iter);
-    }
-  }
-
-  f_out_ << "</div></body></html>" << endl;
-  f_out_.close();
-
-  generate_index();
-  generate_css();
-}
-
-/**
- * Emits the index.html file for the recursive set of Thrift programs
- */
-void t_html_generator::generate_index() {
-  current_file_ = "index.html";
-  string index_fname = get_out_dir() + current_file_;
-  f_out_.open(index_fname.c_str());
-  f_out_ << "<html><head>" << endl;
-  generate_style_tag();
-  f_out_ << "<title>All Thrift declarations</title></head><body>" << endl
-         << "<div class=\"container-fluid\">" << endl << "<h1>All Thrift declarations</h1>" << endl;
-  f_out_ << "<table class=\"table-bordered table-striped "
-            "table-condensed\"><thead><th>Module</th><th>Services</th><th>Data types</th>"
-         << "<th>Constants</th></thead>" << endl;
-  vector<t_program*> programs;
-  generate_program_toc_rows(program_, programs);
-  f_out_ << "</table>" << endl;
-  f_out_ << "</div></body></html>" << endl;
-  f_out_.close();
-}
-
-void t_html_generator::generate_css() {
-  if (!standalone_) {
-    current_file_ = "style.css";
-    string css_fname = get_out_dir() + current_file_;
-    f_out_.open(css_fname.c_str());
-    generate_css_content(f_out_);
-    f_out_.close();
-  }
-}
-
-void t_html_generator::generate_css_content(std::ofstream& f_target) {
-  f_target << BOOTSTRAP_CSS() << endl;
-  f_target << "/* Auto-generated CSS for generated Thrift docs */" << endl;
-  f_target << "h3, h4 { margin-bottom: 6px; }" << endl;
-  f_target << "div.definition { border: 1px solid #CCC; margin-bottom: 10px; padding: 10px; }"
-           << endl;
-  f_target << "div.extends { margin: -0.5em 0 1em 5em }" << endl;
-  f_target << "td { vertical-align: top; }" << endl;
-  f_target << "table { empty-cells: show; }" << endl;
-  f_target << "code { line-height: 20px; }" << endl;
-  f_target << ".table-bordered th, .table-bordered td { border-bottom: 1px solid #DDDDDD; }"
-           << endl;
-}
-
-/**
- * Generates the CSS tag.
- * Depending on "standalone", either a CSS file link (default), or the entire CSS is embedded
- * inline.
- */
-void t_html_generator::generate_style_tag() {
-  if (!standalone_) {
-    f_out_ << "<link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\"/>" << endl;
-  } else {
-    f_out_ << "<style type=\"text/css\"/><!--" << endl;
-    generate_css_content(f_out_);
-    f_out_ << "--></style>" << endl;
-  }
-}
-
-/**
- * Returns the target file for a <a href> link
- * The returned string is empty, whenever filename refers to the current file.
- */
-std::string t_html_generator::make_file_link(std::string filename) {
-  return (current_file_.compare(filename) != 0) ? filename : "";
-}
-
-/**
- * If the provided documentable object has documentation attached, this
- * will emit it to the output stream in HTML format.
- */
-void t_html_generator::print_doc(t_doc* tdoc) {
-  if (tdoc->has_doc()) {
-    if (unsafe_) {
-      f_out_ << tdoc->get_doc() << "<br/>";
-    } else {
-      f_out_ << escape_html(tdoc->get_doc()) << "<br/>";
-    }
-  }
-}
-
-bool t_html_generator::is_utf8_sequence(std::string const& str, size_t firstpos) {
-  // leading char determines the length of the sequence
-  unsigned char c = str.at(firstpos);
-  int count = 0;
-  if ((c & 0xE0) == 0xC0) {
-    count = 1;
-  } else if ((c & 0xF0) == 0xE0) {
-    count = 2;
-  } else if ((c & 0xF8) == 0xF0) {
-    count = 3;
-  } else if ((c & 0xFC) == 0xF8) {
-    count = 4;
-  } else if ((c & 0xFE) == 0xFC) {
-    count = 5;
-  } else {
-    // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 leading byte", c, int(c));
-    return false; // no UTF-8
-  }
-
-  // following chars
-  size_t pos = firstpos + 1;
-  while ((pos < str.length()) && (0 < count)) {
-    c = str.at(pos);
-    if ((c & 0xC0) != 0x80) {
-      // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 following byte", c, int(c));
-      return false; // no UTF-8
-    }
-    --count;
-    ++pos;
-  }
-
-  // true if the sequence is complete
-  return (0 == count);
-}
-
-void t_html_generator::detect_input_encoding(std::string const& str, size_t firstpos) {
-  if (is_utf8_sequence(str, firstpos)) {
-    pdebug("Input seems to be already UTF-8 encoded");
-    input_type_ = INPUT_UTF8;
-    return;
-  }
-
-  // fallback
-  pwarning(1, "Input is not UTF-8, treating as plain ANSI");
-  input_type_ = INPUT_PLAIN;
-}
-
-void t_html_generator::init_allowed__markup() {
-  allowed_markup.clear();
-  // standalone tags
-  allowed_markup["br"] = 1;
-  allowed_markup["br/"] = 1;
-  allowed_markup["img"] = 1;
-  // paired tags
-  allowed_markup["b"] = 1;
-  allowed_markup["/b"] = 1;
-  allowed_markup["u"] = 1;
-  allowed_markup["/u"] = 1;
-  allowed_markup["i"] = 1;
-  allowed_markup["/i"] = 1;
-  allowed_markup["s"] = 1;
-  allowed_markup["/s"] = 1;
-  allowed_markup["big"] = 1;
-  allowed_markup["/big"] = 1;
-  allowed_markup["small"] = 1;
-  allowed_markup["/small"] = 1;
-  allowed_markup["sup"] = 1;
-  allowed_markup["/sup"] = 1;
-  allowed_markup["sub"] = 1;
-  allowed_markup["/sub"] = 1;
-  allowed_markup["pre"] = 1;
-  allowed_markup["/pre"] = 1;
-  allowed_markup["tt"] = 1;
-  allowed_markup["/tt"] = 1;
-  allowed_markup["ul"] = 1;
-  allowed_markup["/ul"] = 1;
-  allowed_markup["ol"] = 1;
-  allowed_markup["/ol"] = 1;
-  allowed_markup["li"] = 1;
-  allowed_markup["/li"] = 1;
-  allowed_markup["a"] = 1;
-  allowed_markup["/a"] = 1;
-  allowed_markup["p"] = 1;
-  allowed_markup["/p"] = 1;
-  allowed_markup["code"] = 1;
-  allowed_markup["/code"] = 1;
-  allowed_markup["dl"] = 1;
-  allowed_markup["/dl"] = 1;
-  allowed_markup["dt"] = 1;
-  allowed_markup["/dt"] = 1;
-  allowed_markup["dd"] = 1;
-  allowed_markup["/dd"] = 1;
-  allowed_markup["h1"] = 1;
-  allowed_markup["/h1"] = 1;
-  allowed_markup["h2"] = 1;
-  allowed_markup["/h2"] = 1;
-  allowed_markup["h3"] = 1;
-  allowed_markup["/h3"] = 1;
-  allowed_markup["h4"] = 1;
-  allowed_markup["/h4"] = 1;
-  allowed_markup["h5"] = 1;
-  allowed_markup["/h5"] = 1;
-  allowed_markup["h6"] = 1;
-  allowed_markup["/h6"] = 1;
-}
-
-std::string t_html_generator::escape_html_tags(std::string const& str) {
-  std::ostringstream result;
-
-  unsigned char c = '?';
-  size_t lastpos;
-  size_t firstpos = 0;
-  while (firstpos < str.length()) {
-
-    // look for non-ASCII char
-    lastpos = firstpos;
-    while (lastpos < str.length()) {
-      c = str.at(lastpos);
-      if (('<' == c) || ('>' == c)) {
-        break;
-      }
-      ++lastpos;
-    }
-
-    // copy what we got so far
-    if (lastpos > firstpos) {
-      result << str.substr(firstpos, lastpos - firstpos);
-      firstpos = lastpos;
-    }
-
-    // reached the end?
-    if (firstpos >= str.length()) {
-      break;
-    }
-
-    // tag end without corresponding begin
-    ++firstpos;
-    if ('>' == c) {
-      result << "&gt;";
-      continue;
-    }
-
-    // extract the tag
-    std::ostringstream tagstream;
-    while (firstpos < str.length()) {
-      c = str.at(firstpos);
-      ++firstpos;
-      if ('<' == c) {
-        tagstream << "&lt;"; // nested begin?
-      } else if ('>' == c) {
-        break;
-      } else {
-        tagstream << c; // not very efficient, but tags should be quite short
-      }
-    }
-
-    // we allow for several markup in docstrings, all else will become escaped
-    string tag_content = tagstream.str();
-    string tag_key = tag_content;
-    size_t first_white = tag_key.find_first_of(" \t\f\v\n\r");
-    if (first_white != string::npos) {
-      tag_key.erase(first_white);
-    }
-    for (std::string::size_type i = 0; i < tag_key.length(); ++i) {
-      tag_key[i] = tolower(tag_key[i]);
-    }
-    if (allowed_markup.find(tag_key) != allowed_markup.end()) {
-      result << "<" << tag_content << ">";
-    } else {
-      result << "&lt;" << tagstream.str() << "&gt;";
-      pverbose("illegal markup <%s> in doc-comment\n", tag_key.c_str());
-    }
-  }
-
-  return result.str();
-}
-
-std::string t_html_generator::escape_html(std::string const& str) {
-  // the generated HTML header says it is UTF-8 encoded
-  // if UTF-8 input has been detected before, we don't need to change anything
-  if (input_type_ == INPUT_UTF8) {
-    return escape_html_tags(str);
-  }
-
-  // convert unsafe chars to their &#<num>; equivalent
-  std::ostringstream result;
-  unsigned char c = '?';
-  unsigned int ic = 0;
-  size_t lastpos;
-  size_t firstpos = 0;
-  while (firstpos < str.length()) {
-
-    // look for non-ASCII char
-    lastpos = firstpos;
-    while (lastpos < str.length()) {
-      c = str.at(lastpos);
-      ic = c;
-      if ((32 > ic) || (127 < ic)) {
-        break;
-      }
-      ++lastpos;
-    }
-
-    // copy what we got so far
-    if (lastpos > firstpos) {
-      result << str.substr(firstpos, lastpos - firstpos);
-      firstpos = lastpos;
-    }
-
-    // reached the end?
-    if (firstpos >= str.length()) {
-      break;
-    }
-
-    // some control code?
-    if (ic <= 31) {
-      switch (c) {
-      case '\r':
-      case '\n':
-      case '\t':
-        result << c;
-        break;
-      default: // silently consume all other ctrl chars
-        break;
-      }
-      ++firstpos;
-      continue;
-    }
-
-    // reached the end?
-    if (firstpos >= str.length()) {
-      break;
-    }
-
-    // try to detect input encoding
-    if (input_type_ == INPUT_UNKNOWN) {
-      detect_input_encoding(str, firstpos);
-      if (input_type_ == INPUT_UTF8) {
-        lastpos = str.length();
-        result << str.substr(firstpos, lastpos - firstpos);
-        break;
-      }
-    }
-
-    // convert the character to something useful based on the detected encoding
-    switch (input_type_) {
-    case INPUT_PLAIN:
-      result << "&#" << ic << ";";
-      ++firstpos;
-      break;
-    default:
-      throw "Unexpected or unrecognized input encoding";
-    }
-  }
-
-  return escape_html_tags(result.str());
-}
-
-/**
- * Prints out the provided type in HTML
- */
-int t_html_generator::print_type(t_type* ttype) {
-  std::string::size_type len = 0;
-  f_out_ << "<code>";
-  if (ttype->is_container()) {
-    if (ttype->is_list()) {
-      f_out_ << "list&lt;";
-      len = 6 + print_type(((t_list*)ttype)->get_elem_type());
-      f_out_ << "&gt;";
-    } else if (ttype->is_set()) {
-      f_out_ << "set&lt;";
-      len = 5 + print_type(((t_set*)ttype)->get_elem_type());
-      f_out_ << "&gt;";
-    } else if (ttype->is_map()) {
-      f_out_ << "map&lt;";
-      len = 5 + print_type(((t_map*)ttype)->get_key_type());
-      f_out_ << ", ";
-      len += print_type(((t_map*)ttype)->get_val_type());
-      f_out_ << "&gt;";
-    }
-  } else if (ttype->is_base_type()) {
-    f_out_ << (((t_base_type*)ttype)->is_binary() ? "binary" : ttype->get_name());
-    len = ttype->get_name().size();
-  } else {
-    string prog_name = ttype->get_program()->get_name();
-    string type_name = ttype->get_name();
-    f_out_ << "<a href=\"" << make_file_link(prog_name + ".html") << "#";
-    if (ttype->is_typedef()) {
-      f_out_ << "Typedef_";
-    } else if (ttype->is_struct() || ttype->is_xception()) {
-      f_out_ << "Struct_";
-    } else if (ttype->is_enum()) {
-      f_out_ << "Enum_";
-    } else if (ttype->is_service()) {
-      f_out_ << "Svc_";
-    }
-    f_out_ << type_name << "\">";
-    len = type_name.size();
-    if (ttype->get_program() != program_) {
-      f_out_ << prog_name << ".";
-      len += prog_name.size() + 1;
-    }
-    f_out_ << type_name << "</a>";
-  }
-  f_out_ << "</code>";
-  return (int)len;
-}
-
-/**
- * Prints out an HTML representation of the provided constant value
- */
-void t_html_generator::print_const_value(t_type* type, t_const_value* tvalue) {
-
-  // if tvalue is an identifier, the constant content is already shown elsewhere
-  if (tvalue->get_type() == t_const_value::CV_IDENTIFIER) {
-    string fname = program_->get_name() + ".html";
-    string name = escape_html(tvalue->get_identifier());
-    f_out_ << "<code><a href=\"" + make_file_link(fname) + "#Const_" + name + "\">" + name
-              + "</a></code>";
-    return;
-  }
-
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
-
-  bool first = true;
-  if (truetype->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      f_out_ << '"' << escape_html(get_escaped_string(tvalue)) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      f_out_ << ((tvalue->get_integer() != 0) ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-      f_out_ << tvalue->get_integer();
-      break;
-    case t_base_type::TYPE_I16:
-      f_out_ << tvalue->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      f_out_ << tvalue->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      f_out_ << tvalue->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (tvalue->get_type() == t_const_value::CV_INTEGER) {
-        f_out_ << tvalue->get_integer();
-      } else {
-        f_out_ << tvalue->get_double();
-      }
-      break;
-    default:
-      f_out_ << "UNKNOWN BASE TYPE";
-      break;
-    }
-  } else if (truetype->is_enum()) {
-    f_out_ << escape_html(truetype->get_name()) << "."
-           << escape_html(tvalue->get_identifier_name());
-  } else if (truetype->is_struct() || truetype->is_xception()) {
-    f_out_ << "{ ";
-    const vector<t_field*>& fields = ((t_struct*)truetype)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = tvalue->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + truetype->get_name() + " has no field "
-            + v_iter->first->get_string();
-      }
-      if (!first) {
-        f_out_ << ", ";
-      }
-      first = false;
-      f_out_ << escape_html(v_iter->first->get_string()) << " = ";
-      print_const_value(field_type, v_iter->second);
-    }
-    f_out_ << " }";
-  } else if (truetype->is_map()) {
-    f_out_ << "{ ";
-    map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
-    map<t_const_value*, t_const_value*>::iterator map_iter;
-    for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
-      if (!first) {
-        f_out_ << ", ";
-      }
-      first = false;
-      print_const_value(((t_map*)truetype)->get_key_type(), map_iter->first);
-      f_out_ << " = ";
-      print_const_value(((t_map*)truetype)->get_val_type(), map_iter->second);
-    }
-    f_out_ << " }";
-  } else if (truetype->is_list()) {
-    f_out_ << "{ ";
-    vector<t_const_value*> list_elems = tvalue->get_list();
-    ;
-    vector<t_const_value*>::iterator list_iter;
-    for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
-      if (!first) {
-        f_out_ << ", ";
-      }
-      first = false;
-      print_const_value(((t_list*)truetype)->get_elem_type(), *list_iter);
-    }
-    f_out_ << " }";
-  } else if (truetype->is_set()) {
-    f_out_ << "{ ";
-    vector<t_const_value*> list_elems = tvalue->get_list();
-    ;
-    vector<t_const_value*>::iterator list_iter;
-    for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
-      if (!first) {
-        f_out_ << ", ";
-      }
-      first = false;
-      print_const_value(((t_set*)truetype)->get_elem_type(), *list_iter);
-    }
-    f_out_ << " }";
-  } else {
-    f_out_ << "UNKNOWN TYPE";
-  }
-}
-
-/**
- * Prints out documentation for arguments/exceptions of a function, if any documentation has been
- * supplied.
- */
-void t_html_generator::print_fn_args_doc(t_function* tfunction) {
-  bool has_docs = false;
-  vector<t_field*> args = tfunction->get_arglist()->get_members();
-  vector<t_field*>::iterator arg_iter = args.begin();
-  if (arg_iter != args.end()) {
-    for (; arg_iter != args.end(); arg_iter++) {
-      if ((*arg_iter)->has_doc() && !(*arg_iter)->get_doc().empty())
-        has_docs = true;
-    }
-    if (has_docs) {
-      arg_iter = args.begin();
-      f_out_ << "<br/><h4 id=\"Parameters_" << service_name_ << "_" << tfunction->get_name()
-             << "\">Parameters</h4>" << endl;
-      f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
-      f_out_ << "<thead><th>Name</th><th>Description</th></thead>";
-      for (; arg_iter != args.end(); arg_iter++) {
-        f_out_ << "<tr><td>" << (*arg_iter)->get_name();
-        f_out_ << "</td><td>";
-        f_out_ << escape_html((*arg_iter)->get_doc());
-        f_out_ << "</td></tr>" << endl;
-      }
-      f_out_ << "</table>";
-    }
-  }
-
-  has_docs = false;
-  vector<t_field*> excepts = tfunction->get_xceptions()->get_members();
-  vector<t_field*>::iterator ex_iter = excepts.begin();
-  if (ex_iter != excepts.end()) {
-    for (; ex_iter != excepts.end(); ex_iter++) {
-      if ((*ex_iter)->has_doc() && !(*ex_iter)->get_doc().empty())
-        has_docs = true;
-    }
-    if (has_docs) {
-      ex_iter = excepts.begin();
-      f_out_ << "<br/><h4 id=\"Exceptions_" << service_name_ << "_" << tfunction->get_name()
-             << "\">Exceptions</h4>" << endl;
-      f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
-      f_out_ << "<thead><th>Type</th><th>Description</th></thead>";
-      for (; ex_iter != excepts.end(); ex_iter++) {
-        f_out_ << "<tr><td>" << (*ex_iter)->get_type()->get_name();
-        f_out_ << "</td><td>";
-        f_out_ << escape_html((*ex_iter)->get_doc());
-        f_out_ << "</td></tr>" << endl;
-      }
-      f_out_ << "</table>";
-    }
-  }
-}
-
-/**
- * Generates a typedef.
- *
- * @param ttypedef The type definition
- */
-void t_html_generator::generate_typedef(t_typedef* ttypedef) {
-  string name = ttypedef->get_name();
-  f_out_ << "<div class=\"definition\">";
-  f_out_ << "<h3 id=\"Typedef_" << name << "\">Typedef: " << name << "</h3>" << endl;
-  f_out_ << "<p><strong>Base type:</strong>&nbsp;";
-  print_type(ttypedef->get_type());
-  f_out_ << "</p>" << endl;
-  print_doc(ttypedef);
-  f_out_ << "</div>" << endl;
-}
-
-/**
- * Generates code for an enumerated type.
- *
- * @param tenum The enumeration
- */
-void t_html_generator::generate_enum(t_enum* tenum) {
-  string name = tenum->get_name();
-  f_out_ << "<div class=\"definition\">";
-  f_out_ << "<h3 id=\"Enum_" << name << "\">Enumeration: " << name << "</h3>" << endl;
-  print_doc(tenum);
-  vector<t_enum_value*> values = tenum->get_constants();
-  vector<t_enum_value*>::iterator val_iter;
-  f_out_ << "<br/><table class=\"table-bordered table-striped table-condensed\">" << endl;
-  for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
-    f_out_ << "<tr><td><code>";
-    f_out_ << (*val_iter)->get_name();
-    f_out_ << "</code></td><td><code>";
-    f_out_ << (*val_iter)->get_value();
-    f_out_ << "</code></td><td>" << endl;
-    print_doc((*val_iter));
-    f_out_ << "</td></tr>" << endl;
-  }
-  f_out_ << "</table></div>" << endl;
-}
-
-/**
- * Generates a constant value
- */
-void t_html_generator::generate_const(t_const* tconst) {
-  string name = tconst->get_name();
-  f_out_ << "<tr id=\"Const_" << name << "\"><td><code>" << name << "</code></td><td>";
-  print_type(tconst->get_type());
-  f_out_ << "</td><td><code>";
-  print_const_value(tconst->get_type(), tconst->get_value());
-  f_out_ << "</code></td></tr>";
-  if (tconst->has_doc()) {
-    f_out_ << "<tr><td colspan=\"3\"><blockquote>";
-    print_doc(tconst);
-    f_out_ << "</blockquote></td></tr>";
-  }
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_html_generator::generate_struct(t_struct* tstruct) {
-  string name = tstruct->get_name();
-  f_out_ << "<div class=\"definition\">";
-  f_out_ << "<h3 id=\"Struct_" << name << "\">";
-  if (tstruct->is_xception()) {
-    f_out_ << "Exception: ";
-  } else if (tstruct->is_union()) {
-    f_out_ << "Union: ";
-  } else {
-    f_out_ << "Struct: ";
-  }
-  f_out_ << name << "</h3>" << endl;
-  vector<t_field*> members = tstruct->get_members();
-  vector<t_field*>::iterator mem_iter = members.begin();
-  f_out_ << "<table class=\"table-bordered table-striped table-condensed\">";
-  f_out_ << "<thead><th>Key</th><th>Field</th><th>Type</th><th>Description</th><th>Requiredness</"
-            "th><th>Default value</th></thead>" << endl;
-  for (; mem_iter != members.end(); mem_iter++) {
-    f_out_ << "<tr><td>" << (*mem_iter)->get_key() << "</td><td>";
-    f_out_ << (*mem_iter)->get_name();
-    f_out_ << "</td><td>";
-    print_type((*mem_iter)->get_type());
-    f_out_ << "</td><td>";
-    f_out_ << escape_html((*mem_iter)->get_doc());
-    f_out_ << "</td><td>";
-    if ((*mem_iter)->get_req() == t_field::T_OPTIONAL) {
-      f_out_ << "optional";
-    } else if ((*mem_iter)->get_req() == t_field::T_REQUIRED) {
-      f_out_ << "required";
-    } else {
-      f_out_ << "default";
-    }
-    f_out_ << "</td><td>";
-    t_const_value* default_val = (*mem_iter)->get_value();
-    if (default_val != NULL) {
-      f_out_ << "<code>";
-      print_const_value((*mem_iter)->get_type(), default_val);
-      f_out_ << "</code>";
-    }
-    f_out_ << "</td></tr>" << endl;
-  }
-  f_out_ << "</table><br/>";
-  print_doc(tstruct);
-  f_out_ << "</div>";
-}
-
-/**
- * Exceptions are special structs
- *
- * @param tstruct The struct definition
- */
-void t_html_generator::generate_xception(t_struct* txception) {
-  generate_struct(txception);
-}
-
-/**
- * Generates the HTML block for a Thrift service.
- *
- * @param tservice The service definition
- */
-void t_html_generator::generate_service(t_service* tservice) {
-  f_out_ << "<h3 id=\"Svc_" << service_name_ << "\">Service: " << service_name_ << "</h3>" << endl;
-
-  if (tservice->get_extends()) {
-    f_out_ << "<div class=\"extends\"><em>extends</em> ";
-    print_type(tservice->get_extends());
-    f_out_ << "</div>\n";
-  }
-  print_doc(tservice);
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator fn_iter = functions.begin();
-  for (; fn_iter != functions.end(); fn_iter++) {
-    string fn_name = (*fn_iter)->get_name();
-    f_out_ << "<div class=\"definition\">";
-    f_out_ << "<h4 id=\"Fn_" << service_name_ << "_" << fn_name << "\">Function: " << service_name_
-           << "." << fn_name << "</h4>" << endl;
-    f_out_ << "<pre>";
-    std::string::size_type offset = print_type((*fn_iter)->get_returntype());
-    bool first = true;
-    f_out_ << " " << fn_name << "(";
-    offset += fn_name.size() + 2;
-    vector<t_field*> args = (*fn_iter)->get_arglist()->get_members();
-    vector<t_field*>::iterator arg_iter = args.begin();
-    for (; arg_iter != args.end(); arg_iter++) {
-      if (!first) {
-        f_out_ << "," << endl;
-        for (std::string::size_type i = 0; i < offset; ++i) {
-          f_out_ << " ";
-        }
-      }
-      first = false;
-      print_type((*arg_iter)->get_type());
-      f_out_ << " " << (*arg_iter)->get_name();
-      if ((*arg_iter)->get_value() != NULL) {
-        f_out_ << " = ";
-        print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value());
-      }
-    }
-    f_out_ << ")" << endl;
-    first = true;
-    vector<t_field*> excepts = (*fn_iter)->get_xceptions()->get_members();
-    vector<t_field*>::iterator ex_iter = excepts.begin();
-    if (ex_iter != excepts.end()) {
-      f_out_ << "    throws ";
-      for (; ex_iter != excepts.end(); ex_iter++) {
-        if (!first) {
-          f_out_ << ", ";
-        }
-        first = false;
-        print_type((*ex_iter)->get_type());
-      }
-      f_out_ << endl;
-    }
-    f_out_ << "</pre>";
-    print_doc(*fn_iter);
-    print_fn_args_doc(*fn_iter);
-    f_out_ << "</div>";
-  }
-}
-
-THRIFT_REGISTER_GENERATOR(
-    html,
-    "HTML",
-    "    standalone:      Self-contained mode, includes all CSS in the HTML files.\n"
-    "                     Generates no style.css file, but HTML files will be larger.\n"
-    "    noescape:        Do not escape html in doc text.\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_html_generator.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_html_generator.h b/compiler/cpp/src/generate/t_html_generator.h
deleted file mode 100644
index 600b17f..0000000
--- a/compiler/cpp/src/generate/t_html_generator.h
+++ /dev/null
@@ -1,240 +0,0 @@
-#define BOOTSTRAP_CSS()                                                                            \
-  "/*!\n"                                                                                          \
-  " * Bootstrap v2.0.3\n"                                                                          \
-  " *\n"                                                                                           \
-  " * Copyright 2012 Twitter, Inc\n"                                                               \
-  " * Licensed under the Apache License v2.0\n"                                                    \
-  " * http://www.apache.org/licenses/LICENSE-2.0\n"                                                \
-  " *\n"                                                                                           \
-  " * Designed and built with all the love in the world @twitter by @mdo and @fat.\n"              \
-  " */\n"                                                                                          \
-  ".clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:\"\";}\n"             \
-  ".clearfix:after{clear:both;}\n"                                                                 \
-  ".hide-text{font:0/0 "                                                                           \
-  "a;color:transparent;text-shadow:none;background-color:transparent;border:0;}\n"                 \
-  ".input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-"    \
-  "moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;}\n"                  \
-  "article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}\n"     \
-  "audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}\n"                            \
-  "audio:not([controls]){display:none;}\n"                                                         \
-  "html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}\n"                \
-  "a:focus{outline:thin dotted #333;outline:5px auto "                                             \
-  "-webkit-focus-ring-color;outline-offset:-2px;}\n"                                               \
-  "a:hover,a:active{outline:0;}\n"                                                                 \
-  "sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}\n"              \
-  "sup{top:-0.5em;}\n"                                                                             \
-  "sub{bottom:-0.25em;}\n"                                                                         \
-  "img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}\n"           \
-  "button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}\n"                 \
-  "button,input{*overflow:visible;line-height:normal;}\n"                                          \
-  "button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}\n"                        \
-  "button,input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{cursor:pointer;-"    \
-  "webkit-appearance:button;}\n"                                                                   \
-  "input[type=\"search\"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:"  \
-  "content-box;-webkit-appearance:textfield;}\n"                                                   \
-  "input[type=\"search\"]::-webkit-search-decoration,input[type=\"search\"]::-webkit-search-"      \
-  "cancel-button{-webkit-appearance:none;}\n"                                                      \
-  "textarea{overflow:auto;vertical-align:top;}\n"                                                  \
-  "body{margin:0;font-family:\"Helvetica "                                                         \
-  "Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-"    \
-  "color:#ffffff;}\n"                                                                              \
-  "a{color:#0088cc;text-decoration:none;}\n"                                                       \
-  "a:hover{color:#005580;text-decoration:underline;}\n"                                            \
-  ".row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:\"\";}\n"          \
-  ".row:after{clear:both;}\n"                                                                      \
-  "[class*=\"span\"]{float:left;margin-left:20px;}\n"                                              \
-  ".container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}\n"        \
-  ".span12{width:940px;}\n"                                                                        \
-  ".span11{width:860px;}\n"                                                                        \
-  ".span10{width:780px;}\n"                                                                        \
-  ".span9{width:700px;}\n"                                                                         \
-  ".span8{width:620px;}\n"                                                                         \
-  ".span7{width:540px;}\n"                                                                         \
-  ".span6{width:460px;}\n"                                                                         \
-  ".span5{width:380px;}\n"                                                                         \
-  ".span4{width:300px;}\n"                                                                         \
-  ".span3{width:220px;}\n"                                                                         \
-  ".span2{width:140px;}\n"                                                                         \
-  ".span1{width:60px;}\n"                                                                          \
-  ".offset12{margin-left:980px;}\n"                                                                \
-  ".offset11{margin-left:900px;}\n"                                                                \
-  ".offset10{margin-left:820px;}\n"                                                                \
-  ".offset9{margin-left:740px;}\n"                                                                 \
-  ".offset8{margin-left:660px;}\n"                                                                 \
-  ".offset7{margin-left:580px;}\n"                                                                 \
-  ".offset6{margin-left:500px;}\n"                                                                 \
-  ".offset5{margin-left:420px;}\n"                                                                 \
-  ".offset4{margin-left:340px;}\n"                                                                 \
-  ".offset3{margin-left:260px;}\n"                                                                 \
-  ".offset2{margin-left:180px;}\n"                                                                 \
-  ".offset1{margin-left:100px;}\n"                                                                 \
-  ".row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:\"\";}" \
-  "\n"                                                                                             \
-  ".row-fluid:after{clear:both;}\n"                                                                \
-  ".row-fluid "                                                                                    \
-  "[class*=\"span\"]{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-" \
-  "box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:"  \
-  "2.127659574%;*margin-left:2.0744680846382977%;}\n"                                              \
-  ".row-fluid [class*=\"span\"]:first-child{margin-left:0;}\n"                                     \
-  ".row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%;}\n"                      \
-  ".row-fluid .span11{width:91.489361693%;*width:91.4361702036383%;}\n"                            \
-  ".row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%;}\n"                      \
-  ".row-fluid .span9{width:74.468085099%;*width:74.4148936096383%;}\n"                             \
-  ".row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%;}\n"                       \
-  ".row-fluid .span7{width:57.446808505%;*width:57.3936170156383%;}\n"                             \
-  ".row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%;}\n"                       \
-  ".row-fluid .span5{width:40.425531911%;*width:40.3723404216383%;}\n"                             \
-  ".row-fluid .span4{width:31.914893614%;*width:31.8617021246383%;}\n"                             \
-  ".row-fluid .span3{width:23.404255317%;*width:23.3510638276383%;}\n"                             \
-  ".row-fluid .span2{width:14.89361702%;*width:14.8404255306383%;}\n"                              \
-  ".row-fluid .span1{width:6.382978723%;*width:6.329787233638298%;}\n"                             \
-  ".container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{"     \
-  "display:table;content:\"\";}\n"                                                                 \
-  ".container:after{clear:both;}\n"                                                                \
-  ".container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,."       \
-  "container-fluid:after{display:table;content:\"\";}\n"                                           \
-  ".container-fluid:after{clear:both;}\n"                                                          \
-  "p{margin:0 0 9px;font-family:\"Helvetica "                                                      \
-  "Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p "                          \
-  "small{font-size:11px;color:#999999;}\n"                                                         \
-  ".lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;}\n"                   \
-  "h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:"  \
-  "optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 "                           \
-  "small{font-weight:normal;color:#999999;}\n"                                                     \
-  "h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}\n"                                \
-  "h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}\n"                                \
-  "h3{font-size:18px;line-height:27px;}h3 small{font-size:14px;}\n"                                \
-  "h4,h5,h6{line-height:18px;}\n"                                                                  \
-  "h4{font-size:14px;}h4 small{font-size:12px;}\n"                                                 \
-  "h5{font-size:12px;}\n"                                                                          \
-  "h6{font-size:11px;color:#999999;text-transform:uppercase;}\n"                                   \
-  ".page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;}\n"             \
-  ".page-header h1{line-height:1;}\n"                                                              \
-  "ul,ol{padding:0;margin:0 0 9px 25px;}\n"                                                        \
-  "ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}\n"                                                    \
-  "ul{list-style:disc;}\n"                                                                         \
-  "ol{list-style:decimal;}\n"                                                                      \
-  "li{line-height:18px;}\n"                                                                        \
-  "ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}\n"                                      \
-  "dl{margin-bottom:18px;}\n"                                                                      \
-  "dt,dd{line-height:18px;}\n"                                                                     \
-  "dt{font-weight:bold;line-height:17px;}\n"                                                       \
-  "dd{margin-left:9px;}\n"                                                                         \
-  ".dl-horizontal "                                                                                \
-  "dt{float:left;width:120px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;"  \
-  "white-space:nowrap;}\n"                                                                         \
-  ".dl-horizontal dd{margin-left:130px;}\n"                                                        \
-  "hr{margin:18px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}\n"     \
-  "strong{font-weight:bold;}\n"                                                                    \
-  "em{font-style:italic;}\n"                                                                       \
-  ".muted{color:#999999;}\n"                                                                       \
-  "abbr[title]{cursor:help;border-bottom:1px dotted #ddd;}\n"                                      \
-  "abbr.initialism{font-size:90%;text-transform:uppercase;}\n"                                     \
-  "blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote "       \
-  "p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}\n"                        \
-  "blockquote small{display:block;line-height:18px;color:#999999;}blockquote "                     \
-  "small:before{content:'\\2014 \\00A0';}\n"                                                       \
-  "blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid "    \
-  "#eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right "                          \
-  "small{text-align:right;}\n"                                                                     \
-  "q:before,q:after,blockquote:before,blockquote:after{content:\"\";}\n"                           \
-  "address{display:block;margin-bottom:18px;font-style:normal;line-height:18px;}\n"                \
-  "small{font-size:100%;}\n"                                                                       \
-  "cite{font-style:normal;}\n"                                                                     \
-  "code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,\"Courier "                        \
-  "New\",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;" \
-  "border-radius:3px;}\n"                                                                          \
-  "code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}\n"          \
-  "pre{display:block;padding:8.5px;margin:0 0 "                                                    \
-  "9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:" \
-  "pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid "      \
-  "rgba(0, 0, 0, "                                                                                 \
-  "0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{"     \
-  "margin-bottom:18px;}\n"                                                                         \
-  "pre code{padding:0;color:inherit;background-color:transparent;border:0;}\n"                     \
-  ".pre-scrollable{max-height:340px;overflow-y:scroll;}\n"                                         \
-  ".label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#ffffff;vertical-"     \
-  "align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, "                          \
-  "0.25);background-color:#999999;}\n"                                                             \
-  ".label{padding:1px 4px "                                                                        \
-  "2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}\n"                     \
-  ".badge{padding:1px 9px "                                                                        \
-  "2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}\n"                     \
-  "a.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}\n"              \
-  ".label-important,.badge-important{background-color:#b94a48;}\n"                                 \
-  ".label-important[href],.badge-important[href]{background-color:#953b39;}\n"                     \
-  ".label-warning,.badge-warning{background-color:#f89406;}\n"                                     \
-  ".label-warning[href],.badge-warning[href]{background-color:#c67605;}\n"                         \
-  ".label-success,.badge-success{background-color:#468847;}\n"                                     \
-  ".label-success[href],.badge-success[href]{background-color:#356635;}\n"                         \
-  ".label-info,.badge-info{background-color:#3a87ad;}\n"                                           \
-  ".label-info[href],.badge-info[href]{background-color:#2d6987;}\n"                               \
-  ".label-inverse,.badge-inverse{background-color:#333333;}\n"                                     \
-  ".label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a;}\n"                         \
-  "table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}"  \
-  "\n"                                                                                             \
-  ".table{width:100%;margin-bottom:18px;}.table th,.table "                                        \
-  "td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid "       \
-  "#dddddd;}\n"                                                                                    \
-  ".table th{font-weight:bold;}\n"                                                                 \
-  ".table thead th{vertical-align:bottom;}\n"                                                      \
-  ".table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table "          \
-  "colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table "               \
-  "thead:first-child tr:first-child th,.table thead:first-child tr:first-child "                   \
-  "td{border-top:0;}\n"                                                                            \
-  ".table tbody+tbody{border-top:2px solid #dddddd;}\n"                                            \
-  ".table-condensed th,.table-condensed td{padding:4px 5px;}\n"                                    \
-  ".table-bordered{border:1px solid "                                                              \
-  "#dddddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-"      \
-  "radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered "       \
-  "td{border-left:1px solid #dddddd;}\n"                                                           \
-  ".table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child "  \
-  "th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead "             \
-  "tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered "            \
-  "colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child "             \
-  "th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child "      \
-  "tr:first-child td{border-top:0;}\n"                                                             \
-  ".table-bordered thead:first-child tr:first-child th:first-child,.table-bordered "               \
-  "tbody:first-child tr:first-child "                                                              \
-  "td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-"      \
-  "radius-topleft:4px;}\n"                                                                         \
-  ".table-bordered thead:first-child tr:first-child th:last-child,.table-bordered "                \
-  "tbody:first-child tr:first-child "                                                              \
-  "td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-"     \
-  "radius-topright:4px;}\n"                                                                        \
-  ".table-bordered thead:last-child tr:last-child th:first-child,.table-bordered "                 \
-  "tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 "                     \
-  "4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 "                                          \
-  "4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-"    \
-  "bottomleft:4px;}\n"                                                                             \
-  ".table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child " \
-  "tr:last-child "                                                                                 \
-  "td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-"      \
-  "border-radius-bottomright:4px;}\n"                                                              \
-  ".table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) "              \
-  "th{background-color:#f9f9f9;}\n"                                                                \
-  ".table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5;}\n"                 \
-  "table .span1{float:none;width:44px;margin-left:0;}\n"                                           \
-  "table .span2{float:none;width:124px;margin-left:0;}\n"                                          \
-  "table .span3{float:none;width:204px;margin-left:0;}\n"                                          \
-  "table .span4{float:none;width:284px;margin-left:0;}\n"                                          \
-  "table .span5{float:none;width:364px;margin-left:0;}\n"                                          \
-  "table .span6{float:none;width:444px;margin-left:0;}\n"                                          \
-  "table .span7{float:none;width:524px;margin-left:0;}\n"                                          \
-  "table .span8{float:none;width:604px;margin-left:0;}\n"                                          \
-  "table .span9{float:none;width:684px;margin-left:0;}\n"                                          \
-  "table .span10{float:none;width:764px;margin-left:0;}\n"                                         \
-  "table .span11{float:none;width:844px;margin-left:0;}\n"                                         \
-  "table .span12{float:none;width:924px;margin-left:0;}\n"                                         \
-  "table .span13{float:none;width:1004px;margin-left:0;}\n"                                        \
-  "table .span14{float:none;width:1084px;margin-left:0;}\n"                                        \
-  "table .span15{float:none;width:1164px;margin-left:0;}\n"                                        \
-  "table .span16{float:none;width:1244px;margin-left:0;}\n"                                        \
-  "table .span17{float:none;width:1324px;margin-left:0;}\n"                                        \
-  "table .span18{float:none;width:1404px;margin-left:0;}\n"                                        \
-  "table .span19{float:none;width:1484px;margin-left:0;}\n"                                        \
-  "table .span20{float:none;width:1564px;margin-left:0;}\n"                                        \
-  "table .span21{float:none;width:1644px;margin-left:0;}\n"                                        \
-  "table .span22{float:none;width:1724px;margin-left:0;}\n"                                        \
-  "table .span23{float:none;width:1804px;margin-left:0;}\n"                                        \
-  "table .span24{float:none;width:1884px;margin-left:0;}"


[16/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
new file mode 100644
index 0000000..8b1a445
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
@@ -0,0 +1,3920 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <cassert>
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <list>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include <cctype>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+class t_delphi_generator : public t_oop_generator {
+public:
+  t_delphi_generator(t_program* program,
+                     const std::map<std::string, std::string>& parsed_options,
+                     const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    indent_impl_ = 0;
+    has_forward = false;
+    has_enum = false;
+    has_const = false;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    ansistr_binary_ = false;
+    register_types_ = false;
+    constprefix_ = false;
+    events_ = false;
+    xmldoc_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("ansistr_binary") == 0) {
+        ansistr_binary_ = true;
+      } else if( iter->first.compare("register_types") == 0) {
+        register_types_ = true;
+      } else if( iter->first.compare("constprefix") == 0) {
+        constprefix_ = true;
+      } else if( iter->first.compare("events") == 0) {
+        events_ = true;
+      } else if( iter->first.compare("xmldoc") == 0) {
+        xmldoc_ = true;
+      } else {
+        throw "unknown option delphi:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-delphi";
+    escape_.clear();
+    escape_['\''] = "''";
+  }
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_forward_declaration(t_struct* tstruct);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+  void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception);
+  void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic);
+
+  void generate_delphi_property(ostream& out,
+                                bool struct_is_exception,
+                                t_field* tfield,
+                                bool isPublic,
+                                std::string fieldPrefix = "");
+  void generate_delphi_isset_reader_definition(ostream& out, t_field* tfield, bool is_xception);
+  void generate_delphi_property_reader_definition(ostream& out,
+                                                  t_field* tfield,
+                                                  bool is_xception_class);
+  void generate_delphi_property_writer_definition(ostream& out,
+                                                  t_field* tfield,
+                                                  bool is_xception_class);
+  void generate_delphi_property_reader_impl(ostream& out,
+                                            std::string cls_prefix,
+                                            std::string name,
+                                            t_type* type,
+                                            t_field* tfield,
+                                            std::string fieldPrefix,
+                                            bool is_xception_class);
+  void generate_delphi_property_writer_impl(ostream& out,
+                                            std::string cls_prefix,
+                                            std::string name,
+                                            t_type* type,
+                                            t_field* tfield,
+                                            std::string fieldPrefix,
+                                            bool is_xception_class,
+                                            bool is_union,
+                                            bool is_xception_factory,
+                                            std::string xception_factroy_name);
+  void generate_delphi_clear_union_value(ostream& out,
+                                         std::string cls_prefix,
+                                         std::string name,
+                                         t_type* type,
+                                         t_field* tfield,
+                                         std::string fieldPrefix,
+                                         bool is_xception_class,
+                                         bool is_union,
+                                         bool is_xception_factory,
+                                         std::string xception_factroy_name);
+  void generate_delphi_isset_reader_impl(ostream& out,
+                                         std::string cls_prefix,
+                                         std::string name,
+                                         t_type* type,
+                                         t_field* tfield,
+                                         std::string fieldPrefix,
+                                         bool is_xception);
+  void generate_delphi_struct_writer_impl(ostream& out,
+                                          std::string cls_prefix,
+                                          t_struct* tstruct,
+                                          bool is_exception);
+  void generate_delphi_struct_result_writer_impl(ostream& out,
+                                                 std::string cls_prefix,
+                                                 t_struct* tstruct,
+                                                 bool is_exception);
+
+  void generate_delphi_struct_tostring_impl(ostream& out,
+                                            std::string cls_prefix,
+                                            t_struct* tstruct,
+                                            bool is_exception,
+                                            bool is_x_factory);
+
+  void add_delphi_uses_list(string unitname);
+
+  void generate_delphi_struct_reader_impl(ostream& out,
+                                          std::string cls_prefix,
+                                          t_struct* tstruct,
+                                          bool is_exception);
+  void generate_delphi_create_exception_impl(ostream& out,
+                                             string cls_prefix,
+                                             t_struct* tstruct,
+                                             bool is_exception);
+
+  bool const_needs_var(t_type* type);
+  void print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value);
+  void print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value);
+  void print_const_value(std::ostream& vars,
+                         std::ostream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value);
+  void initialize_field(std::ostream& vars,
+                        std::ostream& out,
+                        std::string name,
+                        t_type* type,
+                        t_const_value* value);
+  void finalize_field(std::ostream& out,
+                      std::string name,
+                      t_type* type,
+                      t_const_value* value,
+                      std::string cls_nm = "");
+  std::string render_const_value(std::ostream& local_vars,
+                                 std::ostream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+  void print_const_def_value(std::ostream& vars,
+                             std::ostream& out,
+                             std::string name,
+                             t_type* type,
+                             t_const_value* value,
+                             std::string cls_nm = "");
+  std::string make_constants_classname();
+
+  void generate_delphi_struct(t_struct* tstruct, bool is_exception);
+  void generate_delphi_struct_impl(ostream& out,
+                                   std::string cls_prefix,
+                                   t_struct* tstruct,
+                                   bool is_exception,
+                                   bool is_result = false,
+                                   bool is_x_factory = false);
+  void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct);
+  void generate_delphi_struct_type_factory(ostream& out,
+                                           std::string cls_prefix,
+                                           t_struct* tstruct,
+                                           bool is_exception,
+                                           bool is_result = false,
+                                           bool is_x_factory = false);
+  void generate_delphi_struct_type_factory_registration(ostream& out,
+                                                        std::string cls_prefix,
+                                                        t_struct* tstruct,
+                                                        bool is_exception,
+                                                        bool is_result = false,
+                                                        bool is_x_factory = false);
+  void generate_delphi_struct_definition(std::ostream& out,
+                                         t_struct* tstruct,
+                                         bool is_xception = false,
+                                         bool in_class = false,
+                                         bool is_result = false,
+                                         bool is_x_factory = false);
+  void generate_delphi_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_delphi_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_delphi_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_delphi_struct_tostring(std::ostream& out, t_struct* tstruct);
+
+  void generate_function_helpers(t_function* tfunction);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* function);
+
+  void generate_deserialize_field(std::ostream& out,
+                                  bool is_xception,
+                                  t_field* tfield,
+                                  std::string prefix,
+                                  std::ostream& local_vars);
+  void generate_deserialize_struct(std::ostream& out,
+                                   t_struct* tstruct,
+                                   std::string name,
+                                   std::string prefix);
+  void generate_deserialize_container(ostream& out,
+                                      bool is_xception,
+                                      t_type* ttype,
+                                      string name,
+                                      std::ostream& local_vars);
+
+  void generate_deserialize_set_element(std::ostream& out,
+                                        bool is_xception,
+                                        t_set* tset,
+                                        std::string prefix,
+                                        std::ostream& local_vars);
+  void generate_deserialize_map_element(std::ostream& out,
+                                        bool is_xception,
+                                        t_map* tmap,
+                                        std::string prefix,
+                                        std::ostream& local_vars);
+  void generate_deserialize_list_element(std::ostream& out,
+                                         bool is_xception,
+                                         t_list* list,
+                                         std::string prefix,
+                                         std::ostream& local_vars);
+
+  void generate_serialize_field(std::ostream& out,
+                                bool is_xception,
+                                t_field* tfield,
+                                std::string prefix,
+                                std::ostream& local_vars);
+  void generate_serialize_struct(std::ostream& out,
+                                 t_struct* tstruct,
+                                 std::string prefix,
+                                 std::ostream& local_vars);
+  void generate_serialize_container(std::ostream& out,
+                                    bool is_xception,
+                                    t_type* ttype,
+                                    std::string prefix,
+                                    std::ostream& local_vars);
+  void generate_serialize_map_element(std::ostream& out,
+                                      bool is_xception,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map,
+                                      std::ostream& local_vars);
+  void generate_serialize_set_element(std::ostream& out,
+                                      bool is_xception,
+                                      t_set* tmap,
+                                      std::string iter,
+                                      std::ostream& local_vars);
+  void generate_serialize_list_element(std::ostream& out,
+                                       bool is_xception,
+                                       t_list* tlist,
+                                       std::string iter,
+                                       std::ostream& local_vars);
+
+  void delphi_type_usings(std::ostream& out);
+  std::string delphi_thrift_usings();
+
+  std::string type_name(t_type* ttype,
+                        bool b_cls = false,
+                        bool b_no_postfix = false,
+                        bool b_exception_factory = false,
+                        bool b_full_exception_factory = false);
+  std::string normalize_clsnm(std::string name,
+                              std::string prefix,
+                              bool b_no_check_keyword = false);
+  std::string make_valid_delphi_identifier(std::string const& fromName);
+  std::string input_arg_prefix(t_type* ttype);
+
+  std::string base_type_name(t_base_type* tbase);
+  std::string declare_field(t_field* tfield,
+                            bool init = false,
+                            std::string prefix = "",
+                            bool is_xception_class = false);
+  std::string function_signature(t_function* tfunction,
+                                 std::string full_cls = "",
+                                 bool is_xception = false);
+  std::string argument_list(t_struct* tstruct);
+  std::string constructor_argument_list(t_struct* tstruct, std::string current_indent);
+  std::string type_to_enum(t_type* ttype);
+  std::string prop_name(t_field* tfield, bool is_xception = false);
+  std::string prop_name(std::string name, bool is_xception = false);
+  std::string constructor_param_name(string name);
+
+  void write_enum(std::string line);
+  void write_forward_decr(std::string line);
+  void write_const(std::string line);
+  void write_struct(std::string line);
+  void write_service(std::string line);
+
+  virtual std::string autogen_comment() {
+    return std::string("(**\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+           + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
+           + " *)\n";
+  }
+
+  string replace_all(string contents, string search, string replace);
+  string xml_encode(string contents);
+  string xmldoc_encode(string contents);
+  string xmlattrib_encode(string contents);
+  void generate_delphi_doc(std::ostream& out, t_field* field);
+  void generate_delphi_doc(std::ostream& out, t_doc* tdoc);
+  void generate_delphi_doc(std::ostream& out, t_function* tdoc);
+  void generate_delphi_docstring_comment(std::ostream& out, string contents);
+
+  bool type_can_be_null(t_type* ttype) {
+    while (ttype->is_typedef()) {
+      ttype = ((t_typedef*)ttype)->get_type();
+    }
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
+  }
+
+private:
+  std::string namespace_name_;
+  std::ostringstream s_forward_decr;
+  std::ostringstream s_enum;
+  std::ostringstream s_const;
+  std::ostringstream s_struct;
+  std::ostringstream s_service;
+  std::ostringstream s_const_impl;
+  std::ostringstream s_struct_impl;
+  std::ostringstream s_service_impl;
+  std::ostringstream s_type_factory_registration;
+  std::ostringstream s_type_factory_funcs;
+  bool has_forward;
+  bool has_enum;
+  bool has_const;
+  std::string namespace_dir_;
+  std::map<std::string, int> delphi_keywords;
+  std::map<std::string, int> delphi_reserved_method;
+  std::map<std::string, int> delphi_reserved_method_exception;
+  std::map<std::string, int> types_known;
+  std::list<t_typedef*> typedefs_pending;
+  std::vector<std::string> uses_list;
+  void create_keywords();
+  bool find_keyword(std::map<std::string, int>& keyword_map, std::string name);
+  std::string normalize_name(std::string name,
+                             bool b_method = false,
+                             bool b_exception_method = false);
+  std::string empty_value(t_type* type);
+  bool is_fully_defined_type(t_type* ttype);
+  void add_defined_type(t_type* ttype);
+  void init_known_types_list();
+  bool is_void(t_type* type);
+  int indent_impl_;
+  bool ansistr_binary_;
+  bool register_types_;
+  bool constprefix_;
+  bool events_;
+  bool xmldoc_;
+  void indent_up_impl() { ++indent_impl_; };
+  void indent_down_impl() { --indent_impl_; };
+  std::string indent_impl() {
+    std::string ind = "";
+    int i;
+    for (i = 0; i < indent_impl_; ++i) {
+      ind += "  ";
+    }
+    return ind;
+  };
+  std::ostream& indent_impl(std::ostream& os) { return os << indent_impl(); };
+};
+
+string t_delphi_generator::replace_all(string contents, string search, string repl) {
+  string str(contents);
+
+  size_t slen = search.length();
+  size_t rlen = repl.length();
+  size_t incr = (rlen > 0) ? rlen : 1;
+
+  if (slen > 0) {
+    size_t found = str.find(search);
+    while ((found != string::npos) && (found < str.length())) {
+      str.replace(found, slen, repl);
+      found = str.find(search, found + incr);
+    }
+  }
+
+  return str;
+}
+
+// XML encoding
+string t_delphi_generator::xml_encode(string contents) {
+  string str(contents);
+
+  // escape the escape
+  str = replace_all(str, "&", "&amp;");
+
+  // other standard XML entities
+  str = replace_all(str, "<", "&lt;");
+  str = replace_all(str, ">", "&gt;");
+
+  return str;
+}
+
+// XML attribute encoding
+string t_delphi_generator::xmlattrib_encode(string contents) {
+  string str(xml_encode(contents));
+
+  // our attribs are enclosed in "
+  str = replace_all(str, "\"", "\\\"");
+
+  return str;
+}
+
+// XML encoding for doc comments
+string t_delphi_generator::xmldoc_encode(string contents) {
+  string str(xml_encode(contents));
+
+  // XMLDoc specific: convert linebreaks into <para>graphs</para>
+  str = replace_all(str, "\r\n", "\r");
+  str = replace_all(str, "\n", "\r");
+  str = replace_all(str, "\r", "</para>\n<para>");
+
+  return str;
+}
+
+void t_delphi_generator::generate_delphi_docstring_comment(ostream& out, string contents) {
+  if (xmldoc_) {
+    generate_docstring_comment(out,
+                               "{$REGION 'XMLDoc'}/// <summary>\n",
+                               "/// ",
+                               "<para>" + contents + "</para>",
+                               "/// </summary>\n{$ENDREGION}\n");
+  }
+}
+
+void t_delphi_generator::generate_delphi_doc(ostream& out, t_field* field) {
+  if (xmldoc_) {
+    if (field->get_type()->is_enum()) {
+      string combined_message = xmldoc_encode(field->get_doc()) + "\n<seealso cref=\""
+                                + xmldoc_encode(type_name(field->get_type())) + "\"/>";
+      generate_delphi_docstring_comment(out, combined_message);
+    } else {
+      generate_delphi_doc(out, (t_doc*)field);
+    }
+  }
+}
+
+void t_delphi_generator::generate_delphi_doc(ostream& out, t_doc* tdoc) {
+  if (tdoc->has_doc() && xmldoc_) {
+    generate_delphi_docstring_comment(out, xmldoc_encode(tdoc->get_doc()));
+  }
+}
+
+void t_delphi_generator::generate_delphi_doc(ostream& out, t_function* tfunction) {
+  if (tfunction->has_doc() && xmldoc_) {
+    stringstream ps;
+    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+    vector<t_field*>::const_iterator p_iter;
+    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
+      t_field* p = *p_iter;
+      ps << "\n<param name=\"" << xmlattrib_encode(p->get_name()) << "\">";
+      if (p->has_doc()) {
+        std::string str = p->get_doc();
+        str.erase(std::remove(str.begin(), str.end(), '\n'),
+                  str.end()); // remove the newlines that appear from the parser
+        ps << xmldoc_encode(str);
+      }
+      ps << "</param>";
+    }
+    generate_docstring_comment(out,
+                               "{$REGION 'XMLDoc'}",
+                               "/// ",
+                               "<summary><para>" + xmldoc_encode(tfunction->get_doc())
+                               + "</para></summary>" + ps.str(),
+                               "{$ENDREGION}\n");
+  }
+}
+
+bool t_delphi_generator::find_keyword(std::map<std::string, int>& keyword_map, std::string name) {
+  std::string::size_type len = name.length();
+
+  if (len <= 0) {
+    return false;
+  }
+
+  std::string::size_type nlast = name.find_last_of('_');
+
+  if (nlast >= 1) {
+    if (nlast == (len - 1)) {
+      string new_name(name, 0, nlast);
+      return find_keyword(keyword_map, new_name);
+    }
+  }
+  return (keyword_map[name] == 1);
+}
+
+std::string t_delphi_generator::normalize_name(std::string name,
+                                               bool b_method,
+                                               bool b_exception_method) {
+  string tmp(name);
+  std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
+
+  bool b_found = false;
+
+  if (find_keyword(delphi_keywords, tmp)) {
+    b_found = true;
+  } else if (b_method && find_keyword(delphi_reserved_method, tmp)) {
+    b_found = true;
+  } else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) {
+    b_found = true;
+  }
+
+  if (b_found) {
+    return name + "_";
+  } else {
+    return name;
+  }
+}
+
+void t_delphi_generator::create_keywords() {
+  delphi_keywords["and"] = 1;
+  delphi_keywords["end"] = 1;
+  delphi_keywords["interface"] = 1;
+  delphi_keywords["raise"] = 1;
+  delphi_keywords["uses"] = 1;
+  delphi_keywords["array"] = 1;
+  delphi_keywords["except"] = 1;
+  delphi_keywords["is"] = 1;
+  delphi_keywords["record"] = 1;
+  delphi_keywords["var"] = 1;
+  delphi_keywords["as"] = 1;
+  delphi_keywords["exports"] = 1;
+  delphi_keywords["label"] = 1;
+  delphi_keywords["repeat"] = 1;
+  delphi_keywords["while"] = 1;
+  delphi_keywords["asm"] = 1;
+  delphi_keywords["file"] = 1;
+  delphi_keywords["library"] = 1;
+  delphi_keywords["resourcestring"] = 1;
+  delphi_keywords["with"] = 1;
+  delphi_keywords["begin"] = 1;
+  delphi_keywords["finalization"] = 1;
+  delphi_keywords["mod"] = 1;
+  delphi_keywords["set"] = 1;
+  delphi_keywords["xor"] = 1;
+  delphi_keywords["case"] = 1;
+  delphi_keywords["finally"] = 1;
+  delphi_keywords["nil"] = 1;
+  delphi_keywords["shl"] = 1;
+  delphi_keywords["class"] = 1;
+  delphi_keywords["for"] = 1;
+  delphi_keywords["not"] = 1;
+  delphi_keywords["shr"] = 1;
+  delphi_keywords["const"] = 1;
+  delphi_keywords["function"] = 1;
+  delphi_keywords["object"] = 1;
+  delphi_keywords["string"] = 1;
+  delphi_keywords["constructor"] = 1;
+  delphi_keywords["goto"] = 1;
+  delphi_keywords["of"] = 1;
+  delphi_keywords["then"] = 1;
+  delphi_keywords["destructor"] = 1;
+  delphi_keywords["if"] = 1;
+  delphi_keywords["or"] = 1;
+  delphi_keywords["threadvar"] = 1;
+  delphi_keywords["dispinterface"] = 1;
+  delphi_keywords["implementation"] = 1;
+  delphi_keywords["out"] = 1;
+  delphi_keywords["to"] = 1;
+  delphi_keywords["div"] = 1;
+  delphi_keywords["in"] = 1;
+  delphi_keywords["packed"] = 1;
+  delphi_keywords["try"] = 1;
+  delphi_keywords["do"] = 1;
+  delphi_keywords["inherited"] = 1;
+  delphi_keywords["procedure"] = 1;
+  delphi_keywords["type"] = 1;
+  delphi_keywords["downto"] = 1;
+  delphi_keywords["initialization"] = 1;
+  delphi_keywords["program"] = 1;
+  delphi_keywords["unit"] = 1;
+  delphi_keywords["else"] = 1;
+  delphi_keywords["inline"] = 1;
+  delphi_keywords["property"] = 1;
+  delphi_keywords["until"] = 1;
+  delphi_keywords["private"] = 1;
+  delphi_keywords["protected"] = 1;
+  delphi_keywords["public"] = 1;
+  delphi_keywords["published"] = 1;
+  delphi_keywords["automated"] = 1;
+  delphi_keywords["at"] = 1;
+  delphi_keywords["on"] = 1;
+
+  // reserved/predefined variables and types (lowercase!)
+  delphi_keywords["result"] = 1;
+  delphi_keywords["tbytes"] = 1;
+  delphi_keywords["tobject"] = 1;
+  delphi_keywords["tclass"] = 1;
+  delphi_keywords["tinterfacedobject"] = 1;
+
+  delphi_reserved_method["create"] = 1;
+  delphi_reserved_method["free"] = 1;
+  delphi_reserved_method["initinstance"] = 1;
+  delphi_reserved_method["cleanupinstance"] = 1;
+  delphi_reserved_method["classtype"] = 1;
+  delphi_reserved_method["classname"] = 1;
+  delphi_reserved_method["classnameis"] = 1;
+  delphi_reserved_method["classparent"] = 1;
+  delphi_reserved_method["classinfo"] = 1;
+  delphi_reserved_method["instancesize"] = 1;
+  delphi_reserved_method["inheritsfrom"] = 1;
+  delphi_reserved_method["methodaddress"] = 1;
+  delphi_reserved_method["methodaddress"] = 1;
+  delphi_reserved_method["methodname"] = 1;
+  delphi_reserved_method["fieldaddress"] = 1;
+  delphi_reserved_method["fieldaddress"] = 1;
+  delphi_reserved_method["getinterface"] = 1;
+  delphi_reserved_method["getinterfaceentry"] = 1;
+  delphi_reserved_method["getinterfacetable"] = 1;
+  delphi_reserved_method["unitname"] = 1;
+  delphi_reserved_method["equals"] = 1;
+  delphi_reserved_method["gethashcode"] = 1;
+  delphi_reserved_method["tostring"] = 1;
+  delphi_reserved_method["safecallexception"] = 1;
+  delphi_reserved_method["afterconstruction"] = 1;
+  delphi_reserved_method["beforedestruction"] = 1;
+  delphi_reserved_method["dispatch"] = 1;
+  delphi_reserved_method["defaulthandler"] = 1;
+  delphi_reserved_method["newinstance"] = 1;
+  delphi_reserved_method["freeinstance"] = 1;
+  delphi_reserved_method["destroy"] = 1;
+  delphi_reserved_method["read"] = 1;
+  delphi_reserved_method["write"] = 1;
+
+  delphi_reserved_method_exception["setinnerexception"] = 1;
+  delphi_reserved_method_exception["setstackinfo"] = 1;
+  delphi_reserved_method_exception["getstacktrace"] = 1;
+  delphi_reserved_method_exception["raisingexception"] = 1;
+  delphi_reserved_method_exception["createfmt"] = 1;
+  delphi_reserved_method_exception["createres"] = 1;
+  delphi_reserved_method_exception["createresfmt"] = 1;
+  delphi_reserved_method_exception["createhelp"] = 1;
+  delphi_reserved_method_exception["createfmthelp"] = 1;
+  delphi_reserved_method_exception["createreshelp"] = 1;
+  delphi_reserved_method_exception["createresfmthelp"] = 1;
+  delphi_reserved_method_exception["getbaseexception"] = 1;
+  delphi_reserved_method_exception["baseexception"] = 1;
+  delphi_reserved_method_exception["helpcontext"] = 1;
+  delphi_reserved_method_exception["innerexception"] = 1;
+  delphi_reserved_method_exception["message"] = 1;
+  delphi_reserved_method_exception["stacktrace"] = 1;
+  delphi_reserved_method_exception["stackinfo"] = 1;
+  delphi_reserved_method_exception["getexceptionstackinfoproc"] = 1;
+  delphi_reserved_method_exception["getstackinfostringproc"] = 1;
+  delphi_reserved_method_exception["cleanupstackinfoproc"] = 1;
+  delphi_reserved_method_exception["raiseouterexception"] = 1;
+  delphi_reserved_method_exception["throwouterexception"] = 1;
+}
+
+void t_delphi_generator::add_delphi_uses_list(string unitname) {
+  vector<std::string>::const_iterator s_iter;
+  bool found = false;
+  for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
+    if ((*s_iter) == unitname) {
+      found = true;
+      break;
+    }
+  }
+  if (!found) {
+    uses_list.push_back(unitname);
+  }
+}
+
+void t_delphi_generator::init_generator() {
+  indent_impl_ = 0;
+  namespace_name_ = program_->get_namespace("delphi");
+  has_forward = false;
+  has_enum = false;
+  has_const = false;
+  create_keywords();
+  add_delphi_uses_list("Classes");
+  add_delphi_uses_list("SysUtils");
+  add_delphi_uses_list("Generics.Collections");
+  add_delphi_uses_list("Thrift");
+  add_delphi_uses_list("Thrift.Utils");
+  add_delphi_uses_list("Thrift.Collections");
+  add_delphi_uses_list("Thrift.Protocol");
+  add_delphi_uses_list("Thrift.Transport");
+
+  if (register_types_) {
+    add_delphi_uses_list("Thrift.TypeRegistry");
+  }
+
+  init_known_types_list();
+
+  string unitname, nsname;
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    unitname = includes[i]->get_name();
+    nsname = includes[i]->get_namespace("delphi");
+    if ("" != nsname) {
+      unitname = nsname;
+    }
+    add_delphi_uses_list(unitname);
+  }
+
+  MKDIR(get_out_dir().c_str());
+}
+
+void t_delphi_generator::close_generator() {
+  std::string unitname = program_name_;
+  if ("" != namespace_name_) {
+    unitname = namespace_name_;
+  }
+
+  for (int i = 0; i < (int)unitname.size(); i++) {
+    if (unitname[i] == ' ') {
+      unitname.replace(i, 1, "_");
+    }
+  }
+
+  std::string f_name = get_out_dir() + "/" + unitname + ".pas";
+  std::ofstream f_all;
+
+  f_all.open(f_name.c_str());
+
+  f_all << autogen_comment() << endl;
+  generate_delphi_doc(f_all, program_);
+  f_all << "unit " << unitname << ";" << endl << endl;
+  f_all << "interface" << endl << endl;
+  f_all << "uses" << endl;
+
+  indent_up();
+
+  vector<std::string>::const_iterator s_iter;
+  for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
+    if (s_iter != uses_list.begin()) {
+      f_all << ",";
+      f_all << endl;
+    }
+    indent(f_all) << *s_iter;
+  }
+
+  f_all << ";" << endl << endl;
+
+  indent_down();
+
+  string tmp_unit(unitname);
+  for (int i = 0; i < (int)tmp_unit.size(); i++) {
+    if (tmp_unit[i] == '.') {
+      tmp_unit.replace(i, 1, "_");
+    }
+  }
+
+  f_all << "const" << endl;
+  indent_up();
+  indent(f_all) << "c" << tmp_unit
+                << "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";"
+                << endl;
+  indent(f_all) << "c" << tmp_unit
+                << "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";"
+                << endl;
+  indent(f_all) << "c" << tmp_unit
+                << "_Option_ConstPrefix    = " << (constprefix_ ? "True" : "False") << ";" << endl;
+  indent(f_all) << "c" << tmp_unit << "_Option_Events         = " << (events_ ? "True" : "False")
+                << ";" << endl;
+  indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc         = " << (xmldoc_ ? "True" : "False")
+                << ";" << endl;
+  indent_down();
+
+  f_all << endl;
+  f_all << "type" << endl;
+  if (has_forward) {
+    f_all << s_forward_decr.str() << endl;
+  }
+  if (has_enum) {
+    indent(f_all) << endl;
+    indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl;
+    f_all << s_enum.str();
+    indent(f_all) << "{$SCOPEDENUMS OFF}" << endl << endl;
+  }
+  f_all << s_struct.str();
+  f_all << s_service.str();
+  f_all << s_const.str();
+  f_all << "implementation" << endl << endl;
+  f_all << s_struct_impl.str();
+  f_all << s_service_impl.str();
+  f_all << s_const_impl.str();
+
+  if (register_types_) {
+    f_all << endl;
+    f_all << "// Type factory methods and registration" << endl;
+    f_all << s_type_factory_funcs.str();
+    f_all << "procedure RegisterTypeFactories;" << endl;
+    f_all << "begin" << endl;
+    f_all << s_type_factory_registration.str();
+    f_all << "end;" << endl;
+  }
+  f_all << endl;
+
+  string constants_class = make_constants_classname();
+
+  f_all << "initialization" << endl;
+  if (has_const) {
+    f_all << "{$IF CompilerVersion < 21.0}  // D2010" << endl;
+    f_all << "  " << constants_class.c_str() << "_Initialize;" << endl;
+    f_all << "{$IFEND}" << endl;
+  }
+  if (register_types_) {
+    f_all << "  RegisterTypeFactories;" << endl;
+  }
+  f_all << endl;
+
+  f_all << "finalization" << endl;
+  if (has_const) {
+    f_all << "{$IF CompilerVersion < 21.0}  // D2010" << endl;
+    f_all << "  " << constants_class.c_str() << "_Finalize;" << endl;
+    f_all << "{$IFEND}" << endl;
+  }
+  f_all << endl << endl;
+
+  f_all << "end." << endl;
+  f_all.close();
+
+  if (!typedefs_pending.empty()) {
+    pwarning(0, "%d typedefs with unresolved type references left:\n", typedefs_pending.size());
+    for (std::list<t_typedef*>::iterator iter = typedefs_pending.begin();
+         typedefs_pending.end() != iter;
+         ++iter) {
+      pwarning(0, "- %s\n", (*iter)->get_symbolic().c_str());
+    }
+  }
+}
+
+void t_delphi_generator::delphi_type_usings(ostream& out) {
+  indent_up();
+  indent(out) << "Classes, SysUtils, Generics.Collections, Thrift.Collections, Thrift.Protocol,"
+              << endl;
+  indent(out) << "Thrift.Transport;" << endl << endl;
+  indent_down();
+}
+
+void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) {
+  // Forward declare struct def
+  has_forward = true;
+  pverbose("forward declaration of %s\n", type_name(tstruct).c_str());
+
+  string what = tstruct->is_xception() ? "class" : "interface";
+
+  indent_up();
+  indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";"
+                         << endl;
+  indent_down();
+
+  add_defined_type(tstruct);
+}
+
+void t_delphi_generator::generate_typedef(t_typedef* ttypedef) {
+  t_type* type = ttypedef->get_type();
+
+  // write now or save for later?
+  if (!is_fully_defined_type(type)) {
+    pverbose("typedef %s: unresolved dependencies found\n", type_name(ttypedef).c_str());
+    typedefs_pending.push_back(ttypedef);
+    return;
+  }
+
+  indent_up();
+  generate_delphi_doc(s_struct, ttypedef);
+  indent(s_struct) << type_name(ttypedef) << " = ";
+
+  // commented out: the benefit is not big enough to risk breaking existing code
+  // bool container = type->is_list() || type->is_map() || type->is_set();
+  // if( ! container)
+  //  s_struct << "type ";  //the "type A = type B" syntax leads to E2574 with generics
+
+  s_struct << type_name(ttypedef->get_type()) << ";" << endl << endl;
+  indent_down();
+
+  add_defined_type(ttypedef);
+}
+
+bool t_delphi_generator::is_fully_defined_type(t_type* ttype) {
+  if ((NULL != ttype->get_program()) && (ttype->get_program() != program_)) {
+    t_scope* scope = ttype->get_program()->scope();
+    if (NULL != scope->get_type(ttype->get_name())) {
+      // printf("type %s found in included scope %s\n", ttype->get_name().c_str(),
+      // ttype->get_program()->get_name().c_str());
+      return true;
+    }
+  }
+
+  if (ttype->is_typedef()) {
+    return (1 == types_known[type_name(ttype)]);
+  }
+
+  if (ttype->is_base_type()) {
+    return (1 == types_known[base_type_name((t_base_type*)ttype)]);
+  } else if (ttype->is_enum()) {
+    return true; // enums are written first, before all other types
+  } else if (ttype->is_map()) {
+    t_map* tmap = (t_map*)ttype;
+    return is_fully_defined_type(tmap->get_key_type())
+           && is_fully_defined_type(tmap->get_val_type());
+  } else if (ttype->is_set()) {
+    t_set* tset = (t_set*)ttype;
+    return is_fully_defined_type(tset->get_elem_type());
+  } else if (ttype->is_list()) {
+    t_list* tlist = (t_list*)ttype;
+    return is_fully_defined_type(tlist->get_elem_type());
+  }
+
+  return (1 == types_known[type_name(ttype)]);
+}
+
+void t_delphi_generator::add_defined_type(t_type* ttype) {
+  // mark as known type
+  types_known[type_name(ttype)] = 1;
+
+  // check all pending typedefs
+  std::list<t_typedef*>::iterator iter;
+  bool more = true;
+  while (more && (!typedefs_pending.empty())) {
+    more = false;
+
+    for (iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) {
+      t_typedef* ttypedef = (*iter);
+      if (is_fully_defined_type(ttypedef->get_type())) {
+        pverbose("typedef %s: all pending references are now resolved\n",
+                 type_name(ttypedef).c_str());
+        typedefs_pending.erase(iter);
+        generate_typedef(ttypedef);
+        more = true;
+        break;
+      }
+    }
+  }
+}
+
+void t_delphi_generator::init_known_types_list() {
+  // known base types
+  types_known[type_name(g_type_string)] = 1;
+  types_known[type_name(g_type_binary)] = 1;
+  types_known[type_name(g_type_bool)] = 1;
+  types_known[type_name(g_type_i8)] = 1;
+  types_known[type_name(g_type_i16)] = 1;
+  types_known[type_name(g_type_i32)] = 1;
+  types_known[type_name(g_type_i64)] = 1;
+  types_known[type_name(g_type_double)] = 1;
+}
+
+void t_delphi_generator::generate_enum(t_enum* tenum) {
+  has_enum = true;
+  indent_up();
+  generate_delphi_doc(s_enum, tenum);
+  indent(s_enum) << type_name(tenum, true, true) << " = "
+                 << "(" << endl;
+  indent_up();
+  vector<t_enum_value*> constants = tenum->get_constants();
+  if (constants.empty()) {
+    indent(s_enum) << "dummy = 0  // empty enums are not allowed";
+  } else {
+    vector<t_enum_value*>::iterator c_iter;
+    for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+      int value = (*c_iter)->get_value();
+      if (c_iter != constants.begin()) {
+        s_enum << ",";
+        s_enum << endl;
+      }
+      generate_delphi_doc(s_enum, *c_iter);
+      indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value;
+    }
+  }
+  s_enum << endl;
+  indent_down();
+  indent(s_enum) << ");" << endl << endl;
+  indent_down();
+}
+
+std::string t_delphi_generator::make_valid_delphi_identifier(std::string const& fromName) {
+  std::string str = fromName;
+  if (str.empty()) {
+    return str;
+  }
+
+  // tests rely on this
+  assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
+
+  // if the first letter is a number, we add an additional underscore in front of it
+  char c = str.at(0);
+  if (('0' <= c) && (c <= '9')) {
+    str = "_" + str;
+  }
+
+  // following chars: letter, number or underscore
+  for (size_t i = 0; i < str.size(); ++i) {
+    c = str.at(i);
+    if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9'))
+        && ('_' != c)) {
+      str.replace(i, 1, "_");
+    }
+  }
+
+  return str;
+}
+
+std::string t_delphi_generator::make_constants_classname() {
+  if (constprefix_) {
+    return make_valid_delphi_identifier("T" + program_name_ + "Constants");
+  } else {
+    return "TConstants"; // compatibility
+  }
+}
+
+void t_delphi_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  has_const = true;
+  string constants_class = make_constants_classname();
+
+  indent_up();
+  indent(s_const) << constants_class.c_str() << " = class" << endl;
+  indent(s_const) << "private" << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    if (const_needs_var((*c_iter)->get_type())) {
+      print_private_field(s_const,
+                          normalize_name((*c_iter)->get_name()),
+                          (*c_iter)->get_type(),
+                          (*c_iter)->get_value());
+    }
+  }
+  indent_down();
+  indent(s_const) << "public" << endl;
+  indent_up();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    generate_delphi_doc(s_const, *c_iter);
+    print_const_prop(s_const,
+                     normalize_name((*c_iter)->get_name()),
+                     (*c_iter)->get_type(),
+                     (*c_iter)->get_value());
+  }
+  indent(s_const) << "{$IF CompilerVersion >= 21.0}" << endl;
+  indent(s_const) << "class constructor Create;" << endl;
+  indent(s_const) << "class destructor Destroy;" << endl;
+  indent(s_const) << "{$IFEND}" << endl;
+  indent_down();
+  indent(s_const) << "end;" << endl << endl;
+  indent_down();
+
+  std::ostringstream vars, code;
+
+  indent_up_impl();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    initialize_field(vars,
+                     code,
+                     "F" + prop_name((*c_iter)->get_name()),
+                     (*c_iter)->get_type(),
+                     (*c_iter)->get_value());
+  }
+  indent_down_impl();
+
+  indent_impl(s_const_impl) << "{$IF CompilerVersion >= 21.0}" << endl;
+  indent_impl(s_const_impl) << "class constructor " << constants_class.c_str() << ".Create;"
+                            << endl;
+
+  if (!vars.str().empty()) {
+    indent_impl(s_const_impl) << "var" << endl;
+    s_const_impl << vars.str();
+  }
+  indent_impl(s_const_impl) << "begin" << endl;
+  if (!code.str().empty()) {
+    s_const_impl << code.str();
+  }
+  indent_impl(s_const_impl) << "end;" << endl << endl;
+  indent_impl(s_const_impl) << "class destructor " << constants_class.c_str() << ".Destroy;"
+                            << endl;
+  indent_impl(s_const_impl) << "begin" << endl;
+  indent_up_impl();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    if (const_needs_var((*c_iter)->get_type())) {
+      finalize_field(s_const_impl,
+                     normalize_name((*c_iter)->get_name()),
+                     (*c_iter)->get_type(),
+                     (*c_iter)->get_value());
+    }
+  }
+  indent_impl(s_const_impl) << "inherited;" << endl;
+  indent_down_impl();
+  indent_impl(s_const_impl) << "end;" << endl;
+  indent_impl(s_const_impl) << "{$ELSE}" << endl;
+
+  vars.str("");
+  code.str("");
+
+  indent_up_impl();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    if (const_needs_var((*c_iter)->get_type())) {
+      initialize_field(vars,
+                       code,
+                       constants_class + ".F" + prop_name((*c_iter)->get_name()),
+                       (*c_iter)->get_type(),
+                       (*c_iter)->get_value());
+    }
+  }
+  indent_down_impl();
+
+  indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Initialize;" << endl;
+  if (!vars.str().empty()) {
+    indent_impl(s_const_impl) << "var" << endl;
+    s_const_impl << vars.str();
+  }
+  indent_impl(s_const_impl) << "begin" << endl;
+  if (!code.str().empty()) {
+    s_const_impl << code.str();
+  }
+  indent_impl(s_const_impl) << "end;" << endl << endl;
+
+  indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Finalize;" << endl;
+  indent_impl(s_const_impl) << "begin" << endl;
+  indent_up_impl();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    finalize_field(s_const_impl,
+                   normalize_name((*c_iter)->get_name()),
+                   (*c_iter)->get_type(),
+                   (*c_iter)->get_value(),
+                   constants_class);
+  }
+  indent_down_impl();
+  indent_impl(s_const_impl) << "end;" << endl;
+  indent_impl(s_const_impl) << "{$IFEND}" << endl << endl;
+}
+
+void t_delphi_generator::print_const_def_value(std::ostream& vars,
+                                               std::ostream& out,
+                                               string name,
+                                               t_type* type,
+                                               t_const_value* value,
+                                               string cls_nm) {
+
+  string cls_prefix;
+
+  if (cls_nm == "") {
+    cls_prefix = "";
+  } else {
+    cls_prefix = cls_nm + ".";
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(vars, out, name, field_type, v_iter->second);
+      indent_impl(out) << cls_prefix << normalize_name(name) << "."
+                       << prop_name(v_iter->first->get_string(), type->is_xception())
+                       << " := " << val << ";" << endl;
+    }
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(vars, out, name, ktype, v_iter->first);
+      string val = render_const_value(vars, out, name, vtype, v_iter->second);
+      indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]"
+                       << " := " << val << ";" << endl;
+    }
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(vars, out, name, etype, *v_iter);
+      indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << endl;
+    }
+  }
+}
+
+void t_delphi_generator::print_private_field(std::ostream& out,
+                                             string name,
+                                             t_type* type,
+                                             t_const_value* value) {
+  (void)value;
+  indent(out) << "class var F" << name << ": " << type_name(type) << ";" << endl;
+}
+
+bool t_delphi_generator::const_needs_var(t_type* type) {
+  t_type* truetype = type;
+  while (truetype->is_typedef()) {
+    truetype = ((t_typedef*)truetype)->get_type();
+  }
+  return (!truetype->is_base_type());
+}
+
+void t_delphi_generator::print_const_prop(std::ostream& out,
+                                          string name,
+                                          t_type* type,
+                                          t_const_value* value) {
+  (void)value;
+  if (const_needs_var(type)) {
+    indent(out) << "class property " << name << ": " << type_name(type) << " read F" << name << ";"
+                << endl;
+  } else {
+    std::ostringstream vars; // dummy
+    string v2 = render_const_value(vars, out, name, type, value);
+    indent(out) << "const " << name << " = " << v2 << ";" << endl;
+  }
+}
+
+void t_delphi_generator::print_const_value(std::ostream& vars,
+                                           std::ostream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value) {
+  t_type* truetype = type;
+  while (truetype->is_typedef()) {
+    truetype = ((t_typedef*)truetype)->get_type();
+  }
+
+  if (truetype->is_base_type()) {
+    // already done
+    // string v2 = render_const_value( vars, out, name, type, value);
+    // indent_impl(out) << name << " := " << v2 << ";" << endl;
+  } else if (truetype->is_enum()) {
+    indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name()
+                     << ";" << endl;
+  } else {
+    string typname;
+    typname = type_name(truetype, true, false, type->is_xception(), type->is_xception());
+    indent_impl(out) << name << " := " << typname << ".Create;" << endl;
+    print_const_def_value(vars, out, name, truetype, value);
+  }
+}
+
+void t_delphi_generator::initialize_field(std::ostream& vars,
+                                          std::ostream& out,
+                                          string name,
+                                          t_type* type,
+                                          t_const_value* value) {
+  print_const_value(vars, out, name, type, value);
+}
+
+void t_delphi_generator::finalize_field(std::ostream& out,
+                                        string name,
+                                        t_type* type,
+                                        t_const_value* value,
+                                        string cls_nm) {
+  (void)out;
+  (void)name;
+  (void)type;
+  (void)value;
+  (void)cls_nm;
+}
+
+string t_delphi_generator::render_const_value(ostream& vars,
+                                              ostream& out,
+                                              string name,
+                                              t_type* type,
+                                              t_const_value* value) {
+  (void)name;
+
+  t_type* truetype = type;
+  while (truetype->is_typedef()) {
+    truetype = ((t_typedef*)truetype)->get_type();
+  }
+
+  std::ostringstream render;
+
+  if (truetype->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << "'" << get_escaped_string(value) << "'";
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "True" : "False");
+      break;
+    case t_base_type::TYPE_I8:
+      render << "ShortInt( " << value->get_integer() << ")";
+      break;
+    case t_base_type::TYPE_I16:
+      render << "SmallInt( " << value->get_integer() << ")";
+      break;
+    case t_base_type::TYPE_I32:
+      render << "LongInt( " << value->get_integer() << ")";
+      break;
+    case t_base_type::TYPE_I64:
+      render << "Int64( " << value->get_integer() << ")";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer() << ".0"; // make it a double constant by adding ".0"
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (truetype->is_enum()) {
+    render << type_name(type, false) << "." << value->get_identifier_name();
+  } else {
+    string t = tmp("tmp");
+    vars << "  " << t << " : " << type_name(type) << ";" << endl;
+    print_const_value(vars, out, t, type, value);
+    render << t;
+  }
+
+  return render.str();
+}
+
+void t_delphi_generator::generate_struct(t_struct* tstruct) {
+  generate_delphi_struct(tstruct, false);
+}
+
+void t_delphi_generator::generate_xception(t_struct* txception) {
+  generate_delphi_struct(txception, true);
+}
+
+void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) {
+  indent_up();
+  generate_delphi_struct_definition(s_struct, tstruct, is_exception);
+  indent_down();
+
+  add_defined_type(tstruct);
+
+  generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception);
+  if (register_types_) {
+    generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception);
+    generate_delphi_struct_type_factory_registration(s_type_factory_registration,
+                                                     "",
+                                                     tstruct,
+                                                     is_exception);
+  }
+}
+
+void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
+                                                     string cls_prefix,
+                                                     t_struct* tstruct,
+                                                     bool is_exception,
+                                                     bool is_result,
+                                                     bool is_x_factory) {
+
+  if (is_exception && (!is_x_factory)) {
+    generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true);
+  }
+
+  string cls_nm;
+
+  string exception_factory_name;
+
+  if (is_exception) {
+    exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
+  }
+
+  if (is_exception) {
+    cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
+  } else {
+    cls_nm = type_name(tstruct, true, false);
+  }
+
+  std::ostringstream vars, code;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  indent_up_impl();
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = (*m_iter)->get_type();
+    while (t->is_typedef()) {
+      t = ((t_typedef*)t)->get_type();
+    }
+    if ((*m_iter)->get_value() != NULL) {
+      initialize_field(vars,
+                       code,
+                       "F" + prop_name((*m_iter)->get_name(), is_exception),
+                       t,
+                       (*m_iter)->get_value());
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;"
+                          << endl;
+      }
+    }
+  }
+  indent_down_impl();
+
+  indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
+                   << "Create;" << endl;
+
+  if (!vars.str().empty()) {
+    out << "var" << endl;
+    out << vars.str();
+  }
+
+  indent_impl(out) << "begin" << endl;
+  indent_up_impl();
+  if (is_exception && (!is_x_factory)) {
+    indent_impl(out) << "inherited Create('');" << endl;
+    indent_impl(out) << "F" << exception_factory_name << " := T" << exception_factory_name
+                     << "Impl.Create;" << endl;
+  } else {
+    indent_impl(out) << "inherited;" << endl;
+  }
+
+  if (!code.str().empty()) {
+    out << code.str();
+  }
+
+  indent_down_impl();
+  indent_impl(out) << "end;" << endl << endl;
+
+  if ((members.size() > 0) && is_exception && (!is_x_factory)) {
+    indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
+                     << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");"
+                     << endl;
+    indent_impl(out) << "begin" << endl;
+    indent_up_impl();
+    indent_impl(out) << "Create;" << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      string propname = prop_name((*m_iter)->get_name(), is_exception);
+      string param_name = constructor_param_name((*m_iter)->get_name());
+      indent_impl(out) << propname << " := " << param_name << ";" << endl;
+    }
+    indent_impl(out) << "UpdateMessageProperty;" << endl;
+    indent_down_impl();
+    indent_impl(out) << "end;" << endl << endl;
+  }
+
+  indent_impl(out) << "destructor " << cls_prefix << cls_nm << "."
+                   << "Destroy;" << endl;
+  indent_impl(out) << "begin" << endl;
+  indent_up_impl();
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = (*m_iter)->get_type();
+    while (t->is_typedef()) {
+      t = ((t_typedef*)t)->get_type();
+    }
+    finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value());
+  }
+
+  indent_impl(out) << "inherited;" << endl;
+  indent_down_impl();
+  indent_impl(out) << "end;" << endl << endl;
+
+  if (tstruct->is_union()) {
+    indent_impl(out) << "procedure " << cls_prefix << cls_nm << "."
+                     << "ClearUnionValues;" << endl;
+    indent_impl(out) << "begin" << endl;
+    indent_up_impl();
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = (*m_iter)->get_type();
+      while (t->is_typedef()) {
+        t = ((t_typedef*)t)->get_type();
+      }
+
+      generate_delphi_clear_union_value(out,
+                                        cls_prefix,
+                                        cls_nm,
+                                        t,
+                                        *m_iter,
+                                        "F",
+                                        is_exception,
+                                        tstruct->is_union(),
+                                        is_x_factory,
+                                        exception_factory_name);
+    }
+    indent_down_impl();
+    indent_impl(out) << "end;" << endl << endl;
+  }
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = (*m_iter)->get_type();
+    while (t->is_typedef()) {
+      t = ((t_typedef*)t)->get_type();
+    }
+    generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
+    generate_delphi_property_writer_impl(out,
+                                         cls_prefix,
+                                         cls_nm,
+                                         t,
+                                         *m_iter,
+                                         "F",
+                                         is_exception,
+                                         tstruct->is_union(),
+                                         is_x_factory,
+                                         exception_factory_name);
+    if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+      generate_delphi_isset_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
+    }
+  }
+
+  if ((!is_exception) || is_x_factory) {
+    generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception);
+    if (is_result) {
+      generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception);
+    } else {
+      generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception);
+    }
+  }
+  generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
+
+  if (is_exception && is_x_factory) {
+    generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception);
+  }
+}
+
+void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) {
+  string struct_intf_name = type_name(tstruct);
+  out << "Create_";
+  out << struct_intf_name;
+  out << "_Impl";
+}
+
+void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out,
+                                                             string cls_prefix,
+                                                             t_struct* tstruct,
+                                                             bool is_exception,
+                                                             bool is_result,
+                                                             bool is_x_factory) {
+  (void)cls_prefix;
+  if (is_exception)
+    return;
+  if (is_result)
+    return;
+  if (is_x_factory)
+    return;
+
+  string struct_intf_name = type_name(tstruct);
+  string cls_nm = type_name(tstruct, true, false);
+
+  out << "function ";
+  print_delphi_struct_type_factory_func(out, tstruct);
+  out << ": ";
+  out << struct_intf_name;
+  out << ";" << endl;
+  out << "begin" << endl;
+  indent_up();
+  indent(out) << "Result := " << cls_nm << ".Create;" << endl;
+  indent_down();
+  out << "end;" << endl << endl;
+}
+
+void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out,
+                                                                          string cls_prefix,
+                                                                          t_struct* tstruct,
+                                                                          bool is_exception,
+                                                                          bool is_result,
+                                                                          bool is_x_factory) {
+  (void)cls_prefix;
+  if (is_exception)
+    return;
+  if (is_result)
+    return;
+  if (is_x_factory)
+    return;
+
+  string struct_intf_name = type_name(tstruct);
+
+  indent(out) << "  TypeRegistry.RegisterTypeFactory<" << struct_intf_name << ">(";
+  print_delphi_struct_type_factory_func(out, tstruct);
+  out << ");";
+  out << endl;
+}
+
+void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
+                                                           t_struct* tstruct,
+                                                           bool is_exception,
+                                                           bool in_class,
+                                                           bool is_result,
+                                                           bool is_x_factory) {
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+  string struct_intf_name;
+  string struct_name;
+  string isset_name;
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
+
+  if (is_exception) {
+    struct_intf_name = type_name(tstruct, false, false, true);
+  } else {
+    struct_intf_name = type_name(tstruct);
+  }
+
+  if (is_exception) {
+    struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory);
+  } else {
+    struct_name = type_name(tstruct, true);
+  }
+
+  if ((!is_exception) || is_x_factory) {
+
+    generate_delphi_doc(out, tstruct);
+    indent(out) << struct_intf_name << " = interface(IBase)" << endl;
+    indent_up();
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      generate_delphi_property_reader_definition(out, *m_iter, is_exception);
+      generate_delphi_property_writer_definition(out, *m_iter, is_exception);
+    }
+
+    if (is_x_factory) {
+      out << endl;
+      indent(out) << "// Create Exception Object" << endl;
+      indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl;
+    }
+
+    if (members.size() > 0) {
+      out << endl;
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        generate_property(out, *m_iter, true, is_exception);
+      }
+    }
+
+    if (members.size() > 0) {
+      out << endl;
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+          generate_delphi_isset_reader_definition(out, *m_iter, is_exception);
+        }
+      }
+    }
+
+    if (members.size() > 0) {
+      out << endl;
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+          isset_name = "__isset_" + prop_name(*m_iter, is_exception);
+          indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";"
+                      << endl;
+        }
+      }
+    }
+
+    indent_down();
+    indent(out) << "end;" << endl << endl;
+  }
+
+  generate_delphi_doc(out, tstruct);
+  indent(out) << struct_name << " = ";
+  if (is_final) {
+    out << "sealed ";
+  }
+  out << "class(";
+  if (is_exception && (!is_x_factory)) {
+    out << "TException";
+  } else {
+    out << "TInterfacedObject, IBase, " << struct_intf_name;
+  }
+  out << ")" << endl;
+
+  if (is_exception && (!is_x_factory)) {
+    indent(out) << "public" << endl;
+    indent_up();
+    indent(out) << "type" << endl;
+    indent_up();
+    generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true);
+    indent_down();
+    indent_down();
+  }
+
+  indent(out) << "private" << endl;
+  indent_up();
+
+  if (is_exception && (!is_x_factory)) {
+    indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << endl << endl;
+  }
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << declare_field(*m_iter, false, "F", is_exception) << endl;
+  }
+
+  if (members.size() > 0) {
+    indent(out) << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        isset_name = "F__isset_" + prop_name(*m_iter, is_exception);
+        indent(out) << isset_name << ": Boolean;" << endl;
+      }
+    }
+  }
+
+  indent(out) << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_delphi_property_reader_definition(out, *m_iter, is_exception);
+    generate_delphi_property_writer_definition(out, *m_iter, is_exception);
+  }
+
+  if (tstruct->is_union()) {
+    out << endl;
+    indent(out) << "// Clear values(for union's property setter)" << endl;
+    indent(out) << "procedure ClearUnionValues;" << endl;
+  }
+
+  if (members.size() > 0) {
+    out << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        isset_name = "__isset_" + prop_name(*m_iter, is_exception);
+        indent(out) << "function Get" << isset_name << ": Boolean;" << endl;
+      }
+    }
+  }
+
+  indent_down();
+
+  indent(out) << "public" << endl;
+  indent_up();
+
+  if ((members.size() > 0) && is_exception && (!is_x_factory)) {
+    indent(out) << "constructor Create; overload;" << endl;
+    indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent())
+                << "); overload;" << endl;
+  } else {
+    indent(out) << "constructor Create;" << endl;
+  }
+
+  indent(out) << "destructor Destroy; override;" << endl;
+
+  out << endl;
+  indent(out) << "function ToString: string; override;" << endl;
+
+  if (is_exception && (!is_x_factory)) {
+    out << endl;
+    indent(out) << "// Exception Factory" << endl;
+    indent(out) << "property " << exception_factory_name << ": " << struct_intf_name << " read F"
+                << exception_factory_name << " write F" << exception_factory_name << ";" << endl;
+  }
+
+  if ((!is_exception) || is_x_factory) {
+    out << endl;
+    indent(out) << "// IBase" << endl;
+    indent(out) << "procedure Read( const iprot: IProtocol);" << endl;
+    indent(out) << "procedure Write( const oprot: IProtocol);" << endl;
+  }
+
+  if (is_exception && is_x_factory) {
+    out << endl;
+    indent(out) << "// Create Exception Object" << endl;
+    indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl;
+  }
+
+  if (members.size() > 0) {
+    out << endl;
+    indent(out) << "// Properties" << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      generate_property(out, *m_iter, true, is_exception);
+    }
+  }
+
+  if (members.size() > 0) {
+    out << endl;
+    indent(out) << "// isset" << endl;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        isset_name = "__isset_" + prop_name(*m_iter, is_exception);
+        indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";"
+                    << endl;
+      }
+    }
+  }
+
+  indent_down();
+  indent(out) << "end;" << endl << endl;
+}
+
+void t_delphi_generator::generate_service(t_service* tservice) {
+  indent_up();
+  generate_delphi_doc(s_service, tservice);
+  indent(s_service) << normalize_clsnm(service_name_, "T") << " = class" << endl;
+  indent(s_service) << "public" << endl;
+  indent_up();
+  indent(s_service) << "type" << endl;
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+  indent_down();
+  indent_down();
+  indent(s_service) << "end;" << endl;
+  indent(s_service) << endl;
+  indent_down();
+}
+
+void t_delphi_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+
+  indent_up();
+
+  generate_delphi_doc(s_service, tservice);
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends(), true, true);
+    extends_iface = extends + ".Iface";
+    generate_delphi_doc(s_service, tservice);
+    indent(s_service) << "Iface = interface(" << extends_iface << ")" << endl;
+  } else {
+    indent(s_service) << "Iface = interface" << endl;
+  }
+
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_delphi_doc(s_service, *f_iter);
+    indent(s_service) << function_signature(*f_iter) << endl;
+  }
+  indent_down();
+  indent(s_service) << "end;" << endl << endl;
+
+  indent_down();
+}
+
+void t_delphi_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_delphi_struct_definition(s_service, ts, false, true);
+    generate_delphi_struct_impl(s_service_impl,
+                                normalize_clsnm(service_name_, "T") + ".",
+                                ts,
+                                false);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+void t_delphi_generator::generate_service_client(t_service* tservice) {
+  indent_up();
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = extends + ".Client, ";
+  }
+
+  generate_delphi_doc(s_service, tservice);
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends(), true, true);
+    extends_client = extends + ".TClient";
+    indent(s_service) << "TClient = class(" << extends_client << ", Iface)" << endl;
+  } else {
+    indent(s_service) << "TClient = class( TInterfacedObject, Iface)" << endl;
+  }
+
+  indent(s_service) << "public" << endl;
+  indent_up();
+
+  indent(s_service) << "constructor Create( prot: IProtocol); overload;" << endl;
+
+  indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T")
+                              << ".TClient.Create( prot: IProtocol);" << endl;
+  indent_impl(s_service_impl) << "begin" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "Create( prot, prot );" << endl;
+  indent_down_impl();
+  indent_impl(s_service_impl) << "end;" << endl << endl;
+
+  indent(s_service)
+      << "constructor Create( const iprot: IProtocol; const oprot: IProtocol); overload;" << endl;
+
+  indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T")
+                              << ".TClient.Create( const iprot: IProtocol; const oprot: IProtocol);"
+                              << endl;
+  indent_impl(s_service_impl) << "begin" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "inherited Create;" << endl;
+  indent_impl(s_service_impl) << "iprot_ := iprot;" << endl;
+  indent_impl(s_service_impl) << "oprot_ := oprot;" << endl;
+  indent_down_impl();
+  indent_impl(s_service_impl) << "end;" << endl << endl;
+
+  indent_down();
+
+  if (extends.empty()) {
+    indent(s_service) << "protected" << endl;
+    indent_up();
+    indent(s_service) << "iprot_: IProtocol;" << endl;
+    indent(s_service) << "oprot_: IProtocol;" << endl;
+    indent(s_service) << "seqid_: Integer;" << endl;
+    indent_down();
+
+    indent(s_service) << "public" << endl;
+    indent_up();
+    indent(s_service) << "property InputProtocol: IProtocol read iprot_;" << endl;
+    indent(s_service) << "property OutputProtocol: IProtocol read oprot_;" << endl;
+    indent_down();
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+
+  indent(s_service) << "protected" << endl;
+  indent_up();
+  indent(s_service) << "// Iface" << endl;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+    generate_delphi_doc(s_service, *f_iter);
+    indent(s_service) << function_signature(*f_iter) << endl;
+  }
+  indent_down();
+
+  indent(s_service) << "public" << endl;
+  indent_up();
+
+  string full_cls = normalize_clsnm(service_name_, "T") + ".TClient";
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    indent_impl(s_service_impl) << function_signature(*f_iter, full_cls) << endl;
+    indent_impl(s_service_impl) << "begin" << endl;
+    indent_up_impl();
+    indent_impl(s_service_impl) << "send_" << funname << "(";
+
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        s_service_impl << ", ";
+      }
+      s_service_impl << normalize_name((*fld_iter)->get_name());
+    }
+    s_service_impl << ");" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      s_service_impl << indent_impl();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        s_service_impl << "Result := ";
+      }
+      s_service_impl << "recv_" << funname << "();" << endl;
+    }
+
+    indent_down_impl();
+    indent_impl(s_service_impl) << "end;" << endl << endl;
+
+    t_function send_function(g_type_void,
+                             string("send_") + (*f_iter)->get_name(),
+                             (*f_iter)->get_arglist());
+
+    string argsname = (*f_iter)->get_name() + "_args";
+    string args_clsnm = normalize_clsnm(argsname, "T");
+    string args_intfnm = normalize_clsnm(argsname, "I");
+
+    string argsvar = tmp("_args");
+    string msgvar = tmp("_msg");
+
+    indent(s_service) << function_signature(&send_function) << endl;
+    indent_impl(s_service_impl) << function_signature(&send_function, full_cls) << endl;
+    indent_impl(s_service_impl) << "var" << endl;
+    indent_up_impl();
+    indent_impl(s_service_impl) << argsvar << " : " << args_intfnm << ";" << endl;
+    indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.IMessage;" << endl;
+    indent_down_impl();
+    indent_impl(s_service_impl) << "begin" << endl;
+    indent_up_impl();
+
+    indent_impl(s_service_impl) << "seqid_ := seqid_ + 1;" << endl;
+    indent_impl(s_service_impl) << msgvar << " := Thrift.Protocol.TMessageImpl.Create('" << funname
+                                << "', " << ((*f_iter)->is_oneway() ? "TMessageType.Oneway"
+                                                                    : "TMessageType.Call")
+                                << ", seqid_);" << endl;
+
+    indent_impl(s_service_impl) << "oprot_.WriteMessageBegin( " << msgvar << " );" << endl;
+    indent_impl(s_service_impl) << argsvar << " := " << args_clsnm << "Impl.Create();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter)
+                                  << " := " << normalize_name((*fld_iter)->get_name()) << ";"
+                                  << endl;
+    }
+    indent_impl(s_service_impl) << argsvar << ".Write(oprot_);" << endl;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter)
+                                  << " := " << empty_value((*fld_iter)->get_type()) << ";" << endl;
+    }
+
+    indent_impl(s_service_impl) << "oprot_.WriteMessageEnd();" << endl;
+    indent_impl(s_service_impl) << "oprot_.Transport.Flush();" << endl;
+
+    indent_down_impl();
+    indent_impl(s_service_impl) << "end;" << endl << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      string org_resultname = (*f_iter)->get_name() + "_result";
+      string result_clsnm = normalize_clsnm(org_resultname, "T");
+      string result_intfnm = normalize_clsnm(org_resultname, "I");
+
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+
+      string exceptvar = tmp("_ex");
+      string appexvar = tmp("_ax");
+      string retvar = tmp("_ret");
+
+      indent(s_service) << function_signature(&recv_function) << endl;
+      indent_impl(s_service_impl) << function_signature(&recv_function, full_cls) << endl;
+      indent_impl(s_service_impl) << "var" << endl;
+      indent_up_impl();
+      indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.IMessage;" << endl;
+      if (xceptions.size() > 0) {
+        indent_impl(s_service_impl) << exceptvar << " : Exception;" << endl;
+      }
+      indent_impl(s_service_impl) << appexvar << " : TApplicationException;" << endl;
+      indent_impl(s_service_impl) << retvar << " : " << result_intfnm << ";" << endl;
+
+      indent_down_impl();
+      indent_impl(s_service_impl) << "begin" << endl;
+      indent_up_impl();
+      indent_impl(s_service_impl) << msgvar << " := iprot_.ReadMessageBegin();" << endl;
+      indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then"
+                                  << endl;
+      indent_impl(s_service_impl) << "begin" << endl;
+      indent_up_impl();
+      indent_impl(s_service_impl) << appexvar << " := TApplicationException.Read(iprot_);" << endl;
+      indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
+      indent_impl(s_service_impl) << "raise " << appexvar << ";" << endl;
+      indent_down_impl();
+      indent_impl(s_service_impl) << "end;" << endl;
+
+      indent_impl(s_service_impl) << retvar << " := " << result_clsnm << "Impl.Create();" << endl;
+      indent_impl(s_service_impl) << retvar << ".Read(iprot_);" << endl;
+      indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then" << endl;
+        indent_impl(s_service_impl) << "begin" << endl;
+        indent_up_impl();
+        indent_impl(s_service_impl) << "Result := " << retvar << ".Success;" << endl;
+        t_type* type = (*f_iter)->get_returntype();
+        if (type->is_struct() || type->is_xception() || type->is_map() || type->is_list()
+            || type->is_set()) {
+          indent_impl(s_service_impl) << retvar << ".Success := nil;" << endl;
+        }
+        indent_impl(s_service_impl) << "Exit;" << endl;
+        indent_down_impl();
+        indent_impl(s_service_impl) << "end;" << endl;
+      }
+
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter)
+                                    << ") then" << endl;
+        indent_impl(s_service_impl) << "begin" << endl;
+        indent_up_impl();
+        indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter)
+                                    << ".CreateException;" << endl;
+        indent_impl(s_service_impl) << "raise " << exceptvar << ";" << endl;
+        indent_down_impl();
+        indent_impl(s_service_impl) << "end;" << endl;
+      }
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent_impl(s_service_impl)
+			<< "raise TApplicationExceptionMissingResult.Create('"
+            << (*f_iter)->get_name() << " failed: unknown result');" << endl;
+      }
+
+      indent_down_impl();
+      indent_impl(s_service_impl) << "end;" << endl << endl;
+    }
+  }
+
+  indent_down();
+  indent(s_service) << "end;" << endl << endl;
+}
+
+void t_delphi_generator::generate_service_server(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+
+  string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl";
+
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends(), true, true);
+    extends_processor = extends + ".TProcessorImpl";
+    indent(s_service) << "TProcessorImpl = class(" << extends_processor << ", IProcessor)" << endl;
+  } else {
+    indent(s_service) << "TProcessorImpl = class( TInterfacedObject, IProcessor)" << endl;
+  }
+
+  indent(s_service) << "public" << endl;
+  indent_up();
+  indent(s_service) << "constructor Create( iface_: Iface );" << endl;
+  indent(s_service) << "destructor Destroy; override;" << endl;
+  indent_down();
+
+  indent_impl(s_service_impl) << "constructor " << full_cls << ".Create( iface_: Iface );" << endl;
+  indent_impl(s_service_impl) << "begin" << endl;
+  indent_up_impl();
+  if (tservice->get_extends() != NULL) {
+    indent_impl(s_service_impl) << "inherited Create( iface_);" << endl;
+  } else {
+    indent_impl(s_service_impl) << "inherited Create;" << endl;
+  }
+  indent_impl(s_service_impl) << "Self.iface_ := iface_;" << endl;
+  if (tservice->get_extends() != NULL) {
+    indent_impl(s_service_impl) << "ASSERT( processMap_ <> nil);  // inherited" << endl;
+  } else {
+    indent_impl(s_service_impl)
+        << "processMap_ := TThriftDictionaryImpl<string, TProcessFunction>.Create;" << endl;
+  }
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent_impl(s_service_impl) << "processMap_.AddOrSetValue( '" << (*f_iter)->get_name() << "', "
+                                << (*f_iter)->get_name() << "_Process);" << endl;
+  }
+  indent_down_impl();
+  indent_impl(s_service_impl) << "end;" << endl << endl;
+
+  indent_impl(s_service_impl) << "destructor " << full_cls << ".Destroy;" << endl;
+  indent_impl(s_service_impl) << "begin" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "inherited;" << endl;
+  indent_down_impl();
+  indent_impl(s_service_impl) << "end;" << endl << endl;
+
+  indent(s_service) << "private" << endl;
+  indent_up();
+  indent(s_service) << "iface_: Iface;" << endl;
+  indent_down();
+
+  if (tservice->get_extends() == NULL) {
+    indent(s_service) << "protected" << endl;
+    indent_up();
+    indent(s_service) << "type" << endl;
+    indent_up();
+    indent(s_service) << "TProcessFunction = reference to procedure( seqid: Integer; const iprot: "
+                         "IProtocol; const oprot: IProtocol"
+                      << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
+    indent_down();
+    indent_down();
+    indent(s_service) << "protected" << endl;
+    indent_up();
+    indent(s_service) << "processMap_: IThriftDictionary<string, TProcessFunction>;" << endl;
+    indent_down();
+  }
+
+  indent(s_service) << "public" << endl;
+  indent_up();
+  if (extends.empty()) {
+    indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
+                         "events : IProcessorEvents): Boolean;" << endl;
+  } else {
+    indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
+                         "events : IProcessorEvents): Boolean; reintroduce;" << endl;
+  }
+
+  indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; "
+                                                            "const oprot: IProtocol; const events "
+                                                            ": IProcessorEvents): Boolean;" << endl;
+  ;
+  indent_impl(s_service_impl) << "var" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "msg : Thrift.Protocol.IMessage;" << endl;
+  indent_impl(s_service_impl) << "fn : TProcessFunction;" << endl;
+  indent_impl(s_service_impl) << "x : TApplicationException;" << endl;
+  if (events_) {
+    indent_impl(s_service_impl) << "context : IRequestEvents;" << endl;
+  }
+  indent_down_impl();
+  indent_impl(s_service_impl) << "begin" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "try" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl;
+  indent_impl(s_service_impl) << "fn := nil;" << endl;
+  indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl;
+  indent_impl(s_service_impl) << "or not Assigned(fn) then" << endl;
+  indent_impl(s_service_impl) << "begin" << endl;
+  indent_up_impl();
+  indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl;
+  indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
+  indent_impl(s_service_impl) << "x := "
+								 "TApplicationExceptionUnknownMethod.Create("
+								 "'Invalid method name: ''' + msg.Name + '''');" << endl;
+  indent_impl(s_service_impl)
+      << "msg := Thrift.Protocol.TMessageImpl.Create(msg.Name, TMessageType.Exception, msg.SeqID);"
+      << endl;
+  indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl;
+  indent_impl(s_service_impl) << "x.Write(oprot);" << endl;
+  indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
+  indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
+  indent_impl(s_service_impl) << "Result := True;" << endl;
+  indent_impl(s_service_impl) << "Exit;" << endl;
+  indent_down_impl();
+  indent_impl(s_service_impl) << "end;" << endl;
+  if (events_) {
+    indent_impl(s_service_impl) << "if events <> nil" << endl;
+    indent_impl(s_service_impl) << "then context := events.CreateRequestContext(msg.Name)" << endl;
+    indent_impl(s_service_impl) << "else context := nil;" << endl;
+    indent_impl(s_service_impl) << "try" << endl;
+    indent_up_impl();
+    indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot, context);" << endl;
+    indent_down_impl();
+    indent_impl(s_service_impl) << "finally" << endl;
+    indent_up_impl();
+    indent_impl(s_service_impl) << "if context <> nil then begin" << endl;
+    indent_up_impl();
+    indent_impl(s_service_impl) << "context.CleanupContext;" << endl;
+    indent_impl(s_service_impl) << "context := nil;" << endl;
+    indent_down_impl();
+    indent_impl(s_service_impl) << "end;" << endl;
+    indent_down_impl();
+    indent_impl(s_service_impl) << "end;" << endl;
+  } else {
+    indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot);" << endl;
+  }
+  indent_down_i

<TRUNCATED>

[07/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_js_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc
new file mode 100644
index 0000000..b0046a0
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc
@@ -0,0 +1,2231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <map>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <list>
+#include <cassert>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/version.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+#include "thrift/generate/t_oop_generator.h"
+
+
+/**
+ * JS code generator.
+ */
+class t_js_generator : public t_oop_generator {
+public:
+  t_js_generator(t_program* program,
+                 const std::map<std::string, std::string>& parsed_options,
+                 const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    gen_node_ = false;
+    gen_jquery_ = false;
+    gen_ts_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("node") == 0) {
+        gen_node_ = true;
+      } else if( iter->first.compare("jquery") == 0) {
+        gen_jquery_ = true;
+      } else if( iter->first.compare("ts") == 0) {
+        gen_ts_ = true;
+      } else {
+        throw "unknown option js:" + iter->first;
+      }
+    }
+
+    if (gen_node_ && gen_ts_) {
+      throw "Invalid switch: [-gen js:node,ts] options not compatible";
+    }
+
+    if (gen_node_ && gen_jquery_) {
+      throw "Invalid switch: [-gen js:node,jquery] options not compatible, try: [-gen js:node -gen "
+            "js:jquery]";
+    }
+
+    if (gen_node_) {
+      out_dir_base_ = "gen-nodejs";
+    } else {
+      out_dir_base_ = "gen-js";
+    }
+
+    escape_['\''] = "\\'";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_recv_throw(std::string var);
+  std::string render_recv_return(std::string var);
+
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+  /**
+   * Structs!
+   */
+  void generate_js_struct(t_struct* tstruct, bool is_exception);
+  void generate_js_struct_definition(std::ofstream& out,
+                                     t_struct* tstruct,
+                                     bool is_xception = false,
+                                     bool is_exported = true);
+  void generate_js_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_js_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_js_function_helpers(t_function* tfunction);
+
+  /**
+   * Service-level generation functions
+   */
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_rest(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_processor(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool inclass = false);
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string js_includes();
+  std::string render_includes();
+  std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
+  std::string function_signature(t_function* tfunction,
+                                 std::string prefix = "",
+                                 bool include_callback = false);
+  std::string argument_list(t_struct* tstruct, bool include_callback = false);
+  std::string type_to_enum(t_type* ttype);
+  std::string make_valid_nodeJs_identifier(std::string const& name);
+
+  std::string autogen_comment() {
+    return std::string("//\n") + "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+           + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
+           + "//\n";
+  }
+
+  t_type* get_contained_type(t_type* t);
+
+  std::vector<std::string> js_namespace_pieces(t_program* p) {
+    std::string ns = p->get_namespace("js");
+
+    std::string::size_type loc;
+    std::vector<std::string> pieces;
+
+    if (ns.size() > 0) {
+      while ((loc = ns.find(".")) != std::string::npos) {
+        pieces.push_back(ns.substr(0, loc));
+        ns = ns.substr(loc + 1);
+      }
+    }
+
+    if (ns.size() > 0) {
+      pieces.push_back(ns);
+    }
+
+    return pieces;
+  }
+
+  std::string js_type_namespace(t_program* p) {
+    if (gen_node_) {
+      if (p != NULL && p != program_) {
+        return make_valid_nodeJs_identifier(p->get_name()) + "_ttypes.";
+      }
+      return "ttypes.";
+    }
+    return js_namespace(p);
+  }
+
+  std::string js_export_namespace(t_program* p) {
+    if (gen_node_) {
+      return "exports.";
+    }
+    return js_namespace(p);
+  }
+
+  bool has_js_namespace(t_program* p) {
+    std::string ns = p->get_namespace("js");
+    return (ns.size() > 0);
+  }
+
+  std::string js_namespace(t_program* p) {
+    std::string ns = p->get_namespace("js");
+    if (ns.size() > 0) {
+      ns += ".";
+    }
+
+    return ns;
+  }
+
+  /**
+   * TypeScript Definition File helper functions
+   */
+
+  string ts_function_signature(t_function* tfunction, bool include_callback);
+  string ts_get_type(t_type* type);
+
+  /**
+   * Special indentation for TypeScript Definitions because of the module.
+   * Returns the normal indentation + "  " if a module was defined.
+   * @return string
+   */
+  string ts_indent() { return indent() + (!ts_module_.empty() ? "  " : ""); }
+
+  /**
+   * Returns "declare " if no module was defined.
+   * @return string
+   */
+  string ts_declare() { return (ts_module_.empty() ? "declare " : ""); }
+
+  /**
+   * Returns "?" if the given field is optional.
+   * @param t_field The field to check
+   * @return string
+   */
+  string ts_get_req(t_field* field) { return (field->get_req() == t_field::T_OPTIONAL ? "?" : ""); }
+
+  /**
+   * Returns the documentation, if the provided documentable object has one.
+   * @param t_doc The object to get the documentation from
+   * @return string The documentation
+   */
+  string ts_print_doc(t_doc* tdoc) {
+    string result = endl;
+
+    if (tdoc->has_doc()) {
+      std::stringstream doc(tdoc->get_doc());
+      string item;
+
+      result += ts_indent() + "/**" + endl;
+      while (std::getline(doc, item)) {
+        result += ts_indent() + " * " + item + endl;
+      }
+      result += ts_indent() + " */" + endl;
+    }
+    return result;
+  }
+
+private:
+  /**
+   * True if we should generate NodeJS-friendly RPC services.
+   */
+  bool gen_node_;
+
+  /**
+   * True if we should generate services that use jQuery ajax (async/sync).
+   */
+  bool gen_jquery_;
+
+  /**
+   * True if we should generate a TypeScript Definition File for each service.
+   */
+  bool gen_ts_;
+
+  /**
+   * The name of the defined module(s), for TypeScript Definition Files.
+   */
+  string ts_module_;
+
+  /**
+   * File streams
+   */
+  std::ofstream f_types_;
+  std::ofstream f_service_;
+  std::ofstream f_types_ts_;
+  std::ofstream f_service_ts_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_js_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  string outdir = get_out_dir();
+
+  // Make output file(s)
+  string f_types_name = outdir + program_->get_name() + "_types.js";
+  f_types_.open(f_types_name.c_str());
+
+  if (gen_ts_) {
+    string f_types_ts_name = outdir + program_->get_name() + "_types.d.ts";
+    f_types_ts_.open(f_types_ts_name.c_str());
+  }
+
+  // Print header
+  f_types_ << autogen_comment() << js_includes() << endl << render_includes() << endl;
+
+  if (gen_ts_) {
+    f_types_ts_ << autogen_comment() << endl;
+  }
+
+  if (gen_node_) {
+    f_types_ << "var ttypes = module.exports = {};" << endl;
+  }
+
+  string pns;
+
+  // setup the namespace
+  // TODO should the namespace just be in the directory structure for node?
+  vector<string> ns_pieces = js_namespace_pieces(program_);
+  if (ns_pieces.size() > 0) {
+    for (size_t i = 0; i < ns_pieces.size(); ++i) {
+      pns += ((i == 0) ? "" : ".") + ns_pieces[i];
+      f_types_ << "if (typeof " << pns << " === 'undefined') {" << endl;
+      f_types_ << "  " << pns << " = {};" << endl;
+      f_types_ << "}" << endl;
+    }
+    if (gen_ts_) {
+      ts_module_ = pns;
+      f_types_ts_ << "declare module " << ts_module_ << " {";
+    }
+  }
+}
+
+/**
+ * Prints standard js imports
+ */
+string t_js_generator::js_includes() {
+  if (gen_node_) {
+    return string(
+        "var thrift = require('thrift');\n"
+        "var Thrift = thrift.Thrift;\n"
+        "var Q = thrift.Q;\n");
+  }
+
+  return "";
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_js_generator::render_includes() {
+  string result = "";
+
+  if (gen_node_) {
+    const vector<t_program*>& includes = program_->get_includes();
+    for (size_t i = 0; i < includes.size(); ++i) {
+      result += "var " + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name()
+                + "_types');\n";
+    }
+    if (includes.size() > 0) {
+      result += "\n";
+    }
+  }
+
+  return result;
+}
+
+/**
+ * Close up (or down) some filez.
+ */
+void t_js_generator::close_generator() {
+  // Close types file(s)
+
+  f_types_.close();
+
+  if (gen_ts_) {
+    if (!ts_module_.empty()) {
+      f_types_ts_ << "}";
+    }
+    f_types_ts_.close();
+  }
+}
+
+/**
+ * Generates a typedef. This is not done in JS, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_js_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Generates code for an enumerated type. Since define is expensive to lookup
+ * in JS, we use a global array for this.
+ *
+ * @param tenum The enumeration
+ */
+void t_js_generator::generate_enum(t_enum* tenum) {
+  f_types_ << js_type_namespace(tenum->get_program()) << tenum->get_name() << " = {" << endl;
+
+  if (gen_ts_) {
+    f_types_ts_ << ts_print_doc(tenum) << ts_indent() << ts_declare() << "enum "
+                << tenum->get_name() << " {" << endl;
+  }
+
+  indent_up();
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    if (gen_ts_) {
+      f_types_ts_ << ts_indent() << (*c_iter)->get_name() << " = " << value << "," << endl;
+      // add 'value: key' in addition to 'key: value' for TypeScript enums
+      f_types_ << indent() << "'" << value << "' : '" << (*c_iter)->get_name() << "'," << endl;
+    }
+    f_types_ << indent() << "'" << (*c_iter)->get_name() << "' : " << value;
+    if (c_iter != constants.end() - 1) {
+      f_types_ << ",";
+    }
+    f_types_ << endl;
+  }
+
+  indent_down();
+
+  f_types_ << "};" << endl;
+
+  if (gen_ts_) {
+    f_types_ts_ << ts_indent() << "}" << endl;
+  }
+}
+
+/**
+ * Generate a constant value
+ */
+void t_js_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  f_types_ << js_type_namespace(program_) << name << " = ";
+  f_types_ << render_const_value(type, value) << ";" << endl;
+
+  if (gen_ts_) {
+    f_types_ts_ << ts_print_doc(tconst) << ts_indent() << ts_declare() << "var " << name << ": "
+                << ts_get_type(type) << ";" << endl;
+  }
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_js_generator::render_const_value(t_type* type, t_const_value* value) {
+  std::ostringstream out;
+
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << "'" << get_escaped_string(value) << "'";
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    out << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << "new " << js_type_namespace(type->get_program()) << type->get_name() << "({" << endl;
+    indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      if (v_iter != val.begin())
+        out << ",";
+      out << render_const_value(g_type_string, v_iter->first);
+      out << " : ";
+      out << render_const_value(field_type, v_iter->second);
+    }
+
+    out << "})";
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    out << "{" << endl;
+    indent_up();
+
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      if (v_iter != val.begin())
+        out << "," << endl;
+
+      out << indent() << render_const_value(ktype, v_iter->first);
+
+      out << " : ";
+      out << render_const_value(vtype, v_iter->second);
+    }
+
+    indent_down();
+    out << endl << "}";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    out << "[";
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      if (v_iter != val.begin())
+        out << ",";
+      out << render_const_value(etype, *v_iter);
+    }
+    out << "]";
+  }
+  return out.str();
+}
+
+/**
+ * Make a struct
+ */
+void t_js_generator::generate_struct(t_struct* tstruct) {
+  generate_js_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_js_generator::generate_xception(t_struct* txception) {
+  generate_js_struct(txception, true);
+}
+
+/**
+ * Structs can be normal or exceptions.
+ */
+void t_js_generator::generate_js_struct(t_struct* tstruct, bool is_exception) {
+  generate_js_struct_definition(f_types_, tstruct, is_exception);
+}
+
+/**
+ * Return type of contained elements for a container type. For maps
+ * this is type of value (keys are always strings in js)
+ */
+t_type* t_js_generator::get_contained_type(t_type* t) {
+  t_type* etype;
+  if (t->is_list()) {
+    etype = ((t_list*)t)->get_elem_type();
+  } else if (t->is_set()) {
+    etype = ((t_set*)t)->get_elem_type();
+  } else {
+    etype = ((t_map*)t)->get_val_type();
+  }
+  return etype;
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is nothing in JS
+ * where the objects are all just associative arrays (unless of course we
+ * decide to start using objects for them...)
+ *
+ * @param tstruct The struct definition
+ */
+void t_js_generator::generate_js_struct_definition(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   bool is_exception,
+                                                   bool is_exported) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  if (gen_node_) {
+    string prefix = has_js_namespace(tstruct->get_program()) ? js_namespace(tstruct->get_program()) : "var ";
+    if (is_exported) {
+      out << prefix << tstruct->get_name() << " = "
+          << "module.exports." << tstruct->get_name() << " = function(args) {" << endl;
+    } else {
+      out << prefix << tstruct->get_name() << " = function(args) {"
+          << endl;
+    }
+  } else {
+    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = function(args) {"
+        << endl;
+    if (gen_ts_) {
+      f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class "
+                  << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "")
+                  << " {" << endl;
+    }
+  }
+
+  indent_up();
+
+  if (gen_node_ && is_exception) {
+    out << indent() << "Thrift.TException.call(this, \"" << js_namespace(tstruct->get_program())
+        << tstruct->get_name() << "\")" << endl;
+    out << indent() << "this.name = \"" << js_namespace(tstruct->get_program())
+        << tstruct->get_name() << "\"" << endl;
+  }
+
+  // members with arguments
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    string dval = declare_field(*m_iter, false, true);
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
+      dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
+      out << indent() << "this." << (*m_iter)->get_name() << " = " << dval << ";" << endl;
+    } else {
+      out << indent() << dval << ";" << endl;
+    }
+    if (gen_ts_) {
+      f_types_ts_ << ts_indent() << (*m_iter)->get_name() << ": "
+                  << ts_get_type((*m_iter)->get_type()) << ";" << endl;
+    }
+  }
+
+  // Generate constructor from array
+  if (members.size() > 0) {
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
+        indent(out) << "this." << (*m_iter)->get_name() << " = "
+                    << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
+      }
+    }
+
+    // Early returns for exceptions
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      if (t->is_xception()) {
+        out << indent() << "if (args instanceof " << js_type_namespace(t->get_program())
+            << t->get_name() << ") {" << endl << indent() << indent() << "this."
+            << (*m_iter)->get_name() << " = args;" << endl << indent() << indent() << "return;"
+            << endl << indent() << "}" << endl;
+      }
+    }
+
+    out << indent() << "if (args) {" << endl;
+    if (gen_ts_) {
+      f_types_ts_ << endl << ts_indent() << "constructor(args?: { ";
+    }
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      out << indent() << indent() << "if (args." << (*m_iter)->get_name() << " !== undefined && args." << (*m_iter)->get_name() << " !== null) {"
+          << endl << indent() << indent() << indent() << "this." << (*m_iter)->get_name();
+
+      if (t->is_struct()) {
+        out << (" = new " + js_type_namespace(t->get_program()) + t->get_name() +
+                "(args."+(*m_iter)->get_name() +");");
+        out << endl;
+      } else if (t->is_container()) {
+        t_type* etype = get_contained_type(t);
+        string copyFunc = t->is_map() ? "Thrift.copyMap" : "Thrift.copyList";
+        string type_list = "";
+
+        while (etype->is_container()) {
+          if (type_list.length() > 0) {
+            type_list += ", ";
+          }
+          type_list += etype->is_map() ? "Thrift.copyMap" : "Thrift.copyList";
+          etype = get_contained_type(etype);
+        }
+
+        if (etype->is_struct()) {
+          if (type_list.length() > 0) {
+            type_list += ", ";
+          }
+          type_list += js_type_namespace(etype->get_program()) + etype->get_name();
+        }
+        else {
+          if (type_list.length() > 0) {
+            type_list += ", ";
+          }
+          type_list += "null";
+        }
+
+        out << (" = " + copyFunc + "(args." + (*m_iter)->get_name() +
+                ", [" + type_list + "]);");
+        out << endl;
+      } else {
+        out << " = args." << (*m_iter)->get_name() << ";" << endl;
+      }
+
+      if (!(*m_iter)->get_req()) {
+        out << indent() << indent() << "} else {" << endl << indent() << indent() << indent()
+            << "throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.UNKNOWN, "
+               "'Required field " << (*m_iter)->get_name() << " is unset!');" << endl;
+      }
+      out << indent() << indent() << "}" << endl;
+      if (gen_ts_) {
+        f_types_ts_ << (*m_iter)->get_name() << ts_get_req(*m_iter) << ": "
+                    << ts_get_type((*m_iter)->get_type()) << "; ";
+      }
+    }
+
+    out << indent() << "}" << endl;
+    if (gen_ts_) {
+      f_types_ts_ << "});" << endl;
+    }
+  }
+
+  indent_down();
+  out << "};" << endl;
+  if (gen_ts_) {
+    f_types_ts_ << ts_indent() << "}" << endl;
+  }
+
+  if (is_exception) {
+    out << "Thrift.inherits(" << js_namespace(tstruct->get_program()) << tstruct->get_name()
+        << ", Thrift.TException);" << endl;
+    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.name = '"
+        << tstruct->get_name() << "';" << endl;
+  } else {
+    // init prototype
+    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype = {};"
+        << endl;
+  }
+
+  generate_js_struct_reader(out, tstruct);
+  generate_js_struct_writer(out, tstruct);
+}
+
+/**
+ * Generates the read() method for a struct
+ */
+void t_js_generator::generate_js_struct_reader(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << js_namespace(tstruct->get_program()) << tstruct->get_name()
+      << ".prototype.read = function(input) {" << endl;
+
+  indent_up();
+
+  indent(out) << "input.readStructBegin();" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+
+  scope_up(out);
+
+  indent(out) << "var ret = input.readFieldBegin();" << endl;
+  indent(out) << "var fname = ret.fname;" << endl;
+  indent(out) << "var ftype = ret.ftype;" << endl;
+  indent(out) << "var fid = ret.fid;" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (ftype == Thrift.Type.STOP) {" << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+  if (!fields.empty()) {
+    // Switch statement on the field we are reading
+    indent(out) << "switch (fid)" << endl;
+
+    scope_up(out);
+
+    // Generate deserialization code for known cases
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+
+      indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+      indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+
+      indent_up();
+      generate_deserialize_field(out, *f_iter, "this.");
+      indent_down();
+
+      indent(out) << "} else {" << endl;
+
+      indent(out) << "  input.skip(ftype);" << endl;
+
+      out << indent() << "}" << endl << indent() << "break;" << endl;
+    }
+    if (fields.size() == 1) {
+      // pseudo case to make jslint happy
+      indent(out) << "case 0:" << endl;
+      indent(out) << "  input.skip(ftype);" << endl;
+      indent(out) << "  break;" << endl;
+    }
+    // In the default case we skip the field
+    indent(out) << "default:" << endl;
+    indent(out) << "  input.skip(ftype);" << endl;
+
+    scope_down(out);
+  } else {
+    indent(out) << "input.skip(ftype);" << endl;
+  }
+
+  indent(out) << "input.readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  indent(out) << "input.readStructEnd();" << endl;
+
+  indent(out) << "return;" << endl;
+
+  indent_down();
+  out << indent() << "};" << endl << endl;
+}
+
+/**
+ * Generates the write() method for a struct
+ */
+void t_js_generator::generate_js_struct_writer(ofstream& out, t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << js_namespace(tstruct->get_program()) << tstruct->get_name()
+      << ".prototype.write = function(output) {" << endl;
+
+  indent_up();
+
+  indent(out) << "output.writeStructBegin('" << name << "');" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out << indent() << "if (this." << (*f_iter)->get_name() << " !== null && this."
+        << (*f_iter)->get_name() << " !== undefined) {" << endl;
+    indent_up();
+
+    indent(out) << "output.writeFieldBegin("
+                << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
+                << ", " << (*f_iter)->get_key() << ");" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    indent(out) << "output.writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}" << endl;
+  }
+
+  out << indent() << "output.writeFieldStop();" << endl << indent() << "output.writeStructEnd();"
+      << endl;
+
+  out << indent() << "return;" << endl;
+
+  indent_down();
+  out << indent() << "};" << endl << endl;
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_js_generator::generate_service(t_service* tservice) {
+  string f_service_name = get_out_dir() + service_name_ + ".js";
+  f_service_.open(f_service_name.c_str());
+
+  if (gen_ts_) {
+    string f_service_ts_name = get_out_dir() + service_name_ + ".d.ts";
+    f_service_ts_.open(f_service_ts_name.c_str());
+  }
+
+  f_service_ << autogen_comment() << js_includes() << endl << render_includes() << endl;
+
+  if (gen_ts_) {
+    if (tservice->get_extends() != NULL) {
+      f_service_ts_ << "/// <reference path=\"" << tservice->get_extends()->get_name()
+                    << ".d.ts\" />" << endl;
+    }
+    f_service_ts_ << autogen_comment() << endl;
+    if (!ts_module_.empty()) {
+      f_service_ts_ << "declare module " << ts_module_ << " {";
+    }
+  }
+
+  if (gen_node_) {
+    if (tservice->get_extends() != NULL) {
+      f_service_ << "var " << tservice->get_extends()->get_name() << " = require('./"
+                 << tservice->get_extends()->get_name() << "');" << endl << "var "
+                 << tservice->get_extends()->get_name()
+                 << "Client = " << tservice->get_extends()->get_name() << ".Client;" << endl
+                 << "var " << tservice->get_extends()->get_name()
+                 << "Processor = " << tservice->get_extends()->get_name() << ".Processor;" << endl;
+    }
+
+    f_service_ << "var ttypes = require('./" + program_->get_name() + "_types');" << endl;
+  }
+
+  generate_service_helpers(tservice);
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+
+  if (gen_node_) {
+    generate_service_processor(tservice);
+  }
+
+  f_service_.close();
+  if (gen_ts_) {
+    if (!ts_module_.empty()) {
+      f_service_ts_ << "}";
+    }
+    f_service_ts_.close();
+  }
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_js_generator::generate_service_processor(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  if (gen_node_) {
+    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : "var ";
+    f_service_ << prefix << service_name_ << "Processor = " << "exports.Processor = function(handler) ";
+  } else {
+    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Processor = "
+             << "exports.Processor = function(handler) ";
+  }
+
+  scope_up(f_service_);
+
+  f_service_ << indent() << "this._handler = handler" << endl;
+
+  scope_down(f_service_);
+
+  if (tservice->get_extends() != NULL) {
+    indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
+                       << service_name_ << "Processor, " << tservice->get_extends()->get_name()
+                       << "Processor)" << endl;
+  }
+
+  // Generate the server implementation
+  indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                     << "Processor.prototype.process = function(input, output) ";
+
+  scope_up(f_service_);
+
+  f_service_ << indent() << "var r = input.readMessageBegin();" << endl << indent()
+             << "if (this['process_' + r.fname]) {" << endl << indent()
+             << "  return this['process_' + r.fname].call(this, r.rseqid, input, output);" << endl
+             << indent() << "} else {" << endl << indent() << "  input.skip(Thrift.Type.STRUCT);"
+             << endl << indent() << "  input.readMessageEnd();" << endl << indent()
+             << "  var x = new "
+                "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN_METHOD, "
+                "'Unknown function ' + r.fname);" << endl << indent()
+             << "  output.writeMessageBegin(r.fname, Thrift.MessageType.EXCEPTION, r.rseqid);"
+             << endl << indent() << "  x.write(output);" << endl << indent()
+             << "  output.writeMessageEnd();" << endl << indent() << "  output.flush();" << endl
+             << indent() << "}" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_js_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                     << "Processor.prototype.process_" + tfunction->get_name()
+                        + " = function(seqid, input, output) ";
+
+  scope_up(f_service_);
+
+  string argsname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name() + "_args";
+  string resultname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name()
+                      + "_result";
+
+  f_service_ << indent() << "var args = new " << argsname << "();" << endl << indent()
+             << "args.read(input);" << endl << indent() << "input.readMessageEnd();" << endl;
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    indent(f_service_) << "this._handler." << tfunction->get_name() << "(";
+
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+
+    f_service_ << ")" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+    return;
+  }
+
+  f_service_ << indent() << "if (this._handler." << tfunction->get_name()
+             << ".length === " << fields.size() << ") {" << endl;
+  indent_up();
+  indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name();
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    f_service_ << ", args." << (*f_iter)->get_name();
+  }
+
+  f_service_ << ")" << endl;
+  indent_up();
+  indent(f_service_) << ".then(function(result) {" << endl;
+  indent_up();
+  f_service_ << indent() << "var result = new " << resultname << "({success: result});" << endl
+             << indent() << "output.writeMessageBegin(\"" << tfunction->get_name()
+             << "\", Thrift.MessageType.REPLY, seqid);" << endl << indent()
+             << "result.write(output);" << endl << indent() << "output.writeMessageEnd();" << endl
+             << indent() << "output.flush();" << endl;
+  indent_down();
+  indent(f_service_) << "}, function (err) {" << endl;
+  indent_up();
+
+  bool has_exception = false;
+  t_struct* exceptions = tfunction->get_xceptions();
+  if (exceptions) {
+    const vector<t_field*>& members = exceptions->get_members();
+    for (vector<t_field*>::const_iterator it = members.begin(); it != members.end(); ++it) {
+      t_type* t = get_true_type((*it)->get_type());
+      if (t->is_xception()) {
+        if (!has_exception) {
+          has_exception = true;
+          indent(f_service_) << "if (err instanceof " << js_type_namespace(t->get_program())
+                             << t->get_name();
+        } else {
+          f_service_ << " || err instanceof " << js_type_namespace(t->get_program())
+                     << t->get_name();
+        }
+      }
+    }
+  }
+
+  if (has_exception) {
+    f_service_ << ") {" << endl;
+    indent_up();
+    f_service_ << indent() << "var result = new " << resultname << "(err);" << endl << indent()
+               << "output.writeMessageBegin(\"" << tfunction->get_name()
+               << "\", Thrift.MessageType.REPLY, seqid);" << endl;
+
+    indent_down();
+    indent(f_service_) << "} else {" << endl;
+    indent_up();
+  }
+
+  f_service_ << indent() << "var result = new "
+                            "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN,"
+                            " err.message);" << endl << indent() << "output.writeMessageBegin(\""
+             << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << endl;
+
+  if (has_exception) {
+    indent_down();
+    indent(f_service_) << "}" << endl;
+  }
+
+  f_service_ << indent() << "result.write(output);" << endl << indent()
+             << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl;
+  indent_down();
+  indent(f_service_) << "});" << endl;
+  indent_down();
+  indent_down();
+  indent(f_service_) << "} else {" << endl;
+  indent_up();
+  indent(f_service_) << "this._handler." << tfunction->get_name() << "(";
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    f_service_ << "args." << (*f_iter)->get_name() << ", ";
+  }
+
+  f_service_ << "function (err, result) {" << endl;
+  indent_up();
+
+  indent(f_service_) << "if (err == null";
+  if (has_exception) {
+    const vector<t_field*>& members = exceptions->get_members();
+    for (vector<t_field*>::const_iterator it = members.begin(); it != members.end(); ++it) {
+      t_type* t = get_true_type((*it)->get_type());
+      if (t->is_xception()) {
+        f_service_ << " || err instanceof " << js_type_namespace(t->get_program()) << t->get_name();
+      }
+    }
+  }
+  f_service_ << ") {" << endl;
+  indent_up();
+  f_service_ << indent() << "var result = new " << resultname
+             << "((err != null ? err : {success: result}));" << endl << indent()
+             << "output.writeMessageBegin(\"" << tfunction->get_name()
+             << "\", Thrift.MessageType.REPLY, seqid);" << endl;
+  indent_down();
+  indent(f_service_) << "} else {" << endl;
+  indent_up();
+  f_service_ << indent() << "var result = new "
+                            "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN,"
+                            " err.message);" << endl << indent() << "output.writeMessageBegin(\""
+             << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << endl;
+  indent_down();
+  f_service_ << indent() << "}" << endl << indent() << "result.write(output);" << endl << indent()
+             << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl;
+
+  indent_down();
+  indent(f_service_) << "});" << endl;
+  indent_down();
+  indent(f_service_) << "}" << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_js_generator::generate_service_helpers(t_service* tservice) {
+  // Do not generate TS definitions for helper functions
+  bool gen_ts_tmp = gen_ts_;
+  gen_ts_ = false;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  f_service_ << "//HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    string name = ts->get_name();
+    ts->set_name(service_name_ + "_" + name);
+    generate_js_struct_definition(f_service_, ts, false, false);
+    generate_js_function_helpers(*f_iter);
+    ts->set_name(name);
+  }
+
+  gen_ts_ = gen_ts_tmp;
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_js_generator::generate_js_function_helpers(t_function* tfunction) {
+  t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_js_struct_definition(f_service_, &result, false, false);
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_js_generator::generate_service_interface(t_service* tservice) {
+  (void)tservice;
+}
+
+/**
+ * Generates a REST interface
+ */
+void t_js_generator::generate_service_rest(t_service* tservice) {
+  (void)tservice;
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_js_generator::generate_service_client(t_service* tservice) {
+  if (gen_node_) {
+    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : "var ";
+    f_service_ << prefix << service_name_ << "Client = "
+               << "exports.Client = function(output, pClass) {" << endl;
+  } else {
+    f_service_ << js_namespace(tservice->get_program()) << service_name_
+               << "Client = function(input, output) {" << endl;
+    if (gen_ts_) {
+      f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class "
+                    << service_name_ << "Client ";
+      if (tservice->get_extends() != NULL) {
+        f_service_ts_ << "extends " << tservice->get_extends()->get_name() << "Client ";
+      }
+      f_service_ts_ << "{" << endl;
+    }
+  }
+
+  indent_up();
+
+  if (gen_node_) {
+    f_service_ << indent() << "  this.output = output;" << endl << indent()
+               << "  this.pClass = pClass;" << endl << indent() << "  this._seqid = 0;" << endl
+               << indent() << "  this._reqs = {};" << endl;
+  } else {
+    f_service_ << indent() << "  this.input = input;" << endl << indent()
+               << "  this.output = (!output) ? input : output;" << endl << indent()
+               << "  this.seqid = 0;" << endl;
+    if (gen_ts_) {
+      f_service_ts_ << ts_indent() << "input: Thrift.TJSONProtocol;" << endl << ts_indent()
+                    << "output: Thrift.TJSONProtocol;" << endl << ts_indent() << "seqid: number;"
+                    << endl << endl << ts_indent()
+                    << "constructor(input: Thrift.TJSONProtocol, output?: Thrift.TJSONProtocol);"
+                    << endl;
+    }
+  }
+
+  indent_down();
+
+  f_service_ << indent() << "};" << endl;
+
+  if (tservice->get_extends() != NULL) {
+    indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
+                       << service_name_ << "Client, "
+                       << js_namespace(tservice->get_extends()->get_program())
+                       << tservice->get_extends()->get_name() << "Client);" << endl;
+  } else {
+    // init prototype
+    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                       << "Client.prototype = {};" << endl;
+  }
+
+  // utils for multiplexed services
+  if (gen_node_) {
+    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                       << "Client.prototype.seqid = function() { return this._seqid; }" << endl
+                       << js_namespace(tservice->get_program()) << service_name_
+                       << "Client.prototype.new_seqid = function() { return this._seqid += 1; }"
+                       << endl;
+  }
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+    string arglist = argument_list(arg_struct);
+
+    // Open function
+    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype."
+               << function_signature(*f_iter, "", true) << " {" << endl;
+
+    indent_up();
+
+    if (gen_ts_) {
+      f_service_ts_ << ts_print_doc(*f_iter) <<
+          // function definition without callback
+          ts_indent() << ts_function_signature(*f_iter, false) << endl << ts_print_doc(*f_iter) <<
+          // overload with callback
+          ts_indent() << ts_function_signature(*f_iter, true) << endl;
+    }
+
+    if (gen_node_) { // Node.js output      ./gen-nodejs
+      f_service_ << indent() << "this._seqid = this.new_seqid();" << endl << indent()
+                 << "if (callback === undefined) {" << endl;
+      indent_up();
+      f_service_ << indent() << "var _defer = Q.defer();" << endl << indent()
+                 << "this._reqs[this.seqid()] = function(error, result) {" << endl;
+      indent_up();
+      indent(f_service_) << "if (error) {" << endl;
+      indent_up();
+      indent(f_service_) << "_defer.reject(error);" << endl;
+      indent_down();
+      indent(f_service_) << "} else {" << endl;
+      indent_up();
+      indent(f_service_) << "_defer.resolve(result);" << endl;
+      indent_down();
+      indent(f_service_) << "}" << endl;
+      indent_down();
+      indent(f_service_) << "};" << endl;
+      f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");" << endl
+                 << indent() << "return _defer.promise;" << endl;
+      indent_down();
+      indent(f_service_) << "} else {" << endl;
+      indent_up();
+      f_service_ << indent() << "this._reqs[this.seqid()] = callback;" << endl << indent()
+                 << "this.send_" << funname << "(" << arglist << ");" << endl;
+      indent_down();
+      indent(f_service_) << "}" << endl;
+    } else if (gen_jquery_) { // jQuery output       ./gen-js
+      f_service_ << indent() << "if (callback === undefined) {" << endl;
+      indent_up();
+      f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");" << endl;
+      if (!(*f_iter)->is_oneway()) {
+        f_service_ << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          f_service_ << "return ";
+        }
+        f_service_ << "this.recv_" << funname << "();" << endl;
+      }
+      indent_down();
+      f_service_ << indent() << "} else {" << endl;
+      indent_up();
+      f_service_ << indent() << "var postData = this.send_" << funname << "(" << arglist
+                 << (arglist.empty() ? "" : ", ") << "true);" << endl;
+      f_service_ << indent() << "return this.output.getTransport()" << endl;
+      indent_up();
+      f_service_ << indent() << ".jqRequest(this, postData, arguments, this.recv_" << funname
+                 << ");" << endl;
+      indent_down();
+      indent_down();
+      f_service_ << indent() << "}" << endl;
+    } else { // Standard JavaScript ./gen-js
+      f_service_ << indent() << "this.send_" << funname << "(" << arglist
+                 << (arglist.empty() ? "" : ", ") << "callback); " << endl;
+      if (!(*f_iter)->is_oneway()) {
+        f_service_ << indent() << "if (!callback) {" << endl;
+        f_service_ << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          f_service_ << "  return ";
+        }
+        f_service_ << "this.recv_" << funname << "();" << endl;
+        f_service_ << indent() << "}" << endl;
+      }
+    }
+
+    indent_down();
+
+    f_service_ << "};" << endl << endl;
+
+    // Send function
+    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.send_"
+               << function_signature(*f_iter, "", !gen_node_) << " {" << endl;
+
+    indent_up();
+
+    std::string outputVar;
+    if (gen_node_) {
+      f_service_ << indent() << "var output = new this.pClass(this.output);" << endl;
+      outputVar = "output";
+    } else {
+      outputVar = "this.output";
+    }
+
+    std::string argsname = js_namespace(program_) + service_name_ + "_" + (*f_iter)->get_name()
+                           + "_args";
+
+    std::string messageType = (*f_iter)->is_oneway() ? "Thrift.MessageType.ONEWAY"
+                                                     : "Thrift.MessageType.CALL";
+
+    // Serialize the request header
+    if (gen_node_) {
+      f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name()
+                 << "', " << messageType << ", this.seqid());" << endl;
+    } else {
+      f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name()
+                 << "', " << messageType << ", this.seqid);" << endl;
+    }
+
+    f_service_ << indent() << "var args = new " << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    // Write to the stream
+    f_service_ << indent() << "args.write(" << outputVar << ");" << endl << indent() << outputVar
+               << ".writeMessageEnd();" << endl;
+
+    if (gen_node_) {
+      f_service_ << indent() << "return this.output.flush();" << endl;
+    } else {
+      if (gen_jquery_) {
+        f_service_ << indent() << "return this.output.getTransport().flush(callback);" << endl;
+      } else {
+        f_service_ << indent() << "if (callback) {" << endl;
+        f_service_ << indent() << "  var self = this;" << endl;
+        f_service_ << indent() << "  this.output.getTransport().flush(true, function() {" << endl;
+        f_service_ << indent() << "    var result = null;" << endl;
+        f_service_ << indent() << "    try {" << endl;
+        f_service_ << indent() << "      result = self.recv_" << funname << "();" << endl;
+        f_service_ << indent() << "    } catch (e) {" << endl;
+        f_service_ << indent() << "      result = e;" << endl;
+        f_service_ << indent() << "    }" << endl;
+        f_service_ << indent() << "    callback(result);" << endl;
+        f_service_ << indent() << "  });" << endl;
+        f_service_ << indent() << "} else {" << endl;
+        f_service_ << indent() << "  return this.output.getTransport().flush();" << endl;
+        f_service_ << indent() << "}" << endl;
+      }
+    }
+
+    indent_down();
+
+    f_service_ << "};" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = js_namespace(tservice->get_program()) + service_name_ + "_"
+                               + (*f_iter)->get_name() + "_result";
+
+      if (gen_node_) {
+        // Open function
+        f_service_ << endl << js_namespace(tservice->get_program()) << service_name_
+                   << "Client.prototype.recv_" << (*f_iter)->get_name()
+                   << " = function(input,mtype,rseqid) {" << endl;
+      } else {
+        t_struct noargs(program_);
+
+        t_function recv_function((*f_iter)->get_returntype(),
+                                 string("recv_") + (*f_iter)->get_name(),
+                                 &noargs);
+        // Open function
+        f_service_ << endl << js_namespace(tservice->get_program()) << service_name_
+                   << "Client.prototype." << function_signature(&recv_function) << " {" << endl;
+      }
+
+      indent_up();
+
+      std::string inputVar;
+      if (gen_node_) {
+        inputVar = "input";
+      } else {
+        inputVar = "this.input";
+      }
+
+      if (gen_node_) {
+        f_service_ << indent() << "var callback = this._reqs[rseqid] || function() {};" << endl
+                   << indent() << "delete this._reqs[rseqid];" << endl;
+      } else {
+        f_service_ << indent() << "var ret = this.input.readMessageBegin();" << endl << indent()
+                   << "var fname = ret.fname;" << endl << indent() << "var mtype = ret.mtype;"
+                   << endl << indent() << "var rseqid = ret.rseqid;" << endl;
+      }
+
+      f_service_ << indent() << "if (mtype == Thrift.MessageType.EXCEPTION) {" << endl << indent()
+                 << "  var x = new Thrift.TApplicationException();" << endl << indent()
+                 << "  x.read(" << inputVar << ");" << endl << indent() << "  " << inputVar
+                 << ".readMessageEnd();" << endl << indent() << "  " << render_recv_throw("x")
+                 << endl << indent() << "}" << endl;
+
+      f_service_ << indent() << "var result = new " << resultname << "();" << endl << indent()
+                 << "result.read(" << inputVar << ");" << endl;
+
+      f_service_ << indent() << inputVar << ".readMessageEnd();" << endl << endl;
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "if (null !== result." << (*x_iter)->get_name() << ") {" << endl
+                   << indent() << "  " << render_recv_throw("result." + (*x_iter)->get_name())
+                   << endl << indent() << "}" << endl;
+      }
+
+      // Careful, only return result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (null !== result.success) {" << endl << indent() << "  "
+                   << render_recv_return("result.success") << endl << indent() << "}" << endl;
+        f_service_ << indent()
+                   << render_recv_throw("'" + (*f_iter)->get_name() + " failed: unknown result'")
+                   << endl;
+      } else {
+        if (gen_node_) {
+          indent(f_service_) << "callback(null)" << endl;
+        } else {
+          indent(f_service_) << "return;" << endl;
+        }
+      }
+
+      // Close function
+      indent_down();
+      f_service_ << "};" << endl;
+    }
+  }
+
+  if (gen_ts_) {
+    f_service_ts_ << ts_indent() << "}" << endl;
+  }
+}
+
+std::string t_js_generator::render_recv_throw(std::string var) {
+  if (gen_node_) {
+    return "return callback(" + var + ");";
+  } else {
+    return "throw " + var + ";";
+  }
+}
+
+std::string t_js_generator::render_recv_return(std::string var) {
+  if (gen_node_) {
+    return "return callback(null, " + var + ");";
+  } else {
+    return "return " + var + ";";
+  }
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_js_generator::generate_deserialize_field(ofstream& out,
+                                                t_field* tfield,
+                                                string prefix,
+                                                bool inclass) {
+  (void)inclass;
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << name << " = input.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << (((t_base_type*)type)->is_binary() ? "readBinary()" : "readString()");
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool()";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte()";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16()";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32()";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64()";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble()";
+        break;
+      default:
+        throw "compiler error: no JS name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32()";
+    }
+
+    if (!gen_node_) {
+      out << ".value";
+    }
+
+    out << ";" << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a variable. This makes two key assumptions,
+ * first that there is a const char* variable named data that points to the
+ * buffer for deserialization, and that there is a variable protocol which
+ * is a reference to a TProtocol serialization object.
+ */
+void t_js_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  out << indent() << prefix << " = new " << js_type_namespace(tstruct->get_program())
+      << tstruct->get_name() << "();" << endl << indent() << prefix << ".read(input);" << endl;
+}
+
+void t_js_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+  string rtmp3 = tmp("_rtmp3");
+
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_i8, ktype);
+  t_field fvtype(g_type_i8, vtype);
+  t_field fetype(g_type_i8, etype);
+
+  out << indent() << "var " << size << " = 0;" << endl;
+  out << indent() << "var " << rtmp3 << ";" << endl;
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    out << indent() << prefix << " = {};" << endl << indent() << "var " << ktype << " = 0;" << endl
+        << indent() << "var " << vtype << " = 0;" << endl;
+
+    out << indent() << rtmp3 << " = input.readMapBegin();" << endl;
+    out << indent() << ktype << " = " << rtmp3 << ".ktype;" << endl;
+    out << indent() << vtype << " = " << rtmp3 << ".vtype;" << endl;
+    out << indent() << size << " = " << rtmp3 << ".size;" << endl;
+
+  } else if (ttype->is_set()) {
+
+    out << indent() << prefix << " = [];" << endl << indent() << "var " << etype << " = 0;" << endl
+        << indent() << rtmp3 << " = input.readSetBegin();" << endl << indent() << etype << " = "
+        << rtmp3 << ".etype;" << endl << indent() << size << " = " << rtmp3 << ".size;" << endl;
+
+  } else if (ttype->is_list()) {
+
+    out << indent() << prefix << " = [];" << endl << indent() << "var " << etype << " = 0;" << endl
+        << indent() << rtmp3 << " = input.readListBegin();" << endl << indent() << etype << " = "
+        << rtmp3 << ".etype;" << endl << indent() << size << " = " << rtmp3 << ".size;" << endl;
+  }
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for (var " << i << " = 0; " << i << " < " << size << "; ++" << i << ")" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    if (!gen_node_) {
+      out << indent() << "if (" << i << " > 0 ) {" << endl << indent()
+          << "  if (input.rstack.length > input.rpos[input.rpos.length -1] + 1) {" << endl
+          << indent() << "    input.rstack.pop();" << endl << indent() << "  }" << endl << indent()
+          << "}" << endl;
+    }
+
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "input.readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "input.readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "input.readListEnd();" << endl;
+  }
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_js_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("key");
+  string val = tmp("val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey, false, false) << ";" << endl;
+  indent(out) << declare_field(&fval, false, false) << ";" << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
+}
+
+void t_js_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << "var " << elem << " = null;" << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".push(" << elem << ");" << endl;
+}
+
+void t_js_generator::generate_deserialize_list_element(ofstream& out,
+                                                       t_list* tlist,
+                                                       string prefix) {
+  string elem = tmp("elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << "var " << elem << " = null;" << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".push(" << elem << ");" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_js_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + tfield->get_name());
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = tfield->get_name();
+
+    // Hack for when prefix is defined (always a hash ref)
+    if (!prefix.empty())
+      name = prefix + tfield->get_name();
+
+    indent(out) << "output.";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << (((t_base_type*)type)->is_binary() ? "writeBinary(" : "writeString(") << name << ")";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ")";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ")";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ")";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ")";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ")";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ")";
+        break;
+      default:
+        throw "compiler error: no JS name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ")";
+    }
+    out << ";" << endl;
+
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_js_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << prefix << ".write(output);" << endl;
+}
+
+/**
+ * Writes out a container
+ */
+void t_js_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  if (ttype->is_map()) {
+    indent(out) << "output.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
+                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
+                << "Thrift.objectLength(" << prefix << "));" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "output.writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
+                << prefix << ".length);" << endl;
+
+  } else if (ttype->is_list()) {
+
+    indent(out) << "output.writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
+                << ", " << prefix << ".length);" << endl;
+  }
+
+  if (ttype->is_map()) {
+    string kiter = tmp("kiter");
+    string viter = tmp("viter");
+    indent(out) << "for (var " << kiter << " in " << prefix << ")" << endl;
+    scope_up(out);
+    indent(out) << "if (" << prefix << ".hasOwnProperty(" << kiter << "))" << endl;
+    scope_up(out);
+    indent(out) << "var " << viter << " = " << prefix << "[" << kiter << "];" << endl;
+    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+    scope_down(out);
+    scope_down(out);
+
+  } else if (ttype->is_set()) {
+    string iter = tmp("iter");
+    indent(out) << "for (var " << iter << " in " << prefix << ")" << endl;
+    scope_up(out);
+    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << "))" << endl;
+    scope_up(out);
+    indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl;
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    scope_down(out);
+    scope_down(out);
+
+  } else if (ttype->is_list()) {
+    string iter = tmp("iter");
+    indent(out) << "for (var " << iter << " in " << prefix << ")" << endl;
+    scope_up(out);
+    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << "))" << endl;
+    scope_up(out);
+    indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl;
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    scope_down(out);
+    scope_down(out);
+  }
+
+  if (ttype->is_map()) {
+    indent(out) << "output.writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "output.writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "output.writeListEnd();" << endl;
+  }
+}
+
+/**
+ * Serializes the members of a map.
+ *
+ */
+void t_js_generator::generate_serialize_map_element(ofstream& out,
+                                                    t_map* tmap,
+                                                    string kiter,
+                                                    string viter) {
+  t_field kfield(tmap->get_key_type(), kiter);
+  generate_serialize_field(out, &kfield);
+
+  t_field vfield(tmap->get_val_type(), viter);
+  generate_serialize_field(out, &vfield);
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_js_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield);
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_js_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield);
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ */
+string t_js_generator::declare_field(t_field* tfield, bool init, bool obj) {
+  string result = "this." + tfield->get_name();
+
+  if (!obj) {
+    result = "var " + tfield->get_name();
+  }
+
+  if (init) {
+    t_type* type = get_true_type(tfield->get_type());
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        break;
+      case t_base_type::TYPE_STRING:
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+      case t_base_type::TYPE_DOUBLE:
+        result += " = null";
+        break;
+      default:
+        throw "compiler error: no JS initializer for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      result += " = null";
+    } else if (type->is_map()) {
+      result += " = null";
+    } else if (type->is_container()) {
+      result += " = null";
+    } else if (type->is_struct() || type->is_xception()) {
+      if (obj) {
+        result += " = new " + js_type_namespace(type->get_program()) + type->get_name() + "()";
+      } else {
+        result += " = null";
+      }
+    }
+  } else {
+    result += " = null";
+  }
+  return result;
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_js_generator::function_signature(t_function* tfunction,
+                                          string prefix,
+                                          bool include_callback) {
+
+  string str;
+
+  str = prefix + tfunction->get_name() + " = function(";
+
+  str += argument_list(tfunction->get_arglist(), include_callback);
+
+  str += ")";
+  return str;
+}
+
+/**
+ * Renders a field list
+ */
+string t_js_generator::argument_list(t_struct* tstruct, bool include_callback) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += (*f_iter)->get_name();
+  }
+
+  if (include_callback) {
+    if (!fields.empty()) {
+      result += ", ";
+    }
+    result += "callback";
+  }
+
+  return result;
+}
+
+/**
+ * Converts the parse type to a C++ enum string for the given type.
+ */
+string t_js_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "Thrift.Type.STRING";
+    case t_base_type::TYPE_BOOL:
+      return "Thrift.Type.BOOL";
+    case t_base_type::TYPE_I8:
+      return "Thrift.Type.BYTE";
+    case t_base_type::TYPE_I16:
+      return "Thrift.Type.I16";
+    case t_base_type::TYPE_I32:
+      return "Thrift.Type.I32";
+    case t_base_type::TYPE_I64:
+      return "Thrift.Type.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "Thrift.Type.DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "Thrift.Type.I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "Thrift.Type.STRUCT";
+  } else if (type->is_map()) {
+    return "Thrift.Type.MAP";
+  } else if (type->is_set()) {
+    return "Thrift.Type.SET";
+  } else if (type->is_list()) {
+    return "Thrift.Type.LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Converts a t_type to a TypeScript type (string).
+ * @param t_type Type to convert to TypeScript
+ * @return String TypeScript type
+ */
+string t_js_generator::ts_get_type(t_type* type) {
+  std::string ts_type;
+
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      ts_type = "string";
+      break;
+    case t_base_type::TYPE_BOOL:
+      ts_type = "boolean";
+      break;
+    case t_base_type::TYPE_I8:
+      ts_type = "any";
+      break;
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+    case t_base_type::TYPE_DOUBLE:
+      ts_type = "number";
+      break;
+    case t_base_type::TYPE_VOID:
+      ts_type = "void";
+    }
+  } else if (type->is_enum() || type->is_struct() || type->is_xception()) {
+    std::string type_name;
+    if (type->get_program()) {
+      type_name = js_namespace(type->get_program());
+    }
+    type_name.append(type->get_name());
+    ts_type = type_name;
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+
+    ts_type = ts_get_type(etype) + "[]";
+  } else if (type->is_map()) {
+    string ktype = ts_get_type(((t_map*)type)->get_key_type());
+    string vtype = ts_get_type(((t_map*)type)->get_val_type());
+
+
+    if (ktype == "number" || ktype == "string" ) {
+      ts_type = "{ [k: " + ktype + "]: " + vtype + "; }";
+    } else if ((((t_map*)type)->get_key_type())->is_enum()) {
+      // Not yet supported (enum map): https://github.com/Microsoft/TypeScript/pull/2652
+      //ts_type = "{ [k: " + ktype + "]: " + vtype + "; }";
+      ts_type = "{ [k: number /*" + ktype + "*/]: " + vtype + "; }";
+    } else {
+      ts_type = "any";
+    }
+  }
+
+  return ts_type;
+}
+
+/**
+ * Renders a TypeScript function signature of the form 'name(args: types): type;'
+ *
+ * @param t_function Function definition
+ * @param bool in-/exclude the callback argument
+ * @return String of rendered function definition
+ */
+std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback) {
+  string str;
+  const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  str = tfunction->get_name() + "(";
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    str += (*f_iter)->get_name() + ts_get_req(*f_iter) + ": " + ts_get_type((*f_iter)->get_type());
+
+    if (f_iter + 1 != fields.end() || (include_callback && fields.size() > 0)) {
+      str += ", ";
+    }
+  }
+
+  if (include_callback) {
+    str += "callback: Function): ";
+
+    if (gen_jquery_) {
+      str += "JQueryXHR;";
+    } else {
+      str += "void;";
+    }
+  } else {
+    str += "): " + ts_get_type(tfunction->get_returntype()) + ";";
+  }
+
+  return str;
+}
+
+/**
+ * Takes a name and produces a valid NodeJS identifier from it
+ *
+ * @param name The name which shall become a valid NodeJS identifier
+ * @return The modified name with the updated identifier
+ */
+std::string t_js_generator::make_valid_nodeJs_identifier(std::string const& name) {
+  std::string str = name;
+  if (str.empty()) {
+    return str;
+  }
+
+  // tests rely on this
+  assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
+
+  // if the first letter is a number, we add an additional underscore in front of it
+  char c = str.at(0);
+  if (('0' <= c) && (c <= '9')) {
+    str = "_" + str;
+  }
+
+  // following chars: letter, number or underscore
+  for (size_t i = 0; i < str.size(); ++i) {
+    c = str.at(i);
+    if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9'))
+        && ('_' != c) && ('$' != c)) {
+      str.replace(i, 1, "_");
+    }
+  }
+
+  return str;
+}
+
+THRIFT_REGISTER_GENERATOR(js,
+                          "Javascript",
+                          "    jquery:          Generate jQuery compatible code.\n"
+                          "    node:            Generate node.js compatible code.\n"
+                          "    ts:              Generate TypeScript definition files.\n")


[14/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_go_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc
new file mode 100644
index 0000000..9919cb1
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc
@@ -0,0 +1,3685 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/*
+ * This file is programmatically sanitized for style:
+ * astyle --style=1tbs -f -p -H -j -U t_go_generator.cc
+ *
+ * The output of astyle should not be taken unquestioningly, but it is a good
+ * guide for ensuring uniformity and readability.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+#include <algorithm>
+#include <clocale>
+#include "thrift/platform.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * A helper for automatically formatting the emitted Go code from the Thrift
+ * IDL per the Go style guide.
+ *
+ * Returns:
+ *  - true, if the formatting process succeeded.
+ *  - false, if the formatting process failed, which means the basic output was
+ *           still generated.
+ */
+bool format_go_output(const string& file_path);
+
+const string DEFAULT_THRIFT_IMPORT = "git.apache.org/thrift.git/lib/go/thrift";
+static std::string package_flag;
+
+/**
+ * Go code generator.
+ */
+class t_go_generator : public t_generator {
+public:
+  t_go_generator(t_program* program,
+                 const std::map<std::string, std::string>& parsed_options,
+                 const std::string& option_string)
+    : t_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+
+    gen_thrift_import_ = DEFAULT_THRIFT_IMPORT;
+    gen_package_prefix_ = "";
+    package_flag = "";
+    read_write_private_ = false;
+    ignore_initialisms_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("package_prefix") == 0) {
+        gen_package_prefix_ = (iter->second);
+      } else if( iter->first.compare("thrift_import") == 0) {
+        gen_thrift_import_ = (iter->second);
+      } else if( iter->first.compare("package") == 0) {
+        package_flag = (iter->second);
+      } else if( iter->first.compare("read_write_private") == 0) {
+        read_write_private_ = true;
+      } else if( iter->first.compare("ignore_initialisms") == 0) {
+        ignore_initialisms_ =  true;
+      } else {
+        throw "unknown option go:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-go";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_const_value(t_type* type, t_const_value* value, const string& name);
+
+  /**
+   * Struct generation code
+   */
+
+  void generate_go_struct(t_struct* tstruct, bool is_exception);
+  void generate_go_struct_definition(std::ofstream& out,
+                                     t_struct* tstruct,
+                                     bool is_xception = false,
+                                     bool is_result = false,
+                                     bool is_args = false);
+  void generate_go_struct_initializer(std::ofstream& out,
+                                      t_struct* tstruct,
+                                      bool is_args_or_result = false);
+  void generate_isset_helpers(std::ofstream& out,
+                              t_struct* tstruct,
+                              const string& tstruct_name,
+                              bool is_result = false);
+  void generate_countsetfields_helper(std::ofstream& out,
+                                      t_struct* tstruct,
+                                      const string& tstruct_name,
+                                      bool is_result = false);
+  void generate_go_struct_reader(std::ofstream& out,
+                                 t_struct* tstruct,
+                                 const string& tstruct_name,
+                                 bool is_result = false);
+  void generate_go_struct_writer(std::ofstream& out,
+                                 t_struct* tstruct,
+                                 const string& tstruct_name,
+                                 bool is_result = false,
+                                 bool uses_countsetfields = false);
+  void generate_go_function_helpers(t_function* tfunction);
+  void get_publicized_name_and_def_value(t_field* tfield,
+                                         string* OUT_pub_name,
+                                         t_const_value** OUT_def_value) const;
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_remote(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  bool declare,
+                                  std::string prefix = "",
+                                  bool inclass = false,
+                                  bool coerceData = false,
+                                  bool inkey = false,
+                                  bool in_container = false,
+                                  bool use_true_type = false);
+
+  void generate_deserialize_struct(std::ofstream& out,
+                                   t_struct* tstruct,
+                                   bool is_pointer_field,
+                                   bool declare,
+                                   std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out,
+                                      t_type* ttype,
+                                      bool pointer_field,
+                                      bool declare,
+                                      std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out,
+                                        t_set* tset,
+                                        bool declare,
+                                        std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out,
+                                        t_map* tmap,
+                                        bool declare,
+                                        std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         bool declare,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out,
+                                t_field* tfield,
+                                std::string prefix = "",
+                                bool inkey = false);
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out,
+                                    t_type* ttype,
+                                    bool pointer_field,
+                                    std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_go_docstring(std::ofstream& out, t_struct* tstruct);
+
+  void generate_go_docstring(std::ofstream& out, t_function* tfunction);
+
+  void generate_go_docstring(std::ofstream& out,
+                             t_doc* tdoc,
+                             t_struct* tstruct,
+                             const char* subheader);
+
+  void generate_go_docstring(std::ofstream& out, t_doc* tdoc);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string go_autogen_comment();
+  std::string go_package();
+  std::string go_imports_begin(bool consts);
+  std::string go_imports_end();
+  std::string render_includes(bool consts);
+  std::string render_included_programs(string& unused_protection);
+  std::string render_import_protection();
+  std::string render_fastbinary_includes();
+  std::string declare_argument(t_field* tfield);
+  std::string render_field_initial_value(t_field* tfield, const string& name, bool optional_field);
+  std::string type_name(t_type* ttype);
+  std::string module_name(t_type* ttype);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string function_signature_if(t_function* tfunction,
+                                    std::string prefix = "",
+                                    bool addError = false);
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string type_to_go_type(t_type* ttype);
+  std::string type_to_go_type_with_opt(t_type* ttype,
+                                       bool optional_field);
+  std::string type_to_go_key_type(t_type* ttype);
+  std::string type_to_spec_args(t_type* ttype);
+
+  static std::string get_real_go_module(const t_program* program) {
+
+    if (!package_flag.empty()) {
+      return package_flag;
+    }
+    std::string real_module = program->get_namespace("go");
+    if (!real_module.empty()) {
+      return real_module;
+    }
+
+    return lowercase(program->get_name());
+  }
+
+private:
+  std::string gen_package_prefix_;
+  std::string gen_thrift_import_;
+  bool read_write_private_;
+  bool ignore_initialisms_;
+
+  /**
+   * File streams
+   */
+
+  std::ofstream f_types_;
+  std::string f_types_name_;
+  std::ofstream f_consts_;
+  std::string f_consts_name_;
+  std::stringstream f_const_values_;
+
+  std::string package_name_;
+  std::string package_dir_;
+  std::string read_method_name_;
+  std::string write_method_name_;
+
+  std::set<std::string> commonInitialisms;
+
+  std::string camelcase(const std::string& value) const;
+  void fix_common_initialism(std::string& value, int i) const;
+  std::string publicize(const std::string& value, bool is_args_or_result = false) const;
+  std::string privatize(const std::string& value) const;
+  std::string new_prefix(const std::string& value) const;
+  static std::string variable_name_to_go_name(const std::string& value);
+  static bool is_pointer_field(t_field* tfield, bool in_container = false);
+  static bool omit_initialization(t_field* tfield);
+};
+
+// returns true if field initialization can be omitted since it has corresponding go type zero value
+// or default value is not set
+bool t_go_generator::omit_initialization(t_field* tfield) {
+  t_const_value* value = tfield->get_value();
+  if (!value) {
+    return true;
+  }
+  t_type* type = tfield->get_type()->get_true_type();
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "";
+
+    case t_base_type::TYPE_STRING:
+      if (((t_base_type*)type)->is_binary()) {
+        //[]byte are always inline
+        return false;
+      }
+      // strings are pointers if has no default
+      return value->get_string().empty();
+
+    case t_base_type::TYPE_BOOL:
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      return value->get_integer() == 0;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        return value->get_integer() == 0;
+      } else {
+        return value->get_double() == 0.;
+      }
+    }
+  }
+  return false;
+}
+
+// Returns true if the type need a reference if used as optional without default
+static bool type_need_reference(t_type* type) {
+  type = type->get_true_type();
+  if (type->is_map() || type->is_set() || type->is_list() || type->is_struct()
+      || type->is_xception() || (type->is_string() && ((t_base_type*)type)->is_binary())) {
+    return false;
+  }
+  return true;
+}
+
+// returns false if field could not use comparison to default value as !IsSet*
+bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value) {
+  (void)in_container_value;
+  if (tfield->annotations_.count("cpp.ref") != 0) {
+    return true;
+  }
+  t_type* type = tfield->get_type()->get_true_type();
+  // Structs in containers are pointers
+  if (type->is_struct() || type->is_xception()) {
+    return true;
+  }
+  if (!(tfield->get_req() == t_field::T_OPTIONAL)) {
+    return false;
+  }
+
+  bool has_default = tfield->get_value();
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "";
+
+    case t_base_type::TYPE_STRING:
+      if (((t_base_type*)type)->is_binary()) {
+        //[]byte are always inline
+        return false;
+      }
+      // strings are pointers if has no default
+      return !has_default;
+
+    case t_base_type::TYPE_BOOL:
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+    case t_base_type::TYPE_DOUBLE:
+      return !has_default;
+    }
+  } else if (type->is_enum()) {
+    return !has_default;
+  } else if (type->is_struct() || type->is_xception()) {
+    return true;
+  } else if (type->is_map()) {
+    return has_default;
+  } else if (type->is_set()) {
+    return has_default;
+  } else if (type->is_list()) {
+    return has_default;
+  } else if (type->is_typedef()) {
+    return has_default;
+  }
+
+  throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
+}
+
+std::string t_go_generator::camelcase(const std::string& value) const {
+  std::string value2(value);
+  std::setlocale(LC_ALL, "C"); // set locale to classic
+
+  // Fix common initialism in first word
+  fix_common_initialism(value2, 0);
+
+  // as long as we are changing things, let's change _ followed by lowercase to
+  // capital and fix common initialisms
+  for (std::string::size_type i = 1; i < value2.size() - 1; ++i) {
+    if (value2[i] == '_') {
+      if (islower(value2[i + 1])) {
+        value2.replace(i, 2, 1, toupper(value2[i + 1]));
+      }
+      fix_common_initialism(value2, i);
+    }
+  }
+
+  return value2;
+}
+
+// Checks to see if the word starting at i in value contains a common initialism
+// and if so replaces it with the upper case version of the word.
+void t_go_generator::fix_common_initialism(std::string& value, int i) const {
+  if (!ignore_initialisms_) {
+    size_t wordLen = value.find('_', i);
+    if (wordLen != std::string::npos) {
+      wordLen -= i;
+    }
+    std::string word = value.substr(i, wordLen);
+    std::transform(word.begin(), word.end(), word.begin(), ::toupper);
+    if (commonInitialisms.find(word) != commonInitialisms.end()) {
+      value.replace(i, word.length(), word);
+    }
+  }
+}
+
+std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result) const {
+  if (value.size() <= 0) {
+    return value;
+  }
+
+  std::string value2(value), prefix;
+
+  string::size_type dot_pos = value.rfind('.');
+  if (dot_pos != string::npos) {
+    prefix = value.substr(0, dot_pos + 1) + prefix;
+    value2 = value.substr(dot_pos + 1);
+  }
+
+  if (!isupper(value2[0])) {
+    value2[0] = toupper(value2[0]);
+  }
+
+  value2 = camelcase(value2);
+
+  // final length before further checks, the string may become longer
+  size_t len_before = value2.length();
+
+  // IDL identifiers may start with "New" which interferes with the CTOR pattern
+  // Adding an extra underscore to all those identifiers solves this
+  if ((len_before >= 3) && (value2.substr(0, 3) == "New")) {
+    value2 += '_';
+  }
+
+  // IDL identifiers may end with "Args"/"Result" which interferes with the implicit service
+  // function structs
+  // Adding another extra underscore to all those identifiers solves this
+  // Suppress this check for the actual helper struct names
+  if (!is_args_or_result) {
+    bool ends_with_args = (len_before >= 4) && (value2.substr(len_before - 4, 4) == "Args");
+    bool ends_with_rslt = (len_before >= 6) && (value2.substr(len_before - 6, 6) == "Result");
+    if (ends_with_args || ends_with_rslt) {
+      value2 += '_';
+    }
+  }
+
+  // Avoid naming collisions with other services
+  if (is_args_or_result) {
+    prefix += publicize(service_name_);
+  }
+
+  return prefix + value2;
+}
+
+std::string t_go_generator::new_prefix(const std::string& value) const {
+  if (value.size() <= 0) {
+    return value;
+  }
+
+  string::size_type dot_pos = value.rfind('.');
+  if (dot_pos != string::npos) {
+    return value.substr(0, dot_pos + 1) + "New" + publicize(value.substr(dot_pos + 1));
+  }
+  return "New" + publicize(value);
+}
+
+std::string t_go_generator::privatize(const std::string& value) const {
+  if (value.size() <= 0) {
+    return value;
+  }
+
+  std::string value2(value);
+
+  if (!islower(value2[0])) {
+    value2[0] = tolower(value2[0]);
+  }
+
+  value2 = camelcase(value2);
+
+  return value2;
+}
+
+std::string t_go_generator::variable_name_to_go_name(const std::string& value) {
+  if (value.size() <= 0) {
+    return value;
+  }
+
+  std::string value2(value);
+  std::transform(value2.begin(), value2.end(), value2.begin(), ::tolower);
+
+  switch (value[0]) {
+  case 'b':
+  case 'B':
+    if (value2 != "break") {
+      return value;
+    }
+
+    break;
+
+  case 'c':
+  case 'C':
+    if (value2 != "case" && value2 != "chan" && value2 != "const" && value2 != "continue") {
+      return value;
+    }
+
+    break;
+
+  case 'd':
+  case 'D':
+    if (value2 != "default" && value2 != "defer") {
+      return value;
+    }
+
+    break;
+
+  case 'e':
+  case 'E':
+    if (value2 != "else" && value2 != "error") {
+      return value;
+    }
+
+    break;
+
+  case 'f':
+  case 'F':
+    if (value2 != "fallthrough" && value2 != "for" && value2 != "func") {
+      return value;
+    }
+
+    break;
+
+  case 'g':
+  case 'G':
+    if (value2 != "go" && value2 != "goto") {
+      return value;
+    }
+
+    break;
+
+  case 'i':
+  case 'I':
+    if (value2 != "if" && value2 != "import" && value2 != "interface") {
+      return value;
+    }
+
+    break;
+
+  case 'm':
+  case 'M':
+    if (value2 != "map") {
+      return value;
+    }
+
+    break;
+
+  case 'p':
+  case 'P':
+    if (value2 != "package") {
+      return value;
+    }
+
+    break;
+
+  case 'r':
+  case 'R':
+    if (value2 != "range" && value2 != "return") {
+      return value;
+    }
+
+    break;
+
+  case 's':
+  case 'S':
+    if (value2 != "select" && value2 != "struct" && value2 != "switch") {
+      return value;
+    }
+
+    break;
+
+  case 't':
+  case 'T':
+    if (value2 != "type") {
+      return value;
+    }
+
+    break;
+
+  case 'v':
+  case 'V':
+    if (value2 != "var") {
+      return value;
+    }
+
+    break;
+
+  default:
+    return value;
+  }
+
+  return value2 + "_a1";
+}
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_go_generator::init_generator() {
+  // Make output directory
+  string module = get_real_go_module(program_);
+  string target = module;
+  package_dir_ = get_out_dir();
+
+  // This set is taken from https://github.com/golang/lint/blob/master/lint.go#L692
+  commonInitialisms.insert("API");
+  commonInitialisms.insert("ASCII");
+  commonInitialisms.insert("CPU");
+  commonInitialisms.insert("CSS");
+  commonInitialisms.insert("DNS");
+  commonInitialisms.insert("EOF");
+  commonInitialisms.insert("GUID");
+  commonInitialisms.insert("HTML");
+  commonInitialisms.insert("HTTP");
+  commonInitialisms.insert("HTTPS");
+  commonInitialisms.insert("ID");
+  commonInitialisms.insert("IP");
+  commonInitialisms.insert("JSON");
+  commonInitialisms.insert("LHS");
+  commonInitialisms.insert("QPS");
+  commonInitialisms.insert("RAM");
+  commonInitialisms.insert("RHS");
+  commonInitialisms.insert("RPC");
+  commonInitialisms.insert("SLA");
+  commonInitialisms.insert("SMTP");
+  commonInitialisms.insert("SSH");
+  commonInitialisms.insert("TCP");
+  commonInitialisms.insert("TLS");
+  commonInitialisms.insert("TTL");
+  commonInitialisms.insert("UDP");
+  commonInitialisms.insert("UI");
+  commonInitialisms.insert("UID");
+  commonInitialisms.insert("UUID");
+  commonInitialisms.insert("URI");
+  commonInitialisms.insert("URL");
+  commonInitialisms.insert("UTF8");
+  commonInitialisms.insert("VM");
+  commonInitialisms.insert("XML");
+  commonInitialisms.insert("XSRF");
+  commonInitialisms.insert("XSS");
+
+  // names of read and write methods
+  if (read_write_private_) {
+    read_method_name_ = "read";
+    write_method_name_ = "write";
+  } else {
+    read_method_name_ = "Read";
+    write_method_name_ = "Write";
+  }
+
+  while (true) {
+    // TODO: Do better error checking here.
+    MKDIR(package_dir_.c_str());
+
+    if (module.empty()) {
+      break;
+    }
+
+    string::size_type pos = module.find('.');
+
+    if (pos == string::npos) {
+      package_dir_ += "/";
+      package_dir_ += module;
+      package_name_ = module;
+      module.clear();
+    } else {
+      package_dir_ += "/";
+      package_dir_ += module.substr(0, pos);
+      module.erase(0, pos + 1);
+    }
+  }
+
+  string::size_type loc;
+
+  while ((loc = target.find(".")) != string::npos) {
+    target.replace(loc, 1, 1, '/');
+  }
+
+  // Make output files
+  f_types_name_ = package_dir_ + "/" + program_name_ + ".go";
+  f_types_.open(f_types_name_.c_str());
+
+  f_consts_name_ = package_dir_ + "/" + program_name_ + "-consts.go";
+  f_consts_.open(f_consts_name_.c_str());
+
+  vector<t_service*> services = program_->get_services();
+  vector<t_service*>::iterator sv_iter;
+
+  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+    string service_dir = package_dir_ + "/" + underscore((*sv_iter)->get_name()) + "-remote";
+    MKDIR(service_dir.c_str());
+  }
+
+  // Print header
+  f_types_ << go_autogen_comment() << go_package() << render_includes(false);
+
+  f_consts_ << go_autogen_comment() << go_package() << render_includes(true);
+
+  f_const_values_ << endl << "func init() {" << endl;
+
+  // Create file for the GoUnusedProtection__ variable
+  string f_unused_prot_name_ = package_dir_ + "/" + "GoUnusedProtection__.go";
+  ofstream f_unused_prot_;
+  f_unused_prot_.open(f_unused_prot_name_.c_str());
+  f_unused_prot_ << go_autogen_comment() << go_package() << render_import_protection();
+  f_unused_prot_.close();
+}
+
+
+string t_go_generator::render_included_programs(string& unused_protection) {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+
+  unused_protection = "";
+
+  string local_namespace = program_->get_namespace("go");
+  for (size_t i = 0; i < includes.size(); ++i) {
+    if (!local_namespace.empty() && local_namespace == includes[i]->get_namespace("go")) {
+      continue;
+    }
+
+    string go_module = get_real_go_module(includes[i]);
+    size_t found = 0;
+    for (size_t j = 0; j < go_module.size(); j++) {
+      // Import statement uses slashes ('/') in namespace
+      if (go_module[j] == '.') {
+        go_module[j] = '/';
+        found = j + 1;
+      }
+    }
+
+    result += "\t\"" + gen_package_prefix_ + go_module + "\"\n";
+    unused_protection += "var _ = " + go_module.substr(found) + ".GoUnusedProtection__\n";
+  }
+
+  return result;
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program.
+ * If consts include the additional imports.
+ */
+string t_go_generator::render_includes(bool consts) {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  string unused_prot = "";
+
+  string local_namespace = program_->get_namespace("go");
+  for (size_t i = 0; i < includes.size(); ++i) {
+    if (!local_namespace.empty() && local_namespace == includes[i]->get_namespace("go")) {
+      continue;
+    }
+
+    string go_module = get_real_go_module(includes[i]);
+    size_t found = 0;
+    for (size_t j = 0; j < go_module.size(); j++) {
+      // Import statement uses slashes ('/') in namespace
+      if (go_module[j] == '.') {
+        go_module[j] = '/';
+        found = j + 1;
+      }
+    }
+
+    result += "\t\"" + gen_package_prefix_ + go_module + "\"\n";
+    unused_prot += "var _ = " + go_module.substr(found) + ".GoUnusedProtection__\n";
+  }
+
+  if (includes.size() > 0) {
+    result += "\n";
+  }
+
+  return go_imports_begin(consts) + result + go_imports_end() + unused_prot;
+}
+
+string t_go_generator::render_import_protection() {
+  return string("var GoUnusedProtection__ int;\n\n");
+}
+
+/**
+ * Renders all the imports necessary to use the accelerated TBinaryProtocol
+ */
+string t_go_generator::render_fastbinary_includes() {
+  return "";
+}
+
+/**
+ * Autogen'd comment
+ */
+string t_go_generator::go_autogen_comment() {
+  return
+        std::string() +
+        "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+        "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\n";
+}
+
+/**
+ * Prints standard thrift package
+ */
+string t_go_generator::go_package() {
+  return string("package ") + package_name_ + "\n\n";
+}
+
+/**
+ * Render the beginning of the import statement.
+ * If consts include the additional imports.
+ */
+string t_go_generator::go_imports_begin(bool consts) {
+  string extra;
+  // If not writing constants, and there are enums, need extra imports.
+  if (!consts && get_program()->get_enums().size() > 0) {
+    extra =
+      "\t\"database/sql/driver\"\n"
+      "\t\"errors\"\n";
+  }
+  return string(
+      "import (\n"
+      "\t\"bytes\"\n"
+      + extra +
+      "\t\"fmt\"\n"
+      "\t\"" + gen_thrift_import_ + "\"\n");
+}
+
+/**
+ * End the import statement, include undscore-assignments
+ *
+ * These "_ =" prevent the go compiler complaining about used imports.
+ * This will have to do in lieu of more intelligent import statement construction
+ */
+string t_go_generator::go_imports_end() {
+  return string(
+      ")\n\n"
+      "// (needed to ensure safety because of naive import list construction.)\n"
+      "var _ = thrift.ZERO\n"
+      "var _ = fmt.Printf\n"
+      "var _ = bytes.Equal\n\n");
+}
+
+/**
+ * Closes the type files
+ */
+void t_go_generator::close_generator() {
+  f_const_values_ << "}" << endl << endl;
+  f_consts_ << f_const_values_.str();
+
+  // Close types and constants files
+  f_consts_.close();
+  f_types_.close();
+  format_go_output(f_types_name_);
+  format_go_output(f_consts_name_);
+}
+
+/**
+ * Generates a typedef.
+ *
+ * @param ttypedef The type definition
+ */
+void t_go_generator::generate_typedef(t_typedef* ttypedef) {
+  generate_go_docstring(f_types_, ttypedef);
+  string new_type_name(publicize(ttypedef->get_symbolic()));
+  string base_type(type_to_go_type(ttypedef->get_type()));
+
+  if (base_type == new_type_name) {
+    return;
+  }
+
+  f_types_ << "type " << new_type_name << " " << base_type << endl << endl;
+  // Generate a convenience function that converts an instance of a type
+  // (which may be a constant) into a pointer to an instance of a type.
+  f_types_ << "func " << new_type_name << "Ptr(v " << new_type_name << ") *" << new_type_name
+           << " { return &v }" << endl << endl;
+}
+
+/**
+ * Generates code for an enumerated type. Done using a class to scope
+ * the values.
+ *
+ * @param tenum The enumeration
+ */
+void t_go_generator::generate_enum(t_enum* tenum) {
+  std::ostringstream to_string_mapping, from_string_mapping;
+  std::string tenum_name(publicize(tenum->get_name()));
+  generate_go_docstring(f_types_, tenum);
+  f_types_ << "type " << tenum_name << " int64" << endl << "const (" << endl;
+
+  to_string_mapping << indent() << "func (p " << tenum_name << ") String() string {" << endl;
+  to_string_mapping << indent() << "  switch p {" << endl;
+
+  from_string_mapping << indent() << "func " << tenum_name << "FromString(s string) (" << tenum_name
+                      << ", error) {" << endl;
+  from_string_mapping << indent() << "  switch s {" << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  int value = -1;
+
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    value = (*c_iter)->get_value();
+
+    string iter_std_name(escape_string((*c_iter)->get_name()));
+    string iter_name((*c_iter)->get_name());
+    f_types_ << indent() << "  " << tenum_name << "_" << iter_name << ' ' << tenum_name << " = "
+             << value << endl;
+    // Dictionaries to/from string names of enums
+    to_string_mapping << indent() << "  case " << tenum_name << "_" << iter_name << ": return \""
+                      << iter_std_name << "\"" << endl;
+
+    if (iter_std_name != escape_string(iter_name)) {
+      from_string_mapping << indent() << "  case \"" << iter_std_name << "\", \""
+                          << escape_string(iter_name) << "\": return " << tenum_name << "_"
+                          << iter_name << ", nil " << endl;
+    } else {
+      from_string_mapping << indent() << "  case \"" << iter_std_name << "\": return " << tenum_name
+                          << "_" << iter_name << ", nil " << endl;
+    }
+  }
+
+  to_string_mapping << indent() << "  }" << endl;
+  to_string_mapping << indent() << "  return \"<UNSET>\"" << endl;
+  to_string_mapping << indent() << "}" << endl;
+  from_string_mapping << indent() << "  }" << endl;
+  from_string_mapping << indent() << "  return " << tenum_name << "(0),"
+                      << " fmt.Errorf(\"not a valid " << tenum_name << " string\")" << endl;
+  from_string_mapping << indent() << "}" << endl;
+
+  f_types_ << ")" << endl << endl << to_string_mapping.str() << endl << from_string_mapping.str()
+           << endl << endl;
+
+  // Generate a convenience function that converts an instance of an enum
+  // (which may be a constant) into a pointer to an instance of that enum
+  // type.
+  f_types_ << "func " << tenum_name << "Ptr(v " << tenum_name << ") *" << tenum_name
+           << " { return &v }" << endl << endl;
+
+  // Generate MarshalText
+  f_types_ << "func (p " << tenum_name << ") MarshalText() ([]byte, error) {" << endl;
+  f_types_ << "return []byte(p.String()), nil" << endl;
+  f_types_ << "}" << endl << endl;
+
+  // Generate UnmarshalText
+  f_types_ << "func (p *" << tenum_name << ") UnmarshalText(text []byte) error {" << endl;
+  f_types_ << "q, err := " << tenum_name << "FromString(string(text))" << endl;
+  f_types_ << "if (err != nil) {" << endl << "return err" << endl << "}" << endl;
+  f_types_ << "*p = q" << endl;
+  f_types_ << "return nil" << endl;
+  f_types_ << "}" << endl << endl;
+
+  // Generate Scan for sql.Scanner interface
+  f_types_ << "func (p *" << tenum_name << ") Scan(value interface{}) error {" <<endl;
+  f_types_ << "v, ok := value.(int64)" <<endl;
+  f_types_ << "if !ok {" <<endl;
+  f_types_ << "return errors.New(\"Scan value is not int64\")" <<endl;
+  f_types_ << "}" <<endl;
+  f_types_ << "*p = " << tenum_name << "(v)" << endl;
+  f_types_ << "return nil" << endl;
+  f_types_ << "}" << endl << endl;
+
+  // Generate Value for driver.Valuer interface
+  f_types_ << "func (p * " << tenum_name << ") Value() (driver.Value, error) {" <<endl;
+  f_types_ << "  if p == nil {" << endl;
+  f_types_ << "    return nil, nil" << endl;
+  f_types_ << "  }" << endl;
+  f_types_ << "return int64(*p), nil" << endl;
+  f_types_ << "}" << endl;
+
+}
+
+/**
+ * Generate a constant value
+ */
+void t_go_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = publicize(tconst->get_name());
+  t_const_value* value = tconst->get_value();
+
+  if (type->is_base_type() || type->is_enum()) {
+    indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl;
+  } else {
+    f_const_values_ << indent() << name << " = " << render_const_value(type, value, name) << endl
+                    << endl;
+
+    f_consts_ << indent() << "var " << name << " " << type_to_go_type(type) << endl;
+  }
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name) {
+  type = get_true_type(type);
+  std::ostringstream out;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      if (((t_base_type*)type)->is_binary()) {
+        out << "[]byte(\"" << get_escaped_string(value) << "\")";
+      } else {
+        out << '"' << get_escaped_string(value) << '"';
+      }
+
+      break;
+
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+
+      break;
+
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    indent(out) << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << "&" << publicize(type_name(type)) << "{";
+    indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+
+      out << endl << indent() << publicize(v_iter->first->get_string()) << ": "
+          << render_const_value(field_type, v_iter->second, name) << "," << endl;
+    }
+
+    indent_down();
+    out << "}";
+
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    out << "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl;
+    indent_up();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent() << render_const_value(ktype, v_iter->first, name) << ": "
+          << render_const_value(vtype, v_iter->second, name) << "," << endl;
+    }
+
+    indent_down();
+    out << indent() << "}";
+  } else if (type->is_list()) {
+    t_type* etype = ((t_list*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    out << "[]" << type_to_go_type(etype) << "{" << endl;
+    indent_up();
+    vector<t_const_value*>::const_iterator v_iter;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent() << render_const_value(etype, *v_iter, name) << ", ";
+    }
+
+    indent_down();
+    out << indent() << "}";
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    out << "map[" << type_to_go_key_type(etype) << "]struct{}{" << endl;
+    indent_up();
+    vector<t_const_value*>::const_iterator v_iter;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent() << render_const_value(etype, *v_iter, name) << ": struct{}{}," << endl;
+    }
+
+    indent_down();
+    out << indent() << "}";
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+
+  return out.str();
+}
+
+/**
+ * Generates a go struct
+ */
+void t_go_generator::generate_struct(t_struct* tstruct) {
+  generate_go_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_go_generator::generate_xception(t_struct* txception) {
+  generate_go_struct(txception, true);
+}
+
+/**
+ * Generates a go struct
+ */
+void t_go_generator::generate_go_struct(t_struct* tstruct, bool is_exception) {
+  generate_go_struct_definition(f_types_, tstruct, is_exception);
+}
+
+void t_go_generator::get_publicized_name_and_def_value(t_field* tfield,
+                                                       string* OUT_pub_name,
+                                                       t_const_value** OUT_def_value) const {
+  const string base_field_name = tfield->get_name();
+  const string escaped_field_name = escape_string(base_field_name);
+  *OUT_pub_name = publicize(escaped_field_name);
+  *OUT_def_value = tfield->get_value();
+}
+
+void t_go_generator::generate_go_struct_initializer(ofstream& out,
+                                                    t_struct* tstruct,
+                                                    bool is_args_or_result) {
+  out << publicize(type_name(tstruct), is_args_or_result) << "{";
+  const vector<t_field*>& members = tstruct->get_members();
+  for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();
+       ++m_iter) {
+    bool pointer_field = is_pointer_field(*m_iter);
+    string publicized_name;
+    t_const_value* def_value;
+    get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
+    if (!pointer_field && def_value != NULL && !omit_initialization(*m_iter)) {
+      out << endl << indent() << publicized_name << ": "
+          << render_field_initial_value(*m_iter, (*m_iter)->get_name(), pointer_field) << ","
+          << endl;
+    }
+  }
+
+  out << "}" << endl;
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_go_generator::generate_go_struct_definition(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   bool is_exception,
+                                                   bool is_result,
+                                                   bool is_args) {
+  const vector<t_field*>& members = tstruct->get_members();
+  const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  std::string tstruct_name(publicize(tstruct->get_name(), is_args || is_result));
+  generate_go_docstring(out, tstruct);
+  out << indent() << "type " << tstruct_name << " struct {" << endl;
+  /*
+     Here we generate the structure specification for the fastbinary codec.
+     These specifications have the following structure:
+     thrift_spec -> tuple of item_spec
+     item_spec -> nil | (tag, type_enum, name, spec_args, default)
+     tag -> integer
+     type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ...
+     name -> string_literal
+     default -> nil  # Handled by __init__
+     spec_args -> nil  # For simple types
+                | (type_enum, spec_args)  # Value type for list/set
+                | (type_enum, spec_args, type_enum, spec_args)
+                  # Key and value for map
+                | (class_name, spec_args_ptr) # For struct/exception
+     class_name -> identifier  # Basically a pointer to the class
+     spec_args_ptr -> expression  # just class_name.spec_args
+
+     TODO(dreiss): Consider making this work for structs with negative tags.
+  */
+  // TODO(dreiss): Look into generating an empty tuple instead of nil
+  // for structures with no members.
+  // TODO(dreiss): Test encoding of structs where some inner structs
+  // don't have thrift_spec.
+  indent_up();
+
+  int num_setable = 0;
+  if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) {
+    int sorted_keys_pos = 0;
+
+    for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
+      // Set field to optional if field is union, this is so we can get a
+      // pointer to the field.
+      if (tstruct->is_union())
+        (*m_iter)->set_req(t_field::T_OPTIONAL);
+      if (sorted_keys_pos != (*m_iter)->get_key()) {
+        int first_unused = std::max(1, sorted_keys_pos++);
+        while (sorted_keys_pos != (*m_iter)->get_key()) {
+          ++sorted_keys_pos;
+        }
+        int last_unused = sorted_keys_pos - 1;
+        if (first_unused < last_unused) {
+          indent(out) << "// unused fields # " << first_unused << " to " << last_unused << endl;
+        } else if (first_unused == last_unused) {
+          indent(out) << "// unused field # " << first_unused << endl;
+        }
+      }
+
+      t_type* fieldType = (*m_iter)->get_type();
+      string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter));
+      string gotag = "db:\"" + escape_string((*m_iter)->get_name())  + "\" ";
+      if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
+        gotag += "json:\"" + escape_string((*m_iter)->get_name()) + ",omitempty\"";
+      } else {
+        gotag += "json:\"" + escape_string((*m_iter)->get_name()) + "\"";
+      }
+
+      // Check for user override of db and json tags using "go.tag"
+      std::map<string, string>::iterator it = (*m_iter)->annotations_.find("go.tag");
+      if (it != (*m_iter)->annotations_.end()) {
+        gotag = it->second;
+      }
+      indent(out) << publicize((*m_iter)->get_name()) << " " << goType << " `thrift:\""
+                  << escape_string((*m_iter)->get_name()) << "," << sorted_keys_pos;
+      if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
+        out << ",required";
+      }
+
+      out << "\" " << gotag << "`" << endl;
+      sorted_keys_pos++;
+    }
+  } else {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      // This fills in default values, as opposed to nulls
+      out << indent() << publicize((*m_iter)->get_name()) << " "
+          << type_to_go_type((*m_iter)->get_type()) << endl;
+    }
+  }
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+  out << indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl;
+  out << indent() << "  return &";
+  generate_go_struct_initializer(out, tstruct, is_result || is_args);
+  out << indent() << "}" << endl << endl;
+  // Default values for optional fields
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    string publicized_name;
+    t_const_value* def_value;
+    get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
+    t_type* fieldType = (*m_iter)->get_type();
+    string goType = type_to_go_type_with_opt(fieldType, false);
+    string def_var_name = tstruct_name + "_" + publicized_name + "_DEFAULT";
+    if ((*m_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*m_iter)) {
+      out << indent() << "var " << def_var_name << " " << goType;
+      if (def_value != NULL) {
+        out << " = " << render_const_value(fieldType, def_value, (*m_iter)->get_name());
+      }
+      out << endl;
+    }
+    if (is_pointer_field(*m_iter)) {
+      string goOptType = type_to_go_type_with_opt(fieldType, true);
+      string maybepointer = goOptType != goType ? "*" : "";
+      out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "
+          << goType << " {" << endl;
+      out << indent() << "  if !p.IsSet" << publicized_name << "() {" << endl;
+      out << indent() << "    return " << def_var_name << endl;
+      out << indent() << "  }" << endl;
+      out << indent() << "return " << maybepointer << "p." << publicized_name << endl;
+      out << indent() << "}" << endl;
+      num_setable += 1;
+    } else {
+      out << endl;
+      out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "
+          << goType << " {" << endl;
+      out << indent() << "  return p." << publicized_name << endl;
+      out << indent() << "}" << endl;
+    }
+  }
+
+  if (tstruct->is_union() && num_setable > 0) {
+    generate_countsetfields_helper(out, tstruct, tstruct_name, is_result);
+  }
+
+  generate_isset_helpers(out, tstruct, tstruct_name, is_result);
+  generate_go_struct_reader(out, tstruct, tstruct_name, is_result);
+  generate_go_struct_writer(out, tstruct, tstruct_name, is_result, num_setable > 0);
+
+  out << indent() << "func (p *" << tstruct_name << ") String() string {" << endl;
+  out << indent() << "  if p == nil {" << endl;
+  out << indent() << "    return \"<nil>\"" << endl;
+  out << indent() << "  }" << endl;
+  out << indent() << "  return fmt.Sprintf(\"" << escape_string(tstruct_name) << "(%+v)\", *p)"
+      << endl;
+  out << indent() << "}" << endl << endl;
+
+  if (is_exception) {
+    out << indent() << "func (p *" << tstruct_name << ") Error() string {" << endl;
+    out << indent() << "  return p.String()" << endl;
+    out << indent() << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates the IsSet helper methods for a struct
+ */
+void t_go_generator::generate_isset_helpers(ofstream& out,
+                                            t_struct* tstruct,
+                                            const string& tstruct_name,
+                                            bool is_result) {
+  (void)is_result;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  const string escaped_tstruct_name(escape_string(tstruct->get_name()));
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    const string field_name(publicize(escape_string((*f_iter)->get_name())));
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*f_iter)) {
+      out << indent() << "func (p *" << tstruct_name << ") IsSet" << field_name << "() bool {"
+          << endl;
+      indent_up();
+      t_type* ttype = (*f_iter)->get_type()->get_true_type();
+      bool is_byteslice = ttype->is_base_type() && ((t_base_type*)ttype)->is_binary();
+      bool compare_to_nil_only = ttype->is_set() || ttype->is_list() || ttype->is_map()
+                                 || (is_byteslice && !(*f_iter)->get_value());
+      if (is_pointer_field(*f_iter) || compare_to_nil_only) {
+        out << indent() << "return p." << field_name << " != nil" << endl;
+      } else {
+        string def_var_name = tstruct_name + "_" + field_name + "_DEFAULT";
+        if (is_byteslice) {
+          out << indent() << "return !bytes.Equal(p." << field_name << ", " << def_var_name << ")"
+              << endl;
+        } else {
+          out << indent() << "return p." << field_name << " != " << def_var_name << endl;
+        }
+      }
+      indent_down();
+      out << indent() << "}" << endl << endl;
+    }
+  }
+}
+
+/**
+ * Generates the CountSetFields helper method for a struct
+ */
+void t_go_generator::generate_countsetfields_helper(ofstream& out,
+                                                    t_struct* tstruct,
+                                                    const string& tstruct_name,
+                                                    bool is_result) {
+  (void)is_result;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  const string escaped_tstruct_name(escape_string(tstruct->get_name()));
+
+  out << indent() << "func (p *" << tstruct_name << ") CountSetFields" << tstruct_name << "() int {"
+      << endl;
+  indent_up();
+  out << indent() << "count := 0" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
+      continue;
+
+    if (!is_pointer_field(*f_iter))
+      continue;
+
+    const string field_name(publicize(escape_string((*f_iter)->get_name())));
+
+    out << indent() << "if (p.IsSet" << field_name << "()) {" << endl;
+    indent_up();
+    out << indent() << "count++" << endl;
+    indent_down();
+    out << indent() << "}" << endl;
+  }
+
+  out << indent() << "return count" << endl << endl;
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates the read method for a struct
+ */
+void t_go_generator::generate_go_struct_reader(ofstream& out,
+                                               t_struct* tstruct,
+                                               const string& tstruct_name,
+                                               bool is_result) {
+  (void)is_result;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  string escaped_tstruct_name(escape_string(tstruct->get_name()));
+  out << indent() << "func (p *" << tstruct_name << ") " << read_method_name_ << "(iprot thrift.TProtocol) error {"
+      << endl;
+  indent_up();
+  out << indent() << "if _, err := iprot.ReadStructBegin(); err != nil {" << endl;
+  out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T read error: \", p), err)"
+      << endl;
+  out << indent() << "}" << endl << endl;
+
+  // Required variables does not have IsSet functions, so we need tmp vars to check them.
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      const string field_name(publicize(escape_string((*f_iter)->get_name())));
+      indent(out) << "var isset" << field_name << " bool = false;" << endl;
+    }
+  }
+  out << endl;
+
+  // Loop over reading in fields
+  indent(out) << "for {" << endl;
+  indent_up();
+  // Read beginning field marker
+  out << indent() << "_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()" << endl;
+  out << indent() << "if err != nil {" << endl;
+  out << indent() << "  return thrift.PrependError(fmt.Sprintf("
+                     "\"%T field %d read error: \", p, fieldId), err)" << endl;
+  out << indent() << "}" << endl;
+  // Check for field STOP marker and break
+  out << indent() << "if fieldTypeId == thrift.STOP { break; }" << endl;
+
+  string thriftFieldTypeId;
+  // Generate deserialization code for known cases
+  int32_t field_id = -1;
+
+  // Switch statement on the field we are reading, false if no fields present
+  bool have_switch = !fields.empty();
+  if (have_switch) {
+    indent(out) << "switch fieldId {" << endl;
+  }
+
+  // All the fields we know
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    field_id = (*f_iter)->get_key();
+
+    // if negative id, ensure we generate a valid method name
+    string field_method_prefix("ReadField");
+    int32_t field_method_suffix = field_id;
+
+    if (field_method_suffix < 0) {
+      field_method_prefix += "_";
+      field_method_suffix *= -1;
+    }
+
+    out << indent() << "case " << field_id << ":" << endl;
+    indent_up();
+    thriftFieldTypeId = type_to_enum((*f_iter)->get_type());
+
+    if (thriftFieldTypeId == "thrift.BINARY") {
+      thriftFieldTypeId = "thrift.STRING";
+    }
+
+    out << indent() << "if err := p." << field_method_prefix << field_method_suffix << "(iprot); err != nil {"
+        << endl;
+    out << indent() << "  return err" << endl;
+    out << indent() << "}" << endl;
+
+    // Mark required field as read
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      const string field_name(publicize(escape_string((*f_iter)->get_name())));
+      out << indent() << "isset" << field_name << " = true" << endl;
+    }
+
+    indent_down();
+  }
+
+  // Begin switch default case
+  if (have_switch) {
+    out << indent() << "default:" << endl;
+    indent_up();
+  }
+
+  // Skip unknown fields in either case
+  out << indent() << "if err := iprot.Skip(fieldTypeId); err != nil {" << endl;
+  out << indent() << "  return err" << endl;
+  out << indent() << "}" << endl;
+
+  // End switch default case
+  if (have_switch) {
+    indent_down();
+    out << indent() << "}" << endl;
+  }
+
+  // Read field end marker
+  out << indent() << "if err := iprot.ReadFieldEnd(); err != nil {" << endl;
+  out << indent() << "  return err" << endl;
+  out << indent() << "}" << endl;
+  indent_down();
+  out << indent() << "}" << endl;
+  out << indent() << "if err := iprot.ReadStructEnd(); err != nil {" << endl;
+  out << indent() << "  return thrift.PrependError(fmt.Sprintf("
+                     "\"%T read struct end error: \", p), err)" << endl;
+  out << indent() << "}" << endl;
+
+  // Return error if any required fields are missing.
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      const string field_name(publicize(escape_string((*f_iter)->get_name())));
+      out << indent() << "if !isset" << field_name << "{" << endl;
+      out << indent() << "  return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, "
+                         "fmt.Errorf(\"Required field " << field_name << " is not set\"));" << endl;
+      out << indent() << "}" << endl;
+    }
+  }
+
+  out << indent() << "return nil" << endl;
+  indent_down();
+  out << indent() << "}" << endl << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string field_type_name(publicize((*f_iter)->get_type()->get_name()));
+    string field_name(publicize((*f_iter)->get_name()));
+    string field_method_prefix("ReadField");
+    int32_t field_id = (*f_iter)->get_key();
+    int32_t field_method_suffix = field_id;
+
+    if (field_method_suffix < 0) {
+      field_method_prefix += "_";
+      field_method_suffix *= -1;
+    }
+
+    out << indent() << "func (p *" << tstruct_name << ")  " << field_method_prefix << field_method_suffix
+        << "(iprot thrift.TProtocol) error {" << endl;
+    indent_up();
+    generate_deserialize_field(out, *f_iter, false, "p.");
+    indent_down();
+    out << indent() << "  return nil" << endl;
+    out << indent() << "}" << endl << endl;
+  }
+}
+
+void t_go_generator::generate_go_struct_writer(ofstream& out,
+                                               t_struct* tstruct,
+                                               const string& tstruct_name,
+                                               bool is_result,
+                                               bool uses_countsetfields) {
+  (void)is_result;
+  string name(tstruct->get_name());
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+  indent(out) << "func (p *" << tstruct_name << ") " << write_method_name_ << "(oprot thrift.TProtocol) error {" << endl;
+  indent_up();
+  if (tstruct->is_union() && uses_countsetfields) {
+    std::string tstruct_name(publicize(tstruct->get_name()));
+    out << indent() << "if c := p.CountSetFields" << tstruct_name << "(); c != 1 {" << endl
+        << indent()
+        << "  return fmt.Errorf(\"%T write union: exactly one field must be set (%d set).\", p, c)"
+        << endl << indent() << "}" << endl;
+  }
+  out << indent() << "if err := oprot.WriteStructBegin(\"" << name << "\"); err != nil {" << endl;
+  out << indent() << "  return thrift.PrependError(fmt.Sprintf("
+                     "\"%T write struct begin error: \", p), err) }" << endl;
+
+  string field_name;
+  string escape_field_name;
+  // t_const_value* field_default_value;
+  t_field::e_req field_required;
+  int32_t field_id = -1;
+
+  out << indent() << "if p != nil {" << endl;
+  indent_up();
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string field_method_prefix("writeField");
+    field_name = (*f_iter)->get_name();
+    escape_field_name = escape_string(field_name);
+    field_id = (*f_iter)->get_key();
+    int32_t field_method_suffix = field_id;
+
+    if (field_method_suffix < 0) {
+      field_method_prefix += "_";
+      field_method_suffix *= -1;
+    }
+
+    out << indent() << "if err := p." << field_method_prefix << field_method_suffix
+        << "(oprot); err != nil { return err }" << endl;
+  }
+
+  indent_down();
+  out << indent() << "}" << endl;
+
+  // Write the struct map
+  out << indent() << "if err := oprot.WriteFieldStop(); err != nil {" << endl;
+  out << indent() << "  return thrift.PrependError(\"write field stop error: \", err) }" << endl;
+  out << indent() << "if err := oprot.WriteStructEnd(); err != nil {" << endl;
+  out << indent() << "  return thrift.PrependError(\"write struct stop error: \", err) }" << endl;
+  out << indent() << "return nil" << endl;
+  indent_down();
+  out << indent() << "}" << endl << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string field_method_prefix("writeField");
+    field_id = (*f_iter)->get_key();
+    field_name = (*f_iter)->get_name();
+    escape_field_name = escape_string(field_name);
+    // field_default_value = (*f_iter)->get_value();
+    field_required = (*f_iter)->get_req();
+    int32_t field_method_suffix = field_id;
+
+    if (field_method_suffix < 0) {
+      field_method_prefix += "_";
+      field_method_suffix *= -1;
+    }
+
+    out << indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_method_suffix
+        << "(oprot thrift.TProtocol) (err error) {" << endl;
+    indent_up();
+
+    if (field_required == t_field::T_OPTIONAL) {
+      out << indent() << "if p.IsSet" << publicize(field_name) << "() {" << endl;
+      indent_up();
+    }
+
+    out << indent() << "if err := oprot.WriteFieldBegin(\"" << escape_field_name << "\", "
+        << type_to_enum((*f_iter)->get_type()) << ", " << field_id << "); err != nil {" << endl;
+    out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T write field begin error "
+        << field_id << ":" << escape_field_name << ": \", p), err) }" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "p.");
+
+    // Write field closer
+    out << indent() << "if err := oprot.WriteFieldEnd(); err != nil {" << endl;
+    out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T write field end error "
+        << field_id << ":" << escape_field_name << ": \", p), err) }" << endl;
+
+    if (field_required == t_field::T_OPTIONAL) {
+      indent_down();
+      out << indent() << "}" << endl;
+    }
+
+    indent_down();
+    out << indent() << "  return err" << endl;
+    out << indent() << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_go_generator::generate_service(t_service* tservice) {
+  string test_suffix("_test");
+  string filename = lowercase(service_name_);
+  string f_service_name;
+
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+  generate_service_remote(tservice);
+  f_types_ << endl;
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_go_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  f_types_ << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_go_struct_definition(f_types_, ts, false, false, true);
+    generate_go_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_go_generator::generate_go_function_helpers(t_function* tfunction) {
+  if (!tfunction->is_oneway()) {
+    t_struct result(program_, tfunction->get_name() + "_result");
+    t_field success(tfunction->get_returntype(), "success", 0);
+    success.set_req(t_field::T_OPTIONAL);
+
+    if (!tfunction->get_returntype()->is_void()) {
+      result.append(&success);
+    }
+
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& fields = xs->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* f = *f_iter;
+      f->set_req(t_field::T_OPTIONAL);
+      result.append(f);
+    }
+
+    generate_go_struct_definition(f_types_, &result, false, true);
+  }
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_go_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_if = "";
+  string serviceName(publicize(tservice->get_name()));
+  string interfaceName = serviceName;
+
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    size_t index = extends.rfind(".");
+
+    if (index != string::npos) {
+      extends_if = "\n" + indent() + "  " + extends.substr(0, index + 1)
+                   + publicize(extends.substr(index + 1)) + "\n";
+    } else {
+      extends_if = "\n" + indent() + publicize(extends) + "\n";
+    }
+  }
+
+  f_types_ << indent() << "type " << interfaceName << " interface {" << extends_if;
+  indent_up();
+  generate_go_docstring(f_types_, tservice);
+  vector<t_function*> functions = tservice->get_functions();
+
+  if (!functions.empty()) {
+    f_types_ << endl;
+    vector<t_function*>::iterator f_iter;
+
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      generate_go_docstring(f_types_, (*f_iter));
+      f_types_ << indent() << function_signature_if(*f_iter, "", true) << endl;
+    }
+  }
+
+  indent_down();
+  f_types_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_go_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_field = "";
+  string extends_client = "";
+  string extends_client_new = "";
+  string serviceName(publicize(tservice->get_name()));
+
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    size_t index = extends.rfind(".");
+
+    if (index != string::npos) {
+      extends_client = extends.substr(0, index + 1) + publicize(extends.substr(index + 1))
+                       + "Client";
+      extends_client_new = extends.substr(0, index + 1) + "New"
+                           + publicize(extends.substr(index + 1)) + "Client";
+    } else {
+      extends_client = publicize(extends) + "Client";
+      extends_client_new = "New" + extends_client;
+    }
+  }
+
+  extends_field = extends_client.substr(extends_client.find(".") + 1);
+
+  generate_go_docstring(f_types_, tservice);
+  f_types_ << indent() << "type " << serviceName << "Client struct {" << endl;
+  indent_up();
+
+  if (!extends_client.empty()) {
+    f_types_ << indent() << "*" << extends_client << endl;
+  } else {
+    f_types_ << indent() << "Transport thrift.TTransport" << endl;
+    f_types_ << indent() << "ProtocolFactory thrift.TProtocolFactory" << endl;
+    f_types_ << indent() << "InputProtocol thrift.TProtocol" << endl;
+    f_types_ << indent() << "OutputProtocol thrift.TProtocol" << endl;
+    f_types_ << indent() << "SeqId int32" << endl;
+    /*f_types_ << indent() << "reqs map[int32]Deferred" << endl*/;
+  }
+
+  indent_down();
+  f_types_ << indent() << "}" << endl << endl;
+  // Constructor function
+  f_types_ << indent() << "func New" << serviceName
+             << "ClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *" << serviceName
+             << "Client {" << endl;
+  indent_up();
+  f_types_ << indent() << "return &" << serviceName << "Client";
+
+  if (!extends.empty()) {
+    f_types_ << "{" << extends_field << ": " << extends_client_new << "Factory(t, f)}";
+  } else {
+    indent_up();
+    f_types_ << "{Transport: t," << endl;
+    f_types_ << indent() << "ProtocolFactory: f," << endl;
+    f_types_ << indent() << "InputProtocol: f.GetProtocol(t)," << endl;
+    f_types_ << indent() << "OutputProtocol: f.GetProtocol(t)," << endl;
+    f_types_ << indent() << "SeqId: 0," << endl;
+    /*f_types_ << indent() << "Reqs: make(map[int32]Deferred)" << endl*/;
+    indent_down();
+    f_types_ << indent() << "}" << endl;
+  }
+
+  indent_down();
+  f_types_ << indent() << "}" << endl << endl;
+  // Constructor function
+  f_types_
+      << indent() << "func New" << serviceName
+      << "ClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *"
+      << serviceName << "Client {" << endl;
+  indent_up();
+  f_types_ << indent() << "return &" << serviceName << "Client";
+
+  if (!extends.empty()) {
+    f_types_ << "{" << extends_field << ": " << extends_client_new << "Protocol(t, iprot, oprot)}"
+               << endl;
+  } else {
+    indent_up();
+    f_types_ << "{Transport: t," << endl;
+    f_types_ << indent() << "ProtocolFactory: nil," << endl;
+    f_types_ << indent() << "InputProtocol: iprot," << endl;
+    f_types_ << indent() << "OutputProtocol: oprot," << endl;
+    f_types_ << indent() << "SeqId: 0," << endl;
+    /*f_types_ << indent() << "Reqs: make(map[int32]interface{})" << endl*/;
+    indent_down();
+    f_types_ << indent() << "}" << endl;
+  }
+
+  indent_down();
+  f_types_ << indent() << "}" << endl << endl;
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = publicize((*f_iter)->get_name());
+    // Open function
+    generate_go_docstring(f_types_, (*f_iter));
+    f_types_ << indent() << "func (p *" << serviceName << "Client) "
+               << function_signature_if(*f_iter, "", true) << " {" << endl;
+    indent_up();
+    /*
+    f_types_ <<
+      indent() << "p.SeqId += 1" << endl;
+    if (!(*f_iter)->is_oneway()) {
+      f_types_ <<
+        indent() << "d := defer.Deferred()" << endl <<
+        indent() << "p.Reqs[p.SeqId] = d" << endl;
+    }
+    */
+    f_types_ << indent() << "if err = p.send" << funname << "(";
+    bool first = true;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_types_ << ", ";
+      }
+
+      f_types_ << variable_name_to_go_name((*fld_iter)->get_name());
+    }
+
+    f_types_ << "); err != nil { return }" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_types_ << indent() << "return p.recv" << funname << "()" << endl;
+    } else {
+      f_types_ << indent() << "return" << endl;
+    }
+
+    indent_down();
+    f_types_ << indent() << "}" << endl << endl;
+    f_types_ << indent() << "func (p *" << serviceName << "Client) send"
+               << function_signature(*f_iter) << "(err error) {" << endl;
+    indent_up();
+    std::string argsname = publicize((*f_iter)->get_name() + "_args", true);
+    // Serialize the request header
+    f_types_ << indent() << "oprot := p.OutputProtocol" << endl;
+    f_types_ << indent() << "if oprot == nil {" << endl;
+    f_types_ << indent() << "  oprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl;
+    f_types_ << indent() << "  p.OutputProtocol = oprot" << endl;
+    f_types_ << indent() << "}" << endl;
+    f_types_ << indent() << "p.SeqId++" << endl;
+    f_types_ << indent() << "if err = oprot.WriteMessageBegin(\"" << (*f_iter)->get_name()
+               << "\", " << ((*f_iter)->is_oneway() ? "thrift.ONEWAY" : "thrift.CALL")
+               << ", p.SeqId); err != nil {" << endl;
+    indent_up();
+    f_types_ << indent() << "  return" << endl;
+    indent_down();
+    f_types_ << indent() << "}" << endl;
+    f_types_ << indent() << "args := " << argsname << "{" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_types_ << indent() << publicize((*fld_iter)->get_name()) << " : "
+                 << variable_name_to_go_name((*fld_iter)->get_name()) << "," << endl;
+    }
+    f_types_ << indent() << "}" << endl;
+
+    // Write to the stream
+    f_types_ << indent() << "if err = args." << write_method_name_ << "(oprot); err != nil {" << endl;
+    indent_up();
+    f_types_ << indent() << "  return" << endl;
+    indent_down();
+    f_types_ << indent() << "}" << endl;
+    f_types_ << indent() << "if err = oprot.WriteMessageEnd(); err != nil {" << endl;
+    indent_up();
+    f_types_ << indent() << "  return" << endl;
+    indent_down();
+    f_types_ << indent() << "}" << endl;
+    f_types_ << indent() << "return oprot.Flush()" << endl;
+    indent_down();
+    f_types_ << indent() << "}" << endl << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = publicize((*f_iter)->get_name() + "_result", true);
+      // Open function
+      f_types_ << endl << indent() << "func (p *" << serviceName << "Client) recv"
+                 << publicize((*f_iter)->get_name()) << "() (";
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_types_ << "value " << type_to_go_type((*f_iter)->get_returntype()) << ", ";
+      }
+
+      f_types_ << "err error) {" << endl;
+      indent_up();
+      // TODO(mcslee): Validate message reply here, seq ids etc.
+      string error(tmp("error"));
+      string error2(tmp("error"));
+      f_types_ << indent() << "iprot := p.InputProtocol" << endl;
+      f_types_ << indent() << "if iprot == nil {" << endl;
+      f_types_ << indent() << "  iprot = p.ProtocolFactory.GetProtocol(p.Transport)" << endl;
+      f_types_ << indent() << "  p.InputProtocol = iprot" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "method, mTypeId, seqId, err := iprot.ReadMessageBegin()" << endl;
+      f_types_ << indent() << "if err != nil {" << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "if method != \"" << (*f_iter)->get_name() << "\" {" << endl;
+      f_types_ << indent() << "  err = thrift.NewTApplicationException("
+                 << "thrift.WRONG_METHOD_NAME, \"" << (*f_iter)->get_name()
+                 << " failed: wrong method name\")" << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "if p.SeqId != seqId {" << endl;
+      f_types_ << indent() << "  err = thrift.NewTApplicationException("
+                 << "thrift.BAD_SEQUENCE_ID, \"" << (*f_iter)->get_name()
+                 << " failed: out of sequence response\")" << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "if mTypeId == thrift.EXCEPTION {" << endl;
+      f_types_ << indent() << "  " << error
+                 << " := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "
+                    "\"Unknown Exception\")" << endl;
+      f_types_ << indent() << "  var " << error2 << " error" << endl;
+      f_types_ << indent() << "  " << error2 << ", err = " << error << ".Read(iprot)" << endl;
+      f_types_ << indent() << "  if err != nil {" << endl;
+      f_types_ << indent() << "    return" << endl;
+      f_types_ << indent() << "  }" << endl;
+      f_types_ << indent() << "  if err = iprot.ReadMessageEnd(); err != nil {" << endl;
+      f_types_ << indent() << "    return" << endl;
+      f_types_ << indent() << "  }" << endl;
+      f_types_ << indent() << "  err = " << error2 << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "if mTypeId != thrift.REPLY {" << endl;
+      f_types_ << indent() << "  err = thrift.NewTApplicationException("
+                 << "thrift.INVALID_MESSAGE_TYPE_EXCEPTION, \"" << (*f_iter)->get_name()
+                 << " failed: invalid message type\")" << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "result := " << resultname << "{}" << endl;
+      f_types_ << indent() << "if err = result." << read_method_name_ << "(iprot); err != nil {" << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+      f_types_ << indent() << "if err = iprot.ReadMessageEnd(); err != nil {" << endl;
+      f_types_ << indent() << "  return" << endl;
+      f_types_ << indent() << "}" << endl;
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        const std::string pubname = publicize((*x_iter)->get_name());
+
+        f_types_ << indent() << "if result." << pubname << " != nil {" << endl;
+        f_types_ << indent() << "  err = result." << pubname << endl;
+        f_types_ << indent() << "  return " << endl;
+        f_types_ << indent() << "}";
+
+        if ((x_iter + 1) != xceptions.end()) {
+          f_types_ << " else ";
+        } else {
+          f_types_ << endl;
+        }
+      }
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_types_ << indent() << "value = result.GetSuccess()" << endl;
+      }
+
+      f_types_ << indent() << "return" << endl;
+      // Close function
+      indent_down();
+      f_types_ << indent() << "}" << endl << endl;
+    }
+  }
+
+  // indent_down();
+  f_types_ << endl;
+}
+
+/**
+ * Generates a command line tool for making remote requests
+ *
+ * @param tservice The service to generate a remote for.
+ */
+void t_go_generator::generate_service_remote(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  t_service* parent = tservice->get_extends();
+
+  // collect inherited functions
+  while (parent != NULL) {
+    vector<t_function*> p_functions = parent->get_functions();
+    functions.insert(functions.end(), p_functions.begin(), p_functions.end());
+    parent = parent->get_extends();
+  }
+
+  vector<t_function*>::iterator f_iter;
+  string f_remote_name = package_dir_ + "/" + underscore(service_name_) + "-remote/"
+                         + underscore(service_name_) + "-remote.go";
+  ofstream f_remote;
+  f_remote.open(f_remote_name.c_str());
+  string service_module = get_real_go_module(program_);
+  string::size_type loc;
+
+  while ((loc = service_module.find(".")) != string::npos) {
+    service_module.replace(loc, 1, 1, '/');
+  }
+  if (!gen_package_prefix_.empty()) {
+    service_module = gen_package_prefix_ + service_module;
+  }
+
+  string unused_protection;
+
+  f_remote << go_autogen_comment();
+  f_remote << indent() << "package main" << endl << endl;
+  f_remote << indent() << "import (" << endl;
+  f_remote << indent() << "        \"flag\"" << endl;
+  f_remote << indent() << "        \"fmt\"" << endl;
+  f_remote << indent() << "        \"math\"" << endl;
+  f_remote << indent() << "        \"net\"" << endl;
+  f_remote << indent() << "        \"net/url\"" << endl;
+  f_remote << indent() << "        \"os\"" << endl;
+  f_remote << indent() << "        \"strconv\"" << endl;
+  f_remote << indent() << "        \"strings\"" << endl;
+  f_remote << indent() << "        \"" + gen_thrift_import_ + "\"" << endl;
+  f_remote << indent() << render_included_programs(unused_protection);
+  f_remote << indent() << "        \"" << service_module << "\"" << endl;
+  f_remote << indent() << ")" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << unused_protection; // filled in render_included_programs()
+  f_remote << indent() << endl;
+  f_remote << indent() << "func Usage() {" << endl;
+  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Usage of \", os.Args[0], \" "
+                          "[-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:\")"
+           << endl;
+  f_remote << indent() << "  flag.PrintDefaults()" << endl;
+  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"\\nFunctions:\")" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_remote << "  fmt.Fprintln(os.Stderr, \"  " << (*f_iter)->get_returntype()->get_name() << " "
+             << (*f_iter)->get_name() << "(";
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const std::vector<t_field*>& args = arg_struct->get_members();
+    vector<t_field*>::const_iterator a_iter;
+    std::vector<t_field*>::size_type num_args = args.size();
+    bool first = true;
+
+    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
+      if (first) {
+        first = false;
+      } else {
+        f_remote << ", ";
+      }
+
+      f_remote << args[i]->get_type()->get_name() << " " << args[i]->get_name();
+    }
+
+    f_remote << ")\")" << endl;
+  }
+
+  f_remote << indent() << "  fmt.Fprintln(os.Stderr)" << endl;
+  f_remote << indent() << "  os.Exit(0)" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << "func main() {" << endl;
+  indent_up();
+  f_remote << indent() << "flag.Usage = Usage" << endl;
+  f_remote << indent() << "var host string" << endl;
+  f_remote << indent() << "var port int" << endl;
+  f_remote << indent() << "var protocol string" << endl;
+  f_remote << indent() << "var urlString string" << endl;
+  f_remote << indent() << "var framed bool" << endl;
+  f_remote << indent() << "var useHttp bool" << endl;
+  f_remote << indent() << "var parsedUrl url.URL" << endl;
+  f_remote << indent() << "var trans thrift.TTransport" << endl;
+  f_remote << indent() << "_ = strconv.Atoi" << endl;
+  f_remote << indent() << "_ = math.Abs" << endl;
+  f_remote << indent() << "flag.Usage = Usage" << endl;
+  f_remote << indent() << "flag.StringVar(&host, \"h\", \"localhost\", \"Specify host and port\")"
+           << endl;
+  f_remote << indent() << "flag.IntVar(&port, \"p\", 9090, \"Specify port\")" << endl;
+  f_remote << indent() << "flag.StringVar(&protocol, \"P\", \"binary\", \""
+                          "Specify the protocol (binary, compact, simplejson, json)\")" << endl;
+  f_remote << indent() << "flag.StringVar(&urlString, \"u\", \"\", \"Specify the url\")" << endl;
+  f_remote << indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")"
+           << endl;
+  f_remote << indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl;
+  f_remote << indent() << "flag.Parse()" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << "if len(urlString) > 0 {" << endl;
+  f_remote << indent() << "  parsedUrl, err := url.Parse(urlString)" << endl;
+  f_remote << indent() << "  if err != nil {" << endl;
+  f_remote << indent() << "    fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl;
+  f_remote << indent() << "    flag.Usage()" << endl;
+  f_remote << indent() << "  }" << endl;
+  f_remote << indent() << "  host = parsedUrl.Host" << endl;
+  f_remote << indent() << "  useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\""
+           << endl;
+  f_remote << indent() << "} else if useHttp {" << endl;
+  f_remote << indent() << "  _, err := url.Parse(fmt.Sprint(\"http://\", host, \":\", port))"
+           << endl;
+  f_remote << indent() << "  if err != nil {" << endl;
+  f_remote << indent() << "    fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl;
+  f_remote << indent() << "    flag.Usage()" << endl;
+  f_remote << indent() << "  }" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << "cmd := flag.Arg(0)" << endl;
+  f_remote << indent() << "var err error" << endl;
+  f_remote << indent() << "if useHttp {" << endl;
+  f_remote << indent() << "  trans, err = thrift.NewTHttpClient(parsedUrl.String())" << endl;
+  f_remote << indent() << "} else {" << endl;
+  f_remote << indent() << "  portStr := fmt.Sprint(port)" << endl;
+  f_remote << indent() << "  if strings.Contains(host, \":\") {" << endl;
+  f_remote << indent() << "         host, portStr, err = net.SplitHostPort(host)" << endl;
+  f_remote << indent() << "         if err != nil {" << endl;
+  f_remote << indent() << "                 fmt.Fprintln(os.Stderr, \"error with host:\", err)"
+           << endl;
+  f_remote << indent() << "                 os.Exit(1)" << endl;
+  f_remote << indent() << "         }" << endl;
+  f_remote << indent() << "  }" << endl;
+  f_remote << indent() << "  trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr))"
+           << endl;
+  f_remote << indent() << "  if err != nil {" << endl;
+  f_remote << indent() << "    fmt.Fprintln(os.Stderr, \"error resolving address:\", err)" << endl;
+  f_remote << indent() << "    os.Exit(1)" << endl;
+  f_remote << indent() << "  }" << endl;
+  f_remote << indent() << "  if framed {" << endl;
+  f_remote << indent() << "    trans = thrift.NewTFramedTransport(trans)" << endl;
+  f_remote << indent() << "  }" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << "if err != nil {" << endl;
+  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Error creating transport\", err)" << endl;
+  f_remote << indent() << "  os.Exit(1)" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << "defer trans.Close()" << endl;
+  f_remote << indent() << "var protocolFactory thrift.TProtocolFactory" << endl;
+  f_remote << indent() << "switch protocol {" << endl;
+  f_remote << indent() << "case \"compact\":" << endl;
+  f_remote << indent() << "  protocolFactory = thrift.NewTCompactProtocolFactory()" << endl;
+  f_remote << indent() << "  break" << endl;
+  f_remote << indent() << "case \"simplejson\":" << endl;
+  f_remote << indent() << "  protocolFactory = thrift.NewTSimpleJSONProtocolFactory()" << endl;
+  f_remote << indent() << "  break" << endl;
+  f_remote << indent() << "case \"json\":" << endl;
+  f_remote << indent() << "  protocolFactory = thrift.NewTJSONProtocolFactory()" << endl;
+  f_remote << indent() << "  break" << endl;
+  f_remote << indent() << "case \"binary\", \"\":" << endl;
+  f_remote << indent() << "  protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()" << endl;
+  f_remote << indent() << "  break" << endl;
+  f_remote << indent() << "default:" << endl;
+  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Invalid protocol specified: \", protocol)"
+           << endl;
+  f_remote << indent() << "  Usage()" << endl;
+  f_remote << indent() << "  os.Exit(1)" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << "client := " << package_name_ << ".New" << publicize(service_name_)
+           << "ClientFactory(trans, protocolFactory)" << endl;
+  f_remote << indent() << "if err := trans.Open(); err != nil {" << endl;
+  f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"Error opening socket to \", "
+                          "host, \":\", port, \" \", err)" << endl;
+  f_remote << indent() << "  os.Exit(1)" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << "switch cmd {" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const std::vector<t_field*>& args = arg_struct->get_members();
+    vector<t_field*>::const_iterator a_iter;
+    std::vector<t_field*>::size_type num_args = args.size();
+    string funcName((*f_iter)->get_name());
+    string pubName(publicize(funcName));
+    string argumentsName(publicize(funcName + "_args", true));
+    f_remote << indent() << "case \"" << escape_string(funcName) << "\":" << endl;
+    indent_up();
+    f_remote << indent() << "if flag.NArg() - 1 != " << num_args << " {" << endl;
+    f_remote << indent() << "  fmt.Fprintln(os.Stderr, \"" << escape_string(pubName) << " requires "
+             << num_args << " args\")" << endl;
+    f_remote << indent() << "  flag.Usage()" << endl;
+    f_remote << indent() << "}" << endl;
+
+    for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
+      int flagArg = i + 1;
+      t_type* the_type(args[i]->get_type());
+      t_type* the_type2(get_true_type(the_type));
+
+      if (the_type2->is_enum()) {
+        f_remote << indent() << "tmp" << i << ", err := (strconv.Atoi(flag.Arg(" << flagArg << ")))"
+                 << endl;
+        f_remote << indent() << "if err != nil {" << endl;
+        f_remote << indent() << "  Usage()" << endl;
+        f_remote << indent() << " return" << endl;
+        f_remote << indent() << "}" << endl;
+        f_remote << indent() << "argvalue" << i << " := " << package_name_ << "."
+                 << publicize(the_type->get_name()) << "(tmp" << i << ")" << endl;
+      } else if (the_type2->is_base_type()) {
+        t_base_type::t_base e = ((t_base_type*)the_type2)->get_base();
+        string err(tmp("err"));
+
+        switch (e) {
+        case t_base_type::TYPE_VOID:
+          break;
+
+        case t_base_type::TYPE_STRING:
+          if (((t_base_type*)the_type2)->is_binary()) {
+            f_remote << indent() << "argvalue" << i << " := []byte(flag.Arg(" << flagArg << "))"
+                     << endl;
+          } else {
+            f_remote << indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ")" << endl;
+          }
+          break;
+
+        case t_base_type::TYPE_BOOL:
+          f_remote << indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ") == \"true\""
+                   << endl;
+          break;
+
+        case t_base_type::TYPE_I8:
+          f_remote << indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg("
+                   << flagArg << ")))" << endl;
+          f_remote << indent() << "if " << err << " != nil {" << endl;
+          f_remote << indent() << "  Usage()" << endl;
+          f_remote << indent() << "  return" << endl;
+          f_remote << indent() << "}" << endl;
+          f_remote << indent() << "argvalue" << i << " := int8(tmp" << i << ")" << endl;
+          break;
+
+        case t_base_type::TYPE_I16:
+          f_remote << indent() << "tmp" << i << ", " << err << " := (strconv

<TRUNCATED>

[03/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_php_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_php_generator.cc b/compiler/cpp/src/thrift/generate/t_php_generator.cc
new file mode 100644
index 0000000..ba52781
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_php_generator.cc
@@ -0,0 +1,2653 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+#define NSGLOBAL (nsglobal_.size() ? nsglobal_ : "")
+#define NSGLOBAL_A ("\\" + NSGLOBAL)
+#define NSGLOBAL_B (NSGLOBAL + "\\")
+#define NSGLOBAL_AB ("\\" + NSGLOBAL + "\\")
+
+/**
+ * PHP code generator.
+ *
+ */
+class t_php_generator : public t_oop_generator {
+public:
+  t_php_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    binary_inline_ = false;
+    rest_ = false;
+    phps_ = false;
+    oop_ = false;
+    validate_ = false;
+    json_serializable_ = false;
+    nsglobal_ = ""; // by default global namespace is empty
+    psr4_ = false;
+    for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if (iter->first.compare("inlined") == 0) {
+        binary_inline_ = true;
+      } else if (iter->first.compare("rest") == 0) {
+        rest_ = true;
+      } else if (iter->first.compare("server") == 0) {
+        phps_ = true;
+      } else if (iter->first.compare("oop") == 0) {
+        oop_ = true;
+      } else if (iter->first.compare("validate") == 0) {
+        validate_ = true;
+      } else if (iter->first.compare("json") == 0) {
+        json_serializable_ = true;
+      } else if (iter->first.compare("nsglobal") == 0) {
+        nsglobal_ = iter->second;
+      } else if (iter->first.compare("psr4") == 0) {
+        psr4_ = true;
+      } else {
+        throw "unknown option php:" + iter->first;
+      }
+    }
+
+    if (oop_ && binary_inline_) {
+      throw "oop and inlined are mutually exclusive.";
+    }
+
+    out_dir_base_ = (binary_inline_ ? "gen-phpi" : "gen-php");
+    escape_['$'] = "\\$";
+  }
+
+  static bool is_valid_namespace(const std::string& sub_namespace);
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_consts(vector<t_const*> consts);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+  /**
+   * Structs!
+   */
+
+  void generate_php_struct(t_struct* tstruct, bool is_exception);
+  void generate_php_struct_definition(std::ofstream& out,
+                                      t_struct* tstruct,
+                                      bool is_xception = false,
+                                      bool is_result = false);
+  void generate_php_struct_reader(std::ofstream& out, t_struct* tstruct, bool is_result);
+  void generate_php_struct_writer(std::ofstream& out, t_struct* tstruct, bool is_result);
+  void generate_php_function_helpers(t_service* tservice, t_function* tfunction);
+  void generate_php_struct_required_validator(ofstream& out,
+                                              t_struct* tstruct,
+                                              std::string method_name,
+                                              bool write_mode);
+  void generate_php_struct_read_validator(ofstream& out, t_struct* tstruct);
+  void generate_php_struct_write_validator(ofstream& out, t_struct* tstruct);
+  void generate_php_struct_json_serialize(ofstream& out, t_struct* tstruct, bool is_result);
+  bool needs_php_write_validator(t_struct* tstruct, bool is_result);
+  bool needs_php_read_validator(t_struct* tstruct, bool is_result);
+  int get_php_num_required_fields(const vector<t_field*>& fields, bool write_mode);
+
+  void generate_php_type_spec(std::ofstream& out, t_type* t);
+  void generate_php_struct_spec(std::ofstream& out, t_struct* tstruct);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_rest(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_processor(t_service* tservice);
+  void generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction);
+  void generate_service_header(t_service* tservice, std::ofstream& file);
+  void generate_program_header(std::ofstream& file);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool inclass = false);
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  void generate_php_doc(std::ofstream& out, t_doc* tdoc);
+
+  void generate_php_doc(std::ofstream& out, t_field* tfield);
+
+  void generate_php_doc(std::ofstream& out, t_function* tfunction);
+
+  void generate_php_docstring_comment(std::ofstream& out, string contents);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string php_includes();
+  std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct, bool addTypeHints = true);
+  std::string type_to_cast(t_type* ttype);
+  std::string type_to_enum(t_type* ttype);
+  std::string type_to_phpdoc(t_type* ttype);
+
+  std::string php_namespace_base(const t_program* p) {
+    std::string ns = p->get_namespace("php");
+    const char* delimiter = "\\";
+    size_t position = ns.find('.');
+    while (position != string::npos) {
+      ns.replace(position, 1, delimiter);
+      position = ns.find('.', position + 1);
+    }
+    return ns;
+  }
+
+  // general use namespace prefixing: \my\namespace\ or my_namespace_
+  string php_namespace(const t_program* p) {
+    string ns = php_namespace_base(p);
+    return (nsglobal_.size() ? NSGLOBAL_AB : NSGLOBAL_B) + (ns.size() ? (ns + "\\") : "");
+  }
+
+  // setting the namespace of a file: my\namespace
+  string php_namespace_suffix(const t_program* p) {
+    string ns = php_namespace_base(p);
+
+    return (nsglobal_.size() ? NSGLOBAL_B : NSGLOBAL) + ns;
+  }
+
+  // add a directory to already existing namespace
+  string php_namespace_directory(string directory, bool end = true) {
+    (void)directory;
+    if (end) {
+      return ";";
+    } else {
+      return "";
+    }
+  }
+
+  // writing an autload identifier into globa;ls: my\namespace\ or my_namespace_
+  string php_namespace_autoload(const t_program* p) {
+    std::string ns = php_namespace_base(p);
+    return (nsglobal_.size() ? NSGLOBAL_B : NSGLOBAL) + (ns.size() ? (ns + "\\") : "");
+  }
+
+  // declaring a type: typename or my_namespace_typename
+  string php_namespace_declaration(t_type* t) { return t->get_name(); }
+
+  std::string php_path(t_program* p) {
+    std::string ns = p->get_namespace("php.path");
+    if (ns.empty()) {
+      return p->get_name();
+    }
+
+    // Transform the java-style namespace into a path.
+    for (std::string::iterator it = ns.begin(); it != ns.end(); ++it) {
+      if (*it == '.') {
+        *it = '/';
+      }
+    }
+
+    return ns + '/';
+  }
+
+  /**
+   * Transform class_method into ClassMethod
+   *
+   * @param str
+   * @return stirng
+   */
+  string classify(string str) {
+    string classe = "";
+
+    vector<string> x = split(str, '_');
+
+    for (size_t i = 0; i < x.size(); ++i) {
+      classe = classe + capitalize(x[i]);
+    }
+
+    return classe;
+  }
+
+  /**
+   * Split method
+   * @param s
+   * @param delim
+   * @param elems
+   * @return
+   */
+  vector<string>& split(const string& s, char delim, vector<string>& elems) {
+    stringstream ss(s);
+    string item;
+
+    while (getline(ss, item, delim)) {
+      elems.push_back(item);
+    }
+
+    return elems;
+  }
+
+  vector<string> split(const string& s, char delim) {
+    vector<string> elems;
+
+    return split(s, delim, elems);
+  }
+
+  /**
+   * Capitalize method
+   * @param str
+   * @return
+   */
+  string capitalize(string str) {
+    string::iterator it(str.begin());
+
+    if (it != str.end())
+      str[0] = toupper((unsigned char)str[0]);
+
+    //    while(++it != str.end())
+    //    {
+    //      *it = tolower((unsigned char)*it);
+    //    }
+    return str;
+  }
+
+private:
+  /**
+   * File streams
+   */
+  std::ofstream f_types_;
+  std::ofstream f_service_;
+
+  std::string package_dir_;
+  /**
+   * Generate protocol-independent template? Or Binary inline code?
+   */
+  bool binary_inline_;
+
+  /**
+   * Generate a REST handler class
+   */
+  bool rest_;
+
+  /**
+   * Generate stubs for a PHP server
+   */
+  bool phps_;
+
+  /**
+   * Whether to use OOP base class TBase
+   */
+  bool oop_;
+
+  /**
+   * Whether to hold each class in separate file to allow PSR4-autoloading
+   */
+  bool psr4_;
+
+  /**
+   * Whether to generate validator code
+   */
+  bool validate_;
+
+  /**
+   * Whether to generate JsonSerializable classes
+   */
+  bool json_serializable_;
+
+  /**
+   * Global namespace for PHP 5.3
+   */
+  std::string nsglobal_;
+};
+
+bool t_php_generator::is_valid_namespace(const std::string& sub_namespace) {
+  return sub_namespace == "path";
+}
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_php_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  // Create Real directory Namespaces
+  vector<string> NSx = split(php_namespace_suffix(get_program()), '\\');
+  package_dir_ = get_out_dir();
+
+  for (size_t i = 0; i < NSx.size(); ++i) {
+    package_dir_ = package_dir_ + "/" + NSx[i] + "/";
+    MKDIR(package_dir_.c_str());
+  }
+
+  // Prepare output file for all the types in non-psr4 mode
+  if (!psr4_) {
+    // Make output file
+    string f_types_name = package_dir_ + "Types.php";
+    f_types_.open(f_types_name.c_str());
+    generate_program_header(f_types_);
+  }
+}
+
+/**
+ * Prints standard php includes
+ */
+string t_php_generator::php_includes() {
+  string includes = "use Thrift\\Base\\TBase;\n"
+                    "use Thrift\\Type\\TType;\n"
+                    "use Thrift\\Type\\TMessageType;\n"
+                    "use Thrift\\Exception\\TException;\n"
+                    "use Thrift\\Exception\\TProtocolException;\n"
+                    "use Thrift\\Protocol\\TProtocol;\n"
+                    "use Thrift\\Protocol\\TBinaryProtocolAccelerated;\n"
+                    "use Thrift\\Exception\\TApplicationException;\n";
+
+  if (json_serializable_) {
+    includes += "use JsonSerializable;\n"
+                "use stdClass;\n";
+  }
+
+  return includes + "\n";
+}
+
+/**
+ * Close up (or down) some filez.
+ */
+void t_php_generator::close_generator() {
+  if (!psr4_) {
+    // Close types file
+    f_types_ << endl;
+    f_types_.close();
+  }
+}
+
+/**
+ * Generates a typedef. This is not done in PHP, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_php_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Generates service header contains namespace suffix and includes inside file specified
+ */
+void t_php_generator::generate_service_header(t_service* tservice, std::ofstream& file) {
+  file << "<?php" << endl;
+  if (!php_namespace_suffix(tservice->get_program()).empty()) {
+    file << "namespace " << php_namespace_suffix(tservice->get_program()) << ";" << endl;
+  }
+  file << autogen_comment() << php_includes();
+
+  file << endl;
+}
+
+/**
+ * Generates program header contains namespace suffix and includes inside file specified
+ */
+void t_php_generator::generate_program_header(std::ofstream& file) {
+  file << "<?php" << endl;
+  if (!php_namespace_suffix(get_program()).empty()) {
+    file << "namespace " << php_namespace_suffix(get_program()) << ";" << endl << endl;
+  }
+  file << autogen_comment() << php_includes();
+
+  file << endl;
+}
+
+/**
+ * Generates code for an enumerated type. Since define is expensive to lookup
+ * in PHP, we use a global array for this.
+ *
+ * @param tenum The enumeration
+ */
+void t_php_generator::generate_enum(t_enum* tenum) {
+  std::ofstream& f_enum = f_types_;
+  if (psr4_) {
+    string f_enum_name = package_dir_ + tenum->get_name() + ".php";
+    f_enum.open(f_enum_name.c_str());
+    generate_program_header(f_enum);
+  }
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+
+  // We're also doing it this way to see how it performs. It's more legible
+  // code but you can't do things like an 'extract' on it, which is a bit of
+  // a downer.
+  generate_php_doc(f_enum, tenum);
+  f_enum << "final class " << tenum->get_name() << " {" << endl;
+  indent_up();
+
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    generate_php_doc(f_enum, *c_iter);
+    indent(f_enum) << "const " << (*c_iter)->get_name() << " = " << value << ";" << endl;
+  }
+
+  indent(f_enum) << "static public $__names = array(" << endl;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "  " << value << " => '" << (*c_iter)->get_name() << "'," << endl;
+  }
+  indent(f_enum) << ");" << endl;
+
+  indent_down();
+
+  f_enum << "}" << endl << endl;
+  if (psr4_) {
+    f_enum.close();
+  }
+}
+
+/**
+ * Generate constant class
+ *
+ * Override the one from t_generator
+ */
+void t_php_generator::generate_consts(vector<t_const*> consts) {
+  vector<t_const*>::iterator c_iter;
+
+  // Create class only if needed
+  if (consts.size() > 0) {
+
+    std::ofstream& f_consts = f_types_;
+    if (psr4_) {
+      string f_consts_name = package_dir_ + "Constant.php";
+      f_consts.open(f_consts_name.c_str());
+      generate_program_header(f_consts);
+    }
+    f_consts << "final class Constant extends \\Thrift\\Type\\TConstant {" << endl;
+
+    indent_up();
+
+    // Create static property
+    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+      string name = (*c_iter)->get_name();
+
+      indent(f_consts) << "static protected $" << name << ";" << endl;
+    }
+
+    // Create init function
+    for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+      string name = (*c_iter)->get_name();
+
+      f_consts << endl;
+
+      indent(f_consts) << "static protected function init_" << name << "() {" << endl;
+      indent_up();
+
+      indent(f_consts) << "return ";
+      generate_php_doc(f_consts, *c_iter);
+      f_consts << render_const_value((*c_iter)->get_type(), (*c_iter)->get_value());
+      f_consts << ";" << endl;
+
+      indent_down();
+      indent(f_consts) << "}" << endl;
+    }
+
+    indent_down();
+    f_consts << "}" << endl << endl;
+    if (psr4_) {
+      f_consts.close();
+    }
+  }
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_php_generator::render_const_value(t_type* type, t_const_value* value) {
+  std::ostringstream out;
+  type = get_true_type(type);
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    indent(out) << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl;
+    indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      out << indent();
+      out << render_const_value(g_type_string, v_iter->first);
+      out << " => ";
+      out << render_const_value(field_type, v_iter->second);
+      out << "," << endl;
+    }
+    indent_down();
+    indent(out) << "))";
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    out << "array(" << endl;
+    indent_up();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent();
+      out << render_const_value(ktype, v_iter->first);
+      out << " => ";
+      out << render_const_value(vtype, v_iter->second);
+      out << "," << endl;
+    }
+    indent_down();
+    indent(out) << ")";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    out << "array(" << endl;
+    indent_up();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent();
+      out << render_const_value(etype, *v_iter);
+      if (type->is_set()) {
+        out << " => true";
+      }
+      out << "," << endl;
+    }
+    indent_down();
+    indent(out) << ")";
+  }
+  return out.str();
+}
+
+/**
+ * Make a struct
+ */
+void t_php_generator::generate_struct(t_struct* tstruct) {
+  generate_php_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_php_generator::generate_xception(t_struct* txception) {
+  generate_php_struct(txception, true);
+}
+
+/**
+ * Structs can be normal or exceptions.
+ */
+void t_php_generator::generate_php_struct(t_struct* tstruct, bool is_exception) {
+  std::ofstream& f_struct = f_types_;
+  if (psr4_) {
+    string f_struct_name = package_dir_ + tstruct->get_name() + ".php";
+    f_struct.open(f_struct_name.c_str());
+    generate_program_header(f_struct);
+  }
+  generate_php_struct_definition(f_struct, tstruct, is_exception);
+  if (psr4_) {
+    f_struct.close();
+  }
+}
+
+void t_php_generator::generate_php_type_spec(ofstream& out, t_type* t) {
+  t = get_true_type(t);
+  indent(out) << "'type' => " << type_to_enum(t) << "," << endl;
+
+  if (t->is_base_type() || t->is_enum()) {
+    // Noop, type is all we need
+  } else if (t->is_struct() || t->is_xception()) {
+    indent(out) << "'class' => '" << php_namespace(t->get_program()) << t->get_name() << "',"
+                << endl;
+  } else if (t->is_map()) {
+    t_type* ktype = get_true_type(((t_map*)t)->get_key_type());
+    t_type* vtype = get_true_type(((t_map*)t)->get_val_type());
+    indent(out) << "'ktype' => " << type_to_enum(ktype) << "," << endl;
+    indent(out) << "'vtype' => " << type_to_enum(vtype) << "," << endl;
+    indent(out) << "'key' => array(" << endl;
+    indent_up();
+    generate_php_type_spec(out, ktype);
+    indent_down();
+    indent(out) << ")," << endl;
+    indent(out) << "'val' => array(" << endl;
+    indent_up();
+    generate_php_type_spec(out, vtype);
+    indent(out) << ")," << endl;
+    indent_down();
+  } else if (t->is_list() || t->is_set()) {
+    t_type* etype;
+    if (t->is_list()) {
+      etype = get_true_type(((t_list*)t)->get_elem_type());
+    } else {
+      etype = get_true_type(((t_set*)t)->get_elem_type());
+    }
+    indent(out) << "'etype' => " << type_to_enum(etype) << "," << endl;
+    indent(out) << "'elem' => array(" << endl;
+    indent_up();
+    generate_php_type_spec(out, etype);
+    indent(out) << ")," << endl;
+    indent_down();
+  } else {
+    throw "compiler error: no type for php struct spec field";
+  }
+}
+
+/**
+ * Generates the struct specification structure, which fully qualifies enough
+ * type information to generalize serialization routines.
+ */
+void t_php_generator::generate_php_struct_spec(ofstream& out, t_struct* tstruct) {
+  indent(out) << "if (!isset(self::$_TSPEC)) {" << endl;
+  indent_up();
+
+  indent(out) << "self::$_TSPEC = array(" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    indent(out) << (*m_iter)->get_key() << " => array(" << endl;
+    indent_up();
+    out << indent() << "'var' => '" << (*m_iter)->get_name() << "'," << endl;
+    generate_php_type_spec(out, t);
+    indent(out) << ")," << endl;
+    indent_down();
+  }
+
+  indent_down();
+  indent(out) << "  );" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is nothing in PHP
+ * where the objects are all just associative arrays (unless of course we
+ * decide to start using objects for them...)
+ *
+ * @param tstruct The struct definition
+ */
+void t_php_generator::generate_php_struct_definition(ofstream& out,
+                                                     t_struct* tstruct,
+                                                     bool is_exception,
+                                                     bool is_result) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  generate_php_doc(out, tstruct);
+  out << "class " << php_namespace_declaration(tstruct);
+  if (is_exception) {
+    out << " extends "
+        << "TException";
+  } else if (oop_) {
+    out << " extends "
+        << "TBase";
+  }
+  if (json_serializable_) {
+    out << " implements JsonSerializable";
+  }
+  out << " {" << endl;
+  indent_up();
+
+  indent(out) << "static $_TSPEC;" << endl << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    string dval = "null";
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
+      dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
+    }
+    generate_php_doc(out, *m_iter);
+    indent(out) << "public $" << (*m_iter)->get_name() << " = " << dval << ";" << endl;
+  }
+
+  out << endl;
+
+  // Generate constructor from array
+  string param = (members.size() > 0) ? "$vals=null" : "";
+  out << indent() << "public function __construct(" << param << ") {" << endl;
+  indent_up();
+
+  generate_php_struct_spec(out, tstruct);
+
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
+        indent(out) << "$this->" << (*m_iter)->get_name() << " = "
+                    << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
+      }
+    }
+    out << indent() << "if (is_array($vals)) {" << endl;
+    indent_up();
+    if (oop_) {
+      out << indent() << "parent::__construct(self::$_TSPEC, $vals);" << endl;
+    } else {
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        out << indent() << "if (isset($vals['" << (*m_iter)->get_name() << "'])) {" << endl
+            << indent() << "  $this->" << (*m_iter)->get_name() << " = $vals['"
+            << (*m_iter)->get_name() << "'];" << endl << indent() << "}" << endl;
+      }
+    }
+    indent_down();
+    out << indent() << "}" << endl;
+  }
+  scope_down(out);
+  out << endl;
+
+  out << indent() << "public function getName() {" << endl << indent() << "  return '"
+      << tstruct->get_name() << "';" << endl << indent() << "}" << endl << endl;
+
+  generate_php_struct_reader(out, tstruct, is_result);
+  generate_php_struct_writer(out, tstruct, is_result);
+  if (needs_php_read_validator(tstruct, is_result)) {
+    generate_php_struct_read_validator(out, tstruct);
+  }
+  if (needs_php_write_validator(tstruct, is_result)) {
+    generate_php_struct_write_validator(out, tstruct);
+  }
+  if (json_serializable_) {
+    generate_php_struct_json_serialize(out, tstruct, is_result);
+  }
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates the read() method for a struct
+ */
+void t_php_generator::generate_php_struct_reader(ofstream& out, t_struct* tstruct, bool is_result) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "public function read($input)" << endl;
+  scope_up(out);
+
+  if (oop_) {
+    if (needs_php_read_validator(tstruct, is_result)) {
+      indent(out) << "$tmp = $this->_read('" << tstruct->get_name() << "', self::$_TSPEC, $input);"
+                  << endl;
+      indent(out) << "$this->_validateForRead();" << endl;
+      indent(out) << "return $tmp;" << endl;
+    } else {
+      indent(out) << "return $this->_read('" << tstruct->get_name() << "', self::$_TSPEC, $input);"
+                  << endl;
+    }
+    scope_down(out);
+    out << endl;
+    return;
+  }
+
+  out << indent() << "$xfer = 0;" << endl << indent() << "$fname = null;" << endl << indent()
+      << "$ftype = 0;" << endl << indent() << "$fid = 0;" << endl;
+
+  // Declare stack tmp variables
+  if (!binary_inline_) {
+    indent(out) << "$xfer += $input->readStructBegin($fname);" << endl;
+  }
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+
+  scope_up(out);
+
+  // Read beginning field marker
+  if (binary_inline_) {
+    t_field fftype(g_type_i8, "ftype");
+    t_field ffid(g_type_i16, "fid");
+    generate_deserialize_field(out, &fftype);
+    out << indent() << "if ($ftype == "
+        << "TType::STOP) {" << endl << indent() << "  break;" << endl << indent() << "}" << endl;
+    generate_deserialize_field(out, &ffid);
+  } else {
+    indent(out) << "$xfer += $input->readFieldBegin($fname, $ftype, $fid);" << endl;
+    // Check for field STOP marker and break
+    indent(out) << "if ($ftype == "
+                << "TType::STOP) {" << endl;
+    indent_up();
+    indent(out) << "break;" << endl;
+    indent_down();
+    indent(out) << "}" << endl;
+  }
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch ($fid)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+    generate_deserialize_field(out, *f_iter, "this->");
+    indent_down();
+    out << indent() << "} else {" << endl;
+    if (binary_inline_) {
+      indent(out) << "  $xfer += "
+                  << "TProtocol::skipBinary($input, $ftype);" << endl;
+    } else {
+      indent(out) << "  $xfer += $input->skip($ftype);" << endl;
+    }
+    out << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  indent(out) << "default:" << endl;
+  if (binary_inline_) {
+    indent(out) << "  $xfer += "
+                << "TProtocol::skipBinary($input, $ftype);" << endl;
+  } else {
+    indent(out) << "  $xfer += $input->skip($ftype);" << endl;
+  }
+  indent(out) << "  break;" << endl;
+
+  scope_down(out);
+
+  if (!binary_inline_) {
+    // Read field end marker
+    indent(out) << "$xfer += $input->readFieldEnd();" << endl;
+  }
+
+  scope_down(out);
+
+  if (!binary_inline_) {
+    indent(out) << "$xfer += $input->readStructEnd();" << endl;
+  }
+
+  if (needs_php_read_validator(tstruct, is_result)) {
+    indent(out) << "$this->_validateForRead();" << endl;
+  }
+
+  indent(out) << "return $xfer;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates the write() method for a struct
+ */
+void t_php_generator::generate_php_struct_writer(ofstream& out, t_struct* tstruct, bool is_result) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (binary_inline_) {
+    indent(out) << "public function write(&$output) {" << endl;
+  } else {
+    indent(out) << "public function write($output) {" << endl;
+  }
+  indent_up();
+
+  if (needs_php_write_validator(tstruct, is_result)) {
+    indent(out) << "$this->_validateForWrite();" << endl;
+  }
+
+  if (oop_) {
+    indent(out) << "return $this->_write('" << tstruct->get_name() << "', self::$_TSPEC, $output);"
+                << endl;
+    scope_down(out);
+    out << endl;
+    return;
+  }
+
+  indent(out) << "$xfer = 0;" << endl;
+
+  if (!binary_inline_) {
+    indent(out) << "$xfer += $output->writeStructBegin('" << name << "');" << endl;
+  }
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out << indent() << "if ($this->" << (*f_iter)->get_name() << " !== null) {" << endl;
+    indent_up();
+
+    t_type* type = get_true_type((*f_iter)->get_type());
+    string expect;
+    if (type->is_container()) {
+      expect = "array";
+    } else if (type->is_struct()) {
+      expect = "object";
+    }
+    if (!expect.empty()) {
+      out << indent() << "if (!is_" << expect << "($this->" << (*f_iter)->get_name() << ")) {"
+          << endl;
+      indent_up();
+      out << indent() << "throw new "
+          << "TProtocolException('Bad type in structure.', "
+          << "TProtocolException::INVALID_DATA);" << endl;
+      scope_down(out);
+    }
+
+    // Write field header
+    if (binary_inline_) {
+      out << indent() << "$output .= pack('c', " << type_to_enum((*f_iter)->get_type()) << ");"
+          << endl << indent() << "$output .= pack('n', " << (*f_iter)->get_key() << ");" << endl;
+    } else {
+      indent(out) << "$xfer += $output->writeFieldBegin("
+                  << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
+                  << ", " << (*f_iter)->get_key() << ");" << endl;
+    }
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this->");
+
+    // Write field closer
+    if (!binary_inline_) {
+      indent(out) << "$xfer += $output->writeFieldEnd();" << endl;
+    }
+
+    indent_down();
+    indent(out) << "}" << endl;
+  }
+
+  if (binary_inline_) {
+    out << indent() << "$output .= pack('c', "
+        << "TType::STOP);" << endl;
+  } else {
+    out << indent() << "$xfer += $output->writeFieldStop();" << endl << indent()
+        << "$xfer += $output->writeStructEnd();" << endl;
+  }
+
+  out << indent() << "return $xfer;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+void t_php_generator::generate_php_struct_read_validator(ofstream& out, t_struct* tstruct) {
+  generate_php_struct_required_validator(out, tstruct, "_validateForRead", false);
+}
+
+void t_php_generator::generate_php_struct_write_validator(ofstream& out, t_struct* tstruct) {
+  generate_php_struct_required_validator(out, tstruct, "_validateForWrite", true);
+}
+
+void t_php_generator::generate_php_struct_required_validator(ofstream& out,
+                                                             t_struct* tstruct,
+                                                             std::string method_name,
+                                                             bool write_mode) {
+  indent(out) << "private function " << method_name << "() {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+
+  if (fields.size() > 0) {
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = (*f_iter);
+      if (field->get_req() == t_field::T_REQUIRED
+          || (field->get_req() == t_field::T_OPT_IN_REQ_OUT && write_mode)) {
+        indent(out) << "if ($this->" << field->get_name() << " === null) {" << endl;
+        indent_up();
+        indent(out) << "throw new TProtocolException('Required field " << tstruct->get_name() << "."
+                    << field->get_name() << " is unset!');" << endl;
+        indent_down();
+        indent(out) << "}" << endl;
+      }
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_php_generator::generate_php_struct_json_serialize(ofstream& out,
+                                                         t_struct* tstruct,
+                                                         bool is_result) {
+  indent(out) << "public function jsonSerialize() {" << endl;
+  indent_up();
+
+  if (needs_php_write_validator(tstruct, is_result)) {
+    indent(out) << "$this->_validateForWrite();" << endl;
+  }
+
+  indent(out) << "$json = new stdClass;" << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+
+  if (fields.size() > 0) {
+    vector<t_field*>::const_iterator f_iter;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = (*f_iter);
+      t_type* type = field->get_type();
+      const string& name = field->get_name();
+      if (type->is_map()) {
+        t_type* key_type = ((t_map*)type)->get_key_type();
+        if (!(key_type->is_base_type() || key_type->is_enum())) {
+          // JSON object keys must be strings. PHP's json_encode()
+          // function will convert any scalar key to strings, but
+          // we skip thrift maps with non-scalar keys.
+          continue;
+        }
+      }
+      indent(out) << "if ($this->" << name << " !== null) {" << endl;
+      indent_up();
+      indent(out) << "$json->" << name << " = ";
+      if (type->is_map()) {
+        out << "(object)";
+      } else {
+        out << type_to_cast(type);
+      }
+      out << "$this->" << name << ";" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent(out) << "return $json;" << endl;
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+int t_php_generator::get_php_num_required_fields(const vector<t_field*>& fields, bool write_mode) {
+  int num_req = 0;
+
+  if (fields.size() > 0) {
+    vector<t_field*>::const_iterator f_iter;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if ((*f_iter)->get_req() == t_field::T_REQUIRED
+          || ((*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT && write_mode)) {
+        ++num_req;
+      }
+    }
+  }
+  return num_req;
+}
+
+bool t_php_generator::needs_php_write_validator(t_struct* tstruct, bool is_result) {
+  return (validate_ && !is_result && !tstruct->is_union()
+          && get_php_num_required_fields(tstruct->get_members(), true) > 0);
+}
+
+bool t_php_generator::needs_php_read_validator(t_struct* tstruct, bool is_result) {
+  return (validate_ && !is_result
+          && (get_php_num_required_fields(tstruct->get_members(), false) > 0));
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_php_generator::generate_service(t_service* tservice) {
+  if(!psr4_) {
+    string f_service_name = package_dir_ + service_name_ + ".php";
+    f_service_.open(f_service_name.c_str());
+    generate_service_header(tservice, f_service_);
+  }
+
+  // Generate the three main parts of the service (well, two for now in PHP)
+  generate_service_interface(tservice);
+  if (rest_) {
+    generate_service_rest(tservice);
+  }
+  generate_service_client(tservice);
+  generate_service_helpers(tservice);
+  if (phps_) {
+    generate_service_processor(tservice);
+  }
+
+  if(!psr4_) {
+    // Close service file
+    f_service_ << endl;
+    f_service_.close();
+  }
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_php_generator::generate_service_processor(t_service* tservice) {
+  std::ofstream& f_service_processor = f_service_;
+  if (psr4_) {
+    string f_service_processor_name = package_dir_ + service_name_ + "Processor.php";
+    f_service_processor.open(f_service_processor_name.c_str());
+    generate_service_header(tservice, f_service_processor);
+  }
+
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = tservice->get_extends()->get_name();
+    extends_processor = " extends " + php_namespace(tservice->get_extends()->get_program())
+                        + extends + "Processor";
+  }
+
+  // Generate the header portion
+  f_service_processor << "class " << service_name_ << "Processor" << extends_processor << " {" << endl;
+  indent_up();
+
+  if (extends.empty()) {
+    f_service_processor << indent() << "protected $handler_ = null;" << endl;
+  }
+
+  f_service_processor << indent() << "public function __construct($handler) {" << endl;
+  if (extends.empty()) {
+    f_service_processor << indent() << "  $this->handler_ = $handler;" << endl;
+  } else {
+    f_service_processor << indent() << "  parent::__construct($handler);" << endl;
+  }
+  f_service_processor << indent() << "}" << endl << endl;
+
+  // Generate the server implementation
+  indent(f_service_processor) << "public function process($input, $output) {" << endl;
+  indent_up();
+
+  f_service_processor << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl
+                      << indent() << "$mtype = 0;" << endl << endl;
+
+  if (binary_inline_) {
+    t_field ffname(g_type_string, "fname");
+    t_field fmtype(g_type_i8, "mtype");
+    t_field fseqid(g_type_i32, "rseqid");
+    generate_deserialize_field(f_service_processor, &ffname, "", true);
+    generate_deserialize_field(f_service_processor, &fmtype, "", true);
+    generate_deserialize_field(f_service_processor, &fseqid, "", true);
+  } else {
+    f_service_processor << indent() << "$input->readMessageBegin($fname, $mtype, $rseqid);" << endl;
+  }
+
+  // HOT: check for method implementation
+  f_service_processor << indent() << "$methodname = 'process_'.$fname;" << endl << indent()
+                      << "if (!method_exists($this, $methodname)) {" << endl;
+  if (binary_inline_) {
+    f_service_processor << indent() << "  throw new \\Exception('Function '.$fname.' not implemented.');"
+                        << endl;
+  } else {
+    f_service_processor << indent() << "  $input->skip("
+                        << "TType::STRUCT);" << endl << indent() << "  $input->readMessageEnd();" << endl
+                        << indent() << "  $x = new "
+                        << "TApplicationException('Function '.$fname.' not implemented.', "
+                        << "TApplicationException::UNKNOWN_METHOD);" << endl << indent()
+                        << "  $output->writeMessageBegin($fname, "
+                        << "TMessageType::EXCEPTION, $rseqid);" << endl << indent()
+                        << "  $x->write($output);" << endl << indent() << "  $output->writeMessageEnd();"
+                        << endl << indent() << "  $output->getTransport()->flush();" << endl << indent()
+                        << "  return;" << endl;
+  }
+  f_service_processor << indent() << "}" << endl << indent()
+                      << "$this->$methodname($rseqid, $input, $output);" << endl << indent()
+                      << "return true;" << endl;
+  indent_down();
+  f_service_processor << indent() << "}" << endl << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(f_service_processor, tservice, *f_iter);
+  }
+
+  indent_down();
+  f_service_processor << "}" << endl;
+
+  if (psr4_) {
+    f_service_processor.close();
+  }
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_php_generator::generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction) {
+  // Open function
+  indent(out) << "protected function process_" << tfunction->get_name()
+                     << "($seqid, $input, $output) {" << endl;
+  indent_up();
+
+  string argsname = php_namespace(tservice->get_program()) + service_name_ + "_"
+                    + tfunction->get_name() + "_args";
+  string resultname = php_namespace(tservice->get_program()) + service_name_ + "_"
+                      + tfunction->get_name() + "_result";
+
+  out << indent() << "$args = new " << argsname << "();" << endl << indent()
+             << "$args->read($input);" << endl;
+  if (!binary_inline_) {
+    out << indent() << "$input->readMessageEnd();" << endl;
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    out << indent() << "$result = new " << resultname << "();" << endl;
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    out << indent() << "try {" << endl;
+    indent_up();
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    out << "$result->success = ";
+  }
+  out << "$this->handler_->" << tfunction->get_name() << "(";
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      out << ", ";
+    }
+    out << "$args->" << (*f_iter)->get_name();
+  }
+  out << ");" << endl;
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    indent_down();
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      out << indent() << "} catch ("
+                 << php_namespace(get_true_type((*x_iter)->get_type())->get_program())
+                 << (*x_iter)->get_type()->get_name() << " $" << (*x_iter)->get_name() << ") {"
+                 << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        out << indent() << "$result->" << (*x_iter)->get_name() << " = $"
+                   << (*x_iter)->get_name() << ";" << endl;
+        indent_down();
+        out << indent();
+      }
+    }
+    out << "}" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    out << indent() << "return;" << endl;
+    indent_down();
+    out << indent() << "}" << endl;
+    return;
+  }
+
+  out << indent() << "$bin_accel = ($output instanceof "
+             << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');"
+             << endl;
+
+  out << indent() << "if ($bin_accel)" << endl;
+  scope_up(out);
+
+  out << indent() << "thrift_protocol_write_binary($output, '" << tfunction->get_name()
+             << "', "
+             << "TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());" << endl;
+
+  scope_down(out);
+  out << indent() << "else" << endl;
+  scope_up(out);
+
+  // Serialize the request header
+  if (binary_inline_) {
+    out << indent() << "$buff = pack('N', (0x80010000 | "
+        << "TMessageType::REPLY)); " << endl << indent() << "$buff .= pack('N', strlen('"
+        << tfunction->get_name() << "'));" << endl << indent() << "$buff .= '"
+        << tfunction->get_name() << "';" << endl << indent() << "$buff .= pack('N', $seqid);"
+        << endl << indent() << "$result->write($buff);" << endl << indent()
+        << "$output->write($buff);" << endl << indent() << "$output->flush();" << endl;
+  } else {
+    out << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', "
+        << "TMessageType::REPLY, $seqid);" << endl << indent() << "$result->write($output);"
+        << endl << indent() << "$output->writeMessageEnd();" << endl << indent()
+        << "$output->getTransport()->flush();" << endl;
+  }
+
+  scope_down(out);
+
+  // Close function
+  indent_down();
+  out << indent() << "}" << endl;
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_php_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  std::ofstream& f_struct_definition = f_service_;
+  if (!psr4_) {
+    f_struct_definition << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+  }
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    string name = ts->get_name();
+    ts->set_name(service_name_ + "_" + name);
+
+    if (psr4_) {
+      string f_struct_definition_name = package_dir_ + service_name_ + "_" + name + ".php";
+      f_struct_definition.open(f_struct_definition_name.c_str());
+      generate_service_header(tservice, f_struct_definition);
+    }
+
+    generate_php_struct_definition(f_struct_definition, ts);
+    if (psr4_) {
+      f_struct_definition.close();
+    }
+
+    generate_php_function_helpers(tservice, *f_iter);
+    ts->set_name(name);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_php_generator::generate_php_function_helpers(t_service* tservice, t_function* tfunction) {
+  if (!tfunction->is_oneway()) {
+    t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
+    t_field success(tfunction->get_returntype(), "success", 0);
+    if (!tfunction->get_returntype()->is_void()) {
+      result.append(&success);
+    }
+
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& fields = xs->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      result.append(*f_iter);
+    }
+
+    std::ofstream& f_struct_helper = f_service_;
+    if (psr4_) {
+      string f_struct_helper_name = package_dir_ + result.get_name() + ".php";
+      f_struct_helper.open(f_struct_helper_name.c_str());
+      generate_service_header(tservice, f_struct_helper);
+    }
+    generate_php_struct_definition(f_struct_helper, &result, false, true);
+    if (psr4_) {
+      f_struct_helper.close();
+    }
+  }
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_php_generator::generate_service_interface(t_service* tservice) {
+  std::ofstream& f_service_interface = f_service_;
+  if (psr4_) {
+    string f_service_interface_name = package_dir_ + service_name_ + "If.php";
+    f_service_interface.open(f_service_interface_name.c_str());
+    generate_service_header(tservice, f_service_interface);
+  }
+
+  string extends = "";
+  string extends_if = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " extends " + php_namespace(tservice->get_extends()->get_program())
+              + tservice->get_extends()->get_name();
+    extends_if = " extends " + php_namespace(tservice->get_extends()->get_program())
+                 + tservice->get_extends()->get_name() + "If";
+  }
+  generate_php_doc(f_service_interface, tservice);
+  f_service_interface << "interface " << php_namespace_declaration(tservice) << "If" << extends_if << " {"
+             << endl;
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_php_doc(f_service_interface, *f_iter);
+    indent(f_service_interface) << "public function " << function_signature(*f_iter) << ";" << endl;
+  }
+  indent_down();
+  f_service_interface << "}" << endl << endl;
+
+  // Close service interface file
+  f_service_interface << endl;
+  if (psr4_) {
+    f_service_interface.close();
+  }
+}
+
+/**
+ * Generates a REST interface
+ */
+void t_php_generator::generate_service_rest(t_service* tservice) {
+  std::ofstream& f_service_rest = f_service_;
+  if (psr4_) {
+    string f_service_rest_name = package_dir_ + service_name_ + "Rest.php";
+    f_service_rest.open(f_service_rest_name.c_str());
+    generate_service_header(tservice, f_service_rest);
+  }
+
+  string extends = "";
+  string extends_if = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " extends " + php_namespace(tservice->get_extends()->get_program())
+              + tservice->get_extends()->get_name();
+    extends_if = " extends " + php_namespace(tservice->get_extends()->get_program())
+                 + tservice->get_extends()->get_name() + "Rest";
+  }
+  f_service_rest << "class " << service_name_ << "Rest" << extends_if << " {" << endl;
+  indent_up();
+
+  if (extends.empty()) {
+    f_service_rest << indent() << "protected $impl_;" << endl << endl;
+  }
+
+  f_service_rest << indent() << "public function __construct($impl) {" << endl << indent()
+             << "  $this->impl_ = $impl;" << endl << indent() << "}" << endl << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent(f_service_rest) << "public function " << (*f_iter)->get_name() << "($request) {" << endl;
+    indent_up();
+    const vector<t_field*>& args = (*f_iter)->get_arglist()->get_members();
+    vector<t_field*>::const_iterator a_iter;
+    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+      t_type* atype = get_true_type((*a_iter)->get_type());
+      string cast = type_to_cast(atype);
+      string req = "$request['" + (*a_iter)->get_name() + "']";
+      if (atype->is_bool()) {
+        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = " << cast << "(!empty(" << req
+                   << ") && (" << req << " !== 'false'));" << endl;
+      } else {
+        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = isset(" << req << ") ? "
+                   << cast << req << " : null;" << endl;
+      }
+      if (atype->is_string() && ((t_base_type*)atype)->is_string_list()) {
+        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = explode(',', $"
+                       << (*a_iter)->get_name() << ");" << endl;
+      } else if (atype->is_map() || atype->is_list()) {
+        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = json_decode($"
+                       << (*a_iter)->get_name() << ", true);" << endl;
+      } else if (atype->is_set()) {
+        f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = array_fill_keys(json_decode($"
+                       << (*a_iter)->get_name() << ", true), 1);" << endl;
+      } else if (atype->is_struct() || atype->is_xception()) {
+        f_service_rest << indent() << "if ($" << (*a_iter)->get_name() << " !== null) {" << endl
+                       << indent() << "  $" << (*a_iter)->get_name() << " = new "
+                       << php_namespace(atype->get_program()) << atype->get_name() << "(json_decode($"
+                       << (*a_iter)->get_name() << ", true));" << endl << indent() << "}" << endl;
+      }
+    }
+    f_service_rest << indent() << "return $this->impl_->" << (*f_iter)->get_name() << "("
+               << argument_list((*f_iter)->get_arglist(), false) << ");" << endl;
+    indent_down();
+    indent(f_service_rest) << "}" << endl << endl;
+  }
+  indent_down();
+  f_service_rest << "}" << endl << endl;
+
+  // Close service rest file
+  f_service_rest << endl;
+  if (psr4_) {
+    f_service_rest.close();
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_php_generator::generate_service_client(t_service* tservice) {
+  std::ofstream& f_service_client = f_service_;
+  if (psr4_) {
+    string f_service_client_name = package_dir_ + service_name_ + "Client.php";
+    f_service_client.open(f_service_client_name.c_str());
+    generate_service_header(tservice, f_service_client);
+  }
+
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = tservice->get_extends()->get_name();
+    extends_client = " extends " + php_namespace(tservice->get_extends()->get_program()) + extends
+                     + "Client";
+  }
+
+  f_service_client << "class " << php_namespace_declaration(tservice) << "Client" << extends_client
+             << " implements " << php_namespace(tservice->get_program()) << service_name_ << "If {"
+             << endl;
+  indent_up();
+
+  // Private members
+  if (extends.empty()) {
+    f_service_client << indent() << "protected $input_ = null;" << endl << indent()
+               << "protected $output_ = null;" << endl << endl;
+    f_service_client << indent() << "protected $seqid_ = 0;" << endl << endl;
+  }
+
+  // Constructor function
+  f_service_client << indent() << "public function __construct($input, $output=null) {" << endl;
+  if (!extends.empty()) {
+    f_service_client << indent() << "  parent::__construct($input, $output);" << endl;
+  } else {
+    f_service_client << indent() << "  $this->input_ = $input;" << endl << indent()
+               << "  $this->output_ = $output ? $output : $input;" << endl;
+  }
+  f_service_client << indent() << "}" << endl << endl;
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    indent(f_service_client) << "public function " << function_signature(*f_iter) << endl;
+    scope_up(f_service_client);
+    indent(f_service_client) << "$this->send_" << funname << "(";
+
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_client << ", ";
+      }
+      f_service_client << "$" << (*fld_iter)->get_name();
+    }
+    f_service_client << ");" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_client << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_client << "return ";
+      }
+      f_service_client << "$this->recv_" << funname << "();" << endl;
+    }
+    scope_down(f_service_client);
+    f_service_client << endl;
+
+    indent(f_service_client) << "public function send_" << function_signature(*f_iter) << endl;
+    scope_up(f_service_client);
+
+    std::string argsname = php_namespace(tservice->get_program()) + service_name_ + "_"
+                           + (*f_iter)->get_name() + "_args";
+
+    f_service_client << indent() << "$args = new " << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_client << indent() << "$args->" << (*fld_iter)->get_name() << " = $"
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    f_service_client << indent() << "$bin_accel = ($this->output_ instanceof "
+               << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');"
+               << endl;
+
+    f_service_client << indent() << "if ($bin_accel)" << endl;
+    scope_up(f_service_client);
+
+    string messageType = (*f_iter)->is_oneway() ? "TMessageType::ONEWAY" : "TMessageType::CALL";
+
+    f_service_client << indent() << "thrift_protocol_write_binary($this->output_, '"
+               << (*f_iter)->get_name() << "', " << messageType
+               << ", $args, $this->seqid_, $this->output_->isStrictWrite());" << endl;
+
+    scope_down(f_service_client);
+    f_service_client << indent() << "else" << endl;
+    scope_up(f_service_client);
+
+    // Serialize the request header
+    if (binary_inline_) {
+      f_service_client << indent() << "$buff = pack('N', (0x80010000 | " << messageType << "));" << endl
+                       << indent() << "$buff .= pack('N', strlen('" << funname << "'));" << endl
+                       << indent() << "$buff .= '" << funname << "';" << endl << indent()
+                       << "$buff .= pack('N', $this->seqid_);" << endl;
+    } else {
+      f_service_client << indent() << "$this->output_->writeMessageBegin('" << (*f_iter)->get_name()
+                       << "', " << messageType << ", $this->seqid_);" << endl;
+    }
+
+    // Write to the stream
+    if (binary_inline_) {
+      f_service_client << indent() << "$args->write($buff);" << endl << indent()
+                       << "$this->output_->write($buff);" << endl << indent()
+                       << "$this->output_->flush();" << endl;
+    } else {
+      f_service_client << indent() << "$args->write($this->output_);" << endl << indent()
+                       << "$this->output_->writeMessageEnd();" << endl << indent()
+                       << "$this->output_->getTransport()->flush();" << endl;
+    }
+
+    scope_down(f_service_client);
+
+    scope_down(f_service_client);
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = php_namespace(tservice->get_program()) + service_name_ + "_"
+                               + (*f_iter)->get_name() + "_result";
+      t_struct noargs(program_);
+
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs);
+      // Open function
+      f_service_client << endl << indent() << "public function " << function_signature(&recv_function)
+                       << endl;
+      scope_up(f_service_client);
+
+      f_service_client << indent() << "$bin_accel = ($this->input_ instanceof "
+                       << "TBinaryProtocolAccelerated)"
+                       << " && function_exists('thrift_protocol_read_binary');" << endl;
+
+      f_service_client << indent()
+                       << "if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '"
+                       << resultname << "', $this->input_->isStrictRead());" << endl;
+      f_service_client << indent() << "else" << endl;
+      scope_up(f_service_client);
+
+      f_service_client << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl
+                 << indent() << "$mtype = 0;" << endl << endl;
+
+      if (binary_inline_) {
+        t_field ffname(g_type_string, "fname");
+        t_field fseqid(g_type_i32, "rseqid");
+        f_service_client << indent() << "$ver = unpack('N', $this->input_->readAll(4));" << endl
+                         << indent() << "$ver = $ver[1];" << endl << indent() << "$mtype = $ver & 0xff;"
+                         << endl << indent() << "$ver = $ver & 0xffff0000;" << endl << indent()
+                         << "if ($ver != 0x80010000) throw new "
+                         << "TProtocolException('Bad version identifier: '.$ver, "
+                         << "TProtocolException::BAD_VERSION);" << endl;
+        generate_deserialize_field(f_service_client, &ffname, "", true);
+        generate_deserialize_field(f_service_client, &fseqid, "", true);
+      } else {
+        f_service_client << indent() << "$this->input_->readMessageBegin($fname, $mtype, $rseqid);"
+                         << endl << indent() << "if ($mtype == "
+                         << "TMessageType::EXCEPTION) {" << endl << indent() << "  $x = new "
+                         << "TApplicationException();" << endl << indent() << "  $x->read($this->input_);"
+                         << endl << indent() << "  $this->input_->readMessageEnd();" << endl << indent()
+                         << "  throw $x;" << endl << indent() << "}" << endl;
+      }
+
+      f_service_client << indent() << "$result = new " << resultname << "();" << endl << indent()
+                       << "$result->read($this->input_);" << endl;
+
+      if (!binary_inline_) {
+        f_service_client << indent() << "$this->input_->readMessageEnd();" << endl;
+      }
+
+      scope_down(f_service_client);
+
+      // Careful, only return result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_client << indent() << "if ($result->success !== null) {" << endl << indent()
+                   << "  return $result->success;" << endl << indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_client << indent() << "if ($result->" << (*x_iter)->get_name() << " !== null) {" << endl
+                         << indent() << "  throw $result->" << (*x_iter)->get_name() << ";" << endl
+                         << indent() << "}" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_client) << "return;" << endl;
+      } else {
+        f_service_client << indent() << "throw new \\Exception(\"" << (*f_iter)->get_name()
+                         << " failed: unknown result\");" << endl;
+      }
+
+      // Close function
+      scope_down(f_service_client);
+      f_service_client << endl;
+    }
+  }
+
+  indent_down();
+  f_service_client << "}" << endl << endl;
+
+  // Close service client file
+  f_service_client << endl;
+  if (psr4_) {
+    f_service_client.close();
+  }
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_php_generator::generate_deserialize_field(ofstream& out,
+                                                 t_field* tfield,
+                                                 string prefix,
+                                                 bool inclass) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else {
+
+    if (type->is_container()) {
+      generate_deserialize_container(out, type, name);
+    } else if (type->is_base_type() || type->is_enum()) {
+
+      if (binary_inline_) {
+        std::string itrans = (inclass ? "$this->input_" : "$input");
+
+        if (type->is_base_type()) {
+          t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+          switch (tbase) {
+          case t_base_type::TYPE_VOID:
+            throw "compiler error: cannot serialize void field in a struct: " + name;
+            break;
+          case t_base_type::TYPE_STRING:
+            out << indent() << "$len = unpack('N', " << itrans << "->readAll(4));" << endl
+                << indent() << "$len = $len[1];" << endl << indent() << "if ($len > 0x7fffffff) {"
+                << endl << indent() << "  $len = 0 - (($len - 1) ^ 0xffffffff);" << endl << indent()
+                << "}" << endl << indent() << "$" << name << " = " << itrans << "->readAll($len);"
+                << endl;
+            break;
+          case t_base_type::TYPE_BOOL:
+            out << indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));"
+                << endl << indent() << "$" << name << " = (bool)$" << name << "[1];" << endl;
+            break;
+          case t_base_type::TYPE_I8:
+            out << indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));"
+                << endl << indent() << "$" << name << " = $" << name << "[1];" << endl;
+            break;
+          case t_base_type::TYPE_I16:
+            out << indent() << "$val = unpack('n', " << itrans << "->readAll(2));" << endl
+                << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fff) {"
+                << endl << indent() << "  $val = 0 - (($val - 1) ^ 0xffff);" << endl << indent()
+                << "}" << endl << indent() << "$" << name << " = $val;" << endl;
+            break;
+          case t_base_type::TYPE_I32:
+            out << indent() << "$val = unpack('N', " << itrans << "->readAll(4));" << endl
+                << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fffffff) {"
+                << endl << indent() << "  $val = 0 - (($val - 1) ^ 0xffffffff);" << endl << indent()
+                << "}" << endl << indent() << "$" << name << " = $val;" << endl;
+            break;
+          case t_base_type::TYPE_I64:
+            out << indent() << "$arr = unpack('N2', " << itrans << "->readAll(8));" << endl
+                << indent() << "if ($arr[1] & 0x80000000) {" << endl << indent()
+                << "  $arr[1] = $arr[1] ^ 0xFFFFFFFF;" << endl << indent()
+                << "  $arr[2] = $arr[2] ^ 0xFFFFFFFF;" << endl << indent() << "  $" << name
+                << " = 0 - $arr[1]*4294967296 - $arr[2] - 1;" << endl << indent() << "} else {"
+                << endl << indent() << "  $" << name << " = $arr[1]*4294967296 + $arr[2];" << endl
+                << indent() << "}" << endl;
+            break;
+          case t_base_type::TYPE_DOUBLE:
+            out << indent() << "$arr = unpack('d', strrev(" << itrans << "->readAll(8)));" << endl
+                << indent() << "$" << name << " = $arr[1];" << endl;
+            break;
+          default:
+            throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase)
+                + tfield->get_name();
+          }
+        } else if (type->is_enum()) {
+          out << indent() << "$val = unpack('N', " << itrans << "->readAll(4));" << endl << indent()
+              << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fffffff) {" << endl
+              << indent() << "  $val = 0 - (($val - 1) ^ 0xffffffff);" << endl << indent() << "}"
+              << endl << indent() << "$" << name << " = $val;" << endl;
+        }
+      } else {
+
+        indent(out) << "$xfer += $input->";
+
+        if (type->is_base_type()) {
+          t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+          switch (tbase) {
+          case t_base_type::TYPE_VOID:
+            throw "compiler error: cannot serialize void field in a struct: " + name;
+            break;
+          case t_base_type::TYPE_STRING:
+            out << "readString($" << name << ");";
+            break;
+          case t_base_type::TYPE_BOOL:
+            out << "readBool($" << name << ");";
+            break;
+          case t_base_type::TYPE_I8:
+            out << "readByte($" << name << ");";
+            break;
+          case t_base_type::TYPE_I16:
+            out << "readI16($" << name << ");";
+            break;
+          case t_base_type::TYPE_I32:
+            out << "readI32($" << name << ");";
+            break;
+          case t_base_type::TYPE_I64:
+            out << "readI64($" << name << ");";
+            break;
+          case t_base_type::TYPE_DOUBLE:
+            out << "readDouble($" << name << ");";
+            break;
+          default:
+            throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
+          }
+        } else if (type->is_enum()) {
+          out << "readI32($" << name << ");";
+        }
+        out << endl;
+      }
+    } else {
+      printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+             tfield->get_name().c_str(),
+             type->get_name().c_str());
+    }
+  }
+}
+
+/**
+ * Generates an unserializer for a variable. This makes two key assumptions,
+ * first that there is a const char* variable named data that points to the
+ * buffer for deserialization, and that there is a variable protocol which
+ * is a reference to a TProtocol serialization object.
+ */
+void t_php_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  out << indent() << "$" << prefix << " = new " << php_namespace(tstruct->get_program())
+      << tstruct->get_name() << "();" << endl << indent() << "$xfer += $" << prefix
+      << "->read($input);" << endl;
+}
+
+void t_php_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_i8, ktype);
+  t_field fvtype(g_type_i8, vtype);
+  t_field fetype(g_type_i8, etype);
+
+  out << indent() << "$" << prefix << " = array();" << endl << indent() << "$" << size << " = 0;"
+      << endl;
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    out << indent() << "$" << ktype << " = 0;" << endl << indent() << "$" << vtype << " = 0;"
+        << endl;
+    if (binary_inline_) {
+      generate_deserialize_field(out, &fktype);
+      generate_deserialize_field(out, &fvtype);
+      generate_deserialize_field(out, &fsize);
+    } else {
+      out << indent() << "$xfer += $input->readMapBegin("
+          << "$" << ktype << ", $" << vtype << ", $" << size << ");" << endl;
+    }
+  } else if (ttype->is_set()) {
+    if (binary_inline_) {
+      generate_deserialize_field(out, &fetype);
+      generate_deserialize_field(out, &fsize);
+    } else {
+      out << indent() << "$" << etype << " = 0;" << endl << indent()
+          << "$xfer += $input->readSetBegin("
+          << "$" << etype << ", $" << size << ");" << endl;
+    }
+  } else if (ttype->is_list()) {
+    if (binary_inline_) {
+      generate_deserialize_field(out, &fetype);
+      generate_deserialize_field(out, &fsize);
+    } else {
+      out << indent() << "$" << etype << " = 0;" << endl << indent()
+          << "$xfer += $input->readListBegin("
+          << "$" << etype << ", $" << size << ");" << endl;
+    }
+  }
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for ($" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  if (!binary_inline_) {
+    // Read container end
+    if (ttype->is_map()) {
+      indent(out) << "$xfer += $input->readMapEnd();" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) << "$xfer += $input->readSetEnd();" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) << "$xfer += $input->readListEnd();" << endl;
+    }
+  }
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_php_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("key");
+  string val = tmp("val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey, true, true) << endl;
+  indent(out) << declare_field(&fval, true, true) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << "$" << prefix << "[$" << key << "] = $" << val << ";" << endl;
+}
+
+void t_php_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << "$" << elem << " = null;" << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << "if (is_scalar($" << elem << ")) {" << endl;
+  indent(out) << "  $" << prefix << "[$" << elem << "] = true;" << endl;
+  indent(out) << "} else {" << endl;
+  indent(out) << "  $" << prefix << " []= $" << elem << ";" << endl;
+  indent(out) << "}" << endl;
+}
+
+void t_php_generator::generate_deserialize_list_element(ofstream& out,
+                                                        t_list* tlist,
+                                                        string prefix) {
+  string elem = tmp("elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << "$" << elem << " = null;" << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << "$" << prefix << " []= $" << elem << ";" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_php_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + tfield->get_name());
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = prefix + tfield->get_name();
+
+    if (binary_inline_) {
+      if (type->is_base_type()) {
+        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+        switch (tbase) {
+        case t_base_type::TYPE_VOID:
+          throw "compiler error: cannot serialize void field in a struct: " + name;
+          break;
+        case t_base_type::TYPE_STRING:
+          out << indent() << "$output .= pack('N', strlen($" << name << "));" << endl << indent()
+              << "$output .= $" << name << ";" << endl;
+          break;
+        case t_base_type::TYPE_BOOL:
+          out << indent() << "$output .= pack('c', $" << name << " ? 1 : 0);" << endl;
+          break;
+        case t_base_type::TYPE_I8:
+          out << indent() << "$output .= pack('c', $" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_I16:
+          out << indent() << "$output .= pack('n', $" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_I32:
+          out << indent() << "$output .= pack('N', $" << name << ");" << endl;
+          break;
+        case t_base_type::TYPE_I64:
+          out << indent() << "$output .= pack('N2', $" << name << " >> 32, $" << name
+              << " & 0xFFFFFFFF);" << endl;
+          break;
+        case t_base_type::TYPE_DOUBLE:
+          out << indent() << "$output .= strrev(pack('d', $" << name << "));" << endl;
+          break;
+        default:
+          throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
+        }
+      } else if (type->is_enum()) {
+        out << indent() << "$output .= pack('N', $" << name << ");" << endl;
+      }
+    } else {
+
+      indent(out) << "$xfer += $output->";
+
+      if (type->is_base_type()) {
+        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+        switch (tbase) {
+        case t_base_type::TYPE_VOID:
+          throw "compiler error: cannot serialize void field in a struct: " + name;
+          break;
+        case t_base_type::TYPE_STRING:
+          out << "writeString($" << name << ");";
+          break;
+        case t_base_type::TYPE_BOOL:
+          out << "writeBool($" << name << ");";
+          break;
+        case t_base_type::TYPE_I8:
+          out << "writeByte($" << name << ");";
+          break;
+        case t_base_type::TYPE_I16:
+          out << "writeI16($" << name << ");";
+          break;
+        case t_base_type::TYPE_I32:
+          out << "writeI32($" << name << ");";
+          break;
+        case t_base_type::TYPE_I64:
+          out << "writeI64($" << name << ");";
+          break;
+        case t_base_type::TYPE_DOUBLE:
+          out << "writeDouble($" << name << ");";
+          break;
+        default:
+          throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
+        }
+      } else if (type->is_enum()) {
+        out << "writeI32($" << name << ");";
+      }
+      out << endl;
+    }
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_php_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << "$xfer += $" << prefix << "->write($output);" << endl;
+}
+
+/**
+ * Writes out a container
+ */
+void t_php_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    if (binary_inline_) {
+      out << indent() << "$output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_key_type())
+          << ");" << endl << indent() << "$output .= pack('c', "
+          << type_to_enum(((t_map*)ttype)->get_val_type()) << ");" << endl << indent()
+          << "$output .= strrev(pack('l', count($" << prefix << ")));" << endl;
+    } else {
+      indent(out) << "$output->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                  << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
+                  << "count($" << prefix << "));" << endl;
+    }
+  } else if (ttype->is_set()) {
+    if (binary_inline_) {
+      out << indent() << "$output .= pack('c', " << type_to_enum(((t_set*)ttype)->get_elem_type())
+          << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));"
+          << endl;
+
+    } else {
+      indent(out) << "$output->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                  << ", "
+                  << "count($" << prefix << "));" << endl;
+    }
+  } else if (ttype->is_list()) {
+    if (binary_inline_) {
+      out << indent() << "$output .= pack('c', " << type_to_enum(((t_list*)ttype)->get_elem_type())
+          << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));"
+          << endl;
+
+    } else {
+      indent(out) << "$output->writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
+                  << ", "
+                  << "count($" << prefix << "));" << endl;
+    }
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    string kiter = tmp("kiter");
+    string viter = tmp("viter");
+    indent(out) << "foreach ($" << prefix << " as "
+                << "$" << kiter << " => $" << viter << ")" << endl;
+    scope_up(out);
+    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+    scope_down(out);
+  } else if (ttype->is_set()) {
+    string iter = tmp("iter");
+    string iter_val = tmp("iter");
+    indent(out) << "foreach ($" << prefix << " as $" << iter << " => $" << iter_val << ")" << endl;
+    scope_up(out);
+    indent(out) << "if (is_scalar($" << iter_val << ")) {" << endl;
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    indent(out) << "} else {" << endl;
+    generate_serialize_set_element(out, (t_set*)ttype, iter_val);
+    indent(out) << "}" << endl;
+    scope_down(out);
+  } else if (ttype->is_list()) {
+    string iter = tmp("iter");
+    indent(out) << "foreach ($" << prefix << " as $" << iter << ")" << endl;
+    scope_up(out);
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    scope_down(out);
+  }
+
+  scope_down(out);
+
+  if (!binary_inline_) {
+    if (ttype->is_map()) {
+      indent(out) << "$output->writeMapEnd();" << endl;
+    } else if (ttype->is_set()) {
+      indent(out) << "$output->writeSetEnd();" << endl;
+    } else if (ttype->is_list()) {
+      indent(out) << "$output->writeListEnd();" << endl;
+    }
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ *
+ */
+void t_php_generator::generate_serialize_map_element(ofstream& out,
+                                                     t_map* tmap,
+                                                     string kiter,
+                                                     string viter) {
+  t_field kfield(tmap->get_key_type(), kiter);
+  generate_serialize_field(out, &kfield, "");
+
+  t_field vfield(tmap->get_val_type(), viter);
+  generate_serialize_field(out, &vfield, "");
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_php_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_php_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Emits a PHPDoc comment for the given contents
+ */
+void t_php_generator::generate_php_docstring_comment(ofstream& out, string contents) {
+  generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
+}
+
+/**
+ * Emits a PHPDoc comment if the provided object has a doc in Thrift
+ */
+void t_php_generator::generate_php_doc(ofstream& out, t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    generate_php_docstring_comment(out, tdoc->get_doc());
+  }
+}
+
+/**
+ * Emits a PHPDoc comment for a field
+ */
+void t_php_generator::generate_php_doc(ofstream& out, t_field* field) {
+  stringstream ss;
+
+  // prepend free-style doc if available
+  if (field->has_doc()) {
+    ss << field->get_doc() << endl;
+  }
+
+  // append @var tag
+  t_type* type = get_true_type(field->get_type());
+  ss << "@var " << type_to_phpdoc(type) << endl;
+
+  generate_php_docstring_comment(out, ss.str());
+}
+
+/**
+ * Emits a PHPDoc comment for a function
+ */
+void t_php_generator::generate_php_doc(ofstream& out, t_function* function) {
+  stringstream ss;
+  if (function->has_doc()) {
+    ss << function->get_doc() << endl;
+  }
+
+  // generate parameter types doc
+  const vector<t_field*>& args = function->get_arglist()->get_members();
+  vector<t_field*>::const_iterator a_iter;
+  for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+    t_field* arg = *a_iter;
+    ss << "@param " << type_to_phpdoc(arg->get_type()) << " $" << arg->get_name();
+    if (arg->has_doc()) {
+      ss << " " << arg->get_doc();
+    }
+    ss << endl;
+  }
+
+  // generate return type doc
+  t_type* ret_type = function->get_returntype();
+  if (!ret_type->is_void() || ret_type->has_doc()) {
+    ss << "@return " << type_to_phpdoc(ret_type);
+    if (ret_type->has_doc()) {
+      ss << " " << ret_type->get_doc();
+    }
+    ss << endl;
+  }
+
+  // generate exceptions doc
+  const vector<t_field*>& excs = function->get_xceptions()->get_members();
+  vector<t_field*>::const_iterator e_iter;
+  for (e_iter = excs.begin(); e_iter != excs.end(); ++e_iter) {
+    t_field* exc = *e_iter;
+    ss << "@throws " << type_to_phpdoc(exc->get_type());
+    if (exc->has_doc()) {
+      ss << " " << exc->get_doc();
+    }
+    ss << endl;
+  }
+
+  generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n");
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ */
+string t_php_generator::declare_field(t_field* tfield, bool init, bool obj) {
+  string result = "$" + tfield->get_name();
+  if (init) {
+    t_type* type = get_true_type(tfield->get_type());
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        break;
+      case t_base_type::TYPE_STRING:
+        result += " = ''";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+        result += " = 0";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = 0.0";
+        break;


<TRUNCATED>

[15/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_erl_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc
new file mode 100644
index 0000000..4869414
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc
@@ -0,0 +1,1169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const std::string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Erlang code generator.
+ *
+ */
+class t_erl_generator : public t_generator {
+public:
+  t_erl_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    legacy_names_ = false;
+    maps_ = false;
+    otp16_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("legacynames") == 0) {
+        legacy_names_ = true;
+      } else if( iter->first.compare("maps") == 0) {
+        maps_ = true;
+      } else if( iter->first.compare("otp16") == 0) {
+        otp16_ = true;
+      } else {
+        throw "unknown option erl:" + iter->first;
+      }
+    }
+
+    if (maps_ && otp16_) {
+      throw "argument error: Cannot specify both maps and otp16; maps are not available for Erlang/OTP R16 or older";
+    }
+
+    out_dir_base_ = "gen-erl";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+  void generate_member_type(std::ostream& out, t_type* type);
+  void generate_member_value(std::ostream& out, t_type* type, t_const_value* value);
+
+  std::string render_member_type(t_field* field);
+  std::string render_member_value(t_field* field);
+  std::string render_member_requiredness(t_field* field);
+
+  //  std::string render_default_value(t_type* type);
+  std::string render_default_value(t_field* field);
+  std::string render_const_value(t_type* type, t_const_value* value);
+  std::string render_type_term(t_type* ttype, bool expand_structs, bool extended_info = false);
+
+  /**
+   * Struct generation code
+   */
+
+  void generate_erl_struct(t_struct* tstruct, bool is_exception);
+  void generate_erl_struct_definition(std::ostream& out, t_struct* tstruct);
+  void generate_erl_struct_member(std::ostream& out, t_field* tmember);
+  void generate_erl_struct_info(std::ostream& out, t_struct* tstruct);
+  void generate_erl_extended_struct_info(std::ostream& out, t_struct* tstruct);
+  void generate_erl_function_helpers(t_function* tfunction);
+  void generate_type_metadata(std::string function_name, vector<string> names);
+  void generate_enum_info(t_enum* tenum);
+  void generate_enum_metadata();
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_metadata(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_function_info(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string erl_autogen_comment();
+  std::string erl_imports();
+  std::string render_includes();
+  std::string type_name(t_type* ttype);
+
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string type_module(t_type* ttype);
+
+  std::string make_safe_for_module_name(std::string in) {
+    if (legacy_names_) {
+      return decapitalize(in);
+    } else {
+      return underscore(in);
+    }
+  }
+
+  std::string atomify(std::string in) {
+    if (legacy_names_) {
+      return "'" + decapitalize(in) + "'";
+    } else {
+      return "'" + in + "'";
+    }
+  }
+
+  std::string constify(std::string in) {
+    if (legacy_names_) {
+      return capitalize(in);
+    } else {
+      return uppercase(in);
+    }
+  }
+
+  static std::string comment(string in);
+
+private:
+  bool has_default_value(t_field*);
+
+  /* if true retain pre 0.9.2 naming scheme for functions, atoms and consts */
+  bool legacy_names_;
+
+  /* if true use maps instead of dicts in generated code */
+  bool maps_;
+
+  /* if true use non-namespaced dict and set instead of dict:dict and sets:set */
+  bool otp16_;
+
+  /**
+   * add function to export list
+   */
+
+  void export_function(t_function* tfunction, std::string prefix = "");
+  void export_string(std::string name, int num);
+
+  void export_types_function(t_function* tfunction, std::string prefix = "");
+  void export_types_string(std::string name, int num);
+
+  /**
+   * write out headers and footers for hrl files
+   */
+
+  void hrl_header(std::ostream& out, std::string name);
+  void hrl_footer(std::ostream& out, std::string name);
+
+  /**
+   * stuff to spit out at the top of generated files
+   */
+
+  bool export_lines_first_;
+  std::ostringstream export_lines_;
+
+  bool export_types_lines_first_;
+  std::ostringstream export_types_lines_;
+
+  /**
+   * File streams
+   */
+
+  std::ostringstream f_info_;
+  std::ostringstream f_info_ext_;
+
+  std::ofstream f_types_file_;
+  std::ofstream f_types_hrl_file_;
+
+  std::ofstream f_consts_;
+  std::ostringstream f_service_;
+  std::ofstream f_service_file_;
+  std::ofstream f_service_hrl_;
+
+  /**
+   * Metadata containers
+   */
+  std::vector<std::string> v_struct_names_;
+  std::vector<std::string> v_enum_names_;
+  std::vector<std::string> v_exception_names_;
+  std::vector<t_enum*> v_enums_;
+};
+
+/**
+ * UI for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_erl_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  // setup export lines
+  export_lines_first_ = true;
+  export_types_lines_first_ = true;
+
+  // types files
+  string f_types_name = get_out_dir() + make_safe_for_module_name(program_name_) + "_types.erl";
+  string f_types_hrl_name = get_out_dir() + make_safe_for_module_name(program_name_) + "_types.hrl";
+
+  f_types_file_.open(f_types_name.c_str());
+  f_types_hrl_file_.open(f_types_hrl_name.c_str());
+
+  hrl_header(f_types_hrl_file_, make_safe_for_module_name(program_name_) + "_types");
+
+  f_types_file_ << erl_autogen_comment() << endl << "-module("
+                << make_safe_for_module_name(program_name_) << "_types)." << endl << erl_imports()
+                << endl;
+
+  f_types_file_ << "-include(\"" << make_safe_for_module_name(program_name_) << "_types.hrl\")."
+                << endl << endl;
+
+  f_types_hrl_file_ << render_includes() << endl;
+
+  // consts file
+  string f_consts_name = get_out_dir() + make_safe_for_module_name(program_name_)
+                         + "_constants.hrl";
+  f_consts_.open(f_consts_name.c_str());
+
+  f_consts_ << erl_autogen_comment() << endl << erl_imports() << endl << "-include(\""
+            << make_safe_for_module_name(program_name_) << "_types.hrl\")." << endl << endl;
+}
+
+/**
+ * Boilerplate at beginning and end of header files
+ */
+void t_erl_generator::hrl_header(ostream& out, string name) {
+  out << "-ifndef(_" << name << "_included)." << endl << "-define(_" << name << "_included, yeah)."
+      << endl;
+}
+
+void t_erl_generator::hrl_footer(ostream& out, string name) {
+  (void)name;
+  out << "-endif." << endl;
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_erl_generator::render_includes() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  for (size_t i = 0; i < includes.size(); ++i) {
+    result += "-include(\"" + make_safe_for_module_name(includes[i]->get_name())
+              + "_types.hrl\").\n";
+  }
+  if (includes.size() > 0) {
+    result += "\n";
+  }
+  return result;
+}
+
+/**
+ * Autogen'd comment
+ */
+string t_erl_generator::erl_autogen_comment() {
+  return std::string("%%\n") + "%% Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+         + "%%\n" + "%% DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
+         + "%%\n";
+}
+
+/**
+ * Comment out text
+ */
+
+string t_erl_generator::comment(string in) {
+  size_t pos = 0;
+  in.insert(pos, "%% ");
+  while ((pos = in.find_first_of('\n', pos)) != string::npos) {
+    in.insert(++pos, "%% ");
+  }
+  return in;
+}
+
+/**
+ * Prints standard thrift imports
+ */
+string t_erl_generator::erl_imports() {
+  return "";
+}
+
+/**
+ * Closes the type files
+ */
+void t_erl_generator::close_generator() {
+
+  export_types_string("struct_info", 1);
+  export_types_string("struct_info_ext", 1);
+  export_types_string("enum_info", 1);
+  export_types_string("enum_names", 0);
+  export_types_string("struct_names", 0);
+  export_types_string("exception_names", 0);
+
+  f_types_file_ << "-export([" << export_types_lines_.str() << "])." << endl << endl;
+
+  f_types_file_ << f_info_.str();
+  f_types_file_ << "struct_info(_) -> erlang:error(function_clause)." << endl << endl;
+
+  f_types_file_ << f_info_ext_.str();
+  f_types_file_ << "struct_info_ext(_) -> erlang:error(function_clause)." << endl << endl;
+
+  generate_type_metadata("struct_names", v_struct_names_);
+  generate_enum_metadata();
+  generate_type_metadata("enum_names", v_enum_names_);
+  generate_type_metadata("exception_names", v_exception_names_);
+
+  hrl_footer(f_types_hrl_file_, string("BOGUS"));
+
+  f_types_file_.close();
+  f_types_hrl_file_.close();
+  f_consts_.close();
+}
+
+void t_erl_generator::generate_type_metadata(std::string function_name, vector<string> names) {
+  vector<string>::iterator s_iter;
+  size_t num_structs = names.size();
+
+  indent(f_types_file_) << function_name << "() ->\n";
+  indent_up();
+  indent(f_types_file_) << "[";
+
+
+  for(size_t i=0; i < num_structs; i++) {
+    f_types_file_ << names.at(i);
+
+    if (i < num_structs - 1) {
+      f_types_file_ << ", ";
+    }
+  }
+
+  f_types_file_ << "].\n\n";
+  indent_down();
+}
+
+/**
+ * Generates a typedef. no op
+ *
+ * @param ttypedef The type definition
+ */
+void t_erl_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Generates code for an enumerated type. Done using a class to scope
+ * the values.
+ *
+ * @param tenum The enumeration
+ */
+void t_erl_generator::generate_enum(t_enum* tenum) {
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+
+  v_enums_.push_back(tenum);
+  v_enum_names_.push_back(atomify(tenum->get_name()));
+
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    string name = (*c_iter)->get_name();
+    indent(f_types_hrl_file_) << "-define(" << constify(make_safe_for_module_name(program_name_))
+                              << "_" << constify(tenum->get_name()) << "_" << constify(name) << ", "
+                              << value << ")." << endl;
+  }
+
+  f_types_hrl_file_ << endl;
+}
+
+void t_erl_generator::generate_enum_info(t_enum* tenum){
+  vector<t_enum_value*> constants = tenum->get_constants();
+  size_t num_constants = constants.size();
+
+  indent(f_types_file_) << "enum_info(" << atomify(tenum->get_name()) << ") ->\n";
+  indent_up();
+  indent(f_types_file_) << "[\n";
+
+  for(size_t i=0; i < num_constants; i++) {
+    indent_up();
+    t_enum_value* value = constants.at(i);
+    indent(f_types_file_) << "{" << atomify(value->get_name()) << ", " << value->get_value() << "}";
+
+    if (i < num_constants - 1) {
+      f_types_file_ << ",\n";
+    }
+    indent_down();
+  }
+  f_types_file_ << "\n";
+  indent(f_types_file_) << "];\n\n";
+  indent_down();
+}
+
+void t_erl_generator::generate_enum_metadata() {
+  size_t enum_count = v_enums_.size();
+
+  for(size_t i=0; i < enum_count; i++) {
+    t_enum* tenum = v_enums_.at(i);
+    generate_enum_info(tenum);
+  }
+
+  indent(f_types_file_) << "enum_info(_) -> erlang:error(function_clause).\n\n";
+}
+
+/**
+ * Generate a constant value
+ */
+void t_erl_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  f_consts_ << "-define(" << constify(make_safe_for_module_name(program_name_)) << "_"
+            << constify(name) << ", " << render_const_value(type, value) << ")." << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_erl_generator::render_const_value(t_type* type, t_const_value* value) {
+  type = get_true_type(type);
+  std::ostringstream out;
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    indent(out) << value->get_integer();
+
+  } else if (type->is_struct() || type->is_xception()) {
+    out << "#" << type_name(type) << "{";
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+
+    bool first = true;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+
+      if (first) {
+        first = false;
+      } else {
+        out << ",";
+      }
+      out << v_iter->first->get_string();
+      out << " = ";
+      out << render_const_value(field_type, v_iter->second);
+    }
+    indent_down();
+    indent(out) << "}";
+
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+
+    if (maps_) {
+      out << "maps:from_list([";
+    } else {
+      out << "dict:from_list([";
+    }
+    map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
+    for (i = value->get_map().begin(); i != end;) {
+      out << "{" << render_const_value(ktype, i->first) << ","
+          << render_const_value(vtype, i->second) << "}";
+      if (++i != end) {
+        out << ",";
+      }
+    }
+    out << "])";
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    out << "sets:from_list([";
+    vector<t_const_value*>::const_iterator i, end = value->get_list().end();
+    for (i = value->get_list().begin(); i != end;) {
+      out << render_const_value(etype, *i);
+      if (++i != end) {
+        out << ",";
+      }
+    }
+    out << "])";
+  } else if (type->is_list()) {
+    t_type* etype;
+    etype = ((t_list*)type)->get_elem_type();
+    out << "[";
+
+    bool first = true;
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      if (first) {
+        first = false;
+      } else {
+        out << ",";
+      }
+      out << render_const_value(etype, *v_iter);
+    }
+    out << "]";
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+  return out.str();
+}
+
+string t_erl_generator::render_default_value(t_field* field) {
+  t_type* type = field->get_type();
+  if (type->is_struct() || type->is_xception()) {
+    return "#" + type_name(type) + "{}";
+  } else if (type->is_map()) {
+    if (maps_) {
+      return "#{}";
+    } else {
+      return "dict:new()";
+    }
+  } else if (type->is_set()) {
+    return "sets:new()";
+  } else if (type->is_list()) {
+    return "[]";
+  } else {
+    return "undefined";
+  }
+}
+
+string t_erl_generator::render_member_type(t_field* field) {
+  t_type* type = get_true_type(field->get_type());
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      return "string() | binary()";
+    case t_base_type::TYPE_BOOL:
+      return "boolean()";
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      return "integer()";
+    case t_base_type::TYPE_DOUBLE:
+      return "float()";
+    default:
+      throw "compiler error: unsupported base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    return "integer()";
+  } else if (type->is_struct() || type->is_xception()) {
+    return type_name(type) + "()";
+  } else if (type->is_map()) {
+    if (maps_) {
+      return "#{}";
+    } else if (otp16_) {
+      return "dict()";
+    } else {
+      return "dict:dict()";
+    }
+  } else if (type->is_set()) {
+    if (otp16_) {
+      return "set()";
+    } else {
+      return "sets:set()";
+    }
+  } else if (type->is_list()) {
+    return "list()";
+  } else {
+    throw "compiler error: unsupported type " + type->get_name();
+  }
+}
+
+string t_erl_generator::render_member_requiredness(t_field* field) {
+  switch (field->get_req()) {
+  case t_field::T_REQUIRED:
+    return "required";
+  case t_field::T_OPTIONAL:
+    return "optional";
+  default:
+    return "undefined";
+  }
+}
+
+/**
+ * Generates a struct
+ */
+void t_erl_generator::generate_struct(t_struct* tstruct) {
+  v_struct_names_.push_back(type_name(tstruct));
+  generate_erl_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_erl_generator::generate_xception(t_struct* txception) {
+  v_exception_names_.push_back(type_name(txception));
+  generate_erl_struct(txception, true);
+}
+
+/**
+ * Generates a struct
+ */
+void t_erl_generator::generate_erl_struct(t_struct* tstruct, bool is_exception) {
+  (void)is_exception;
+  generate_erl_struct_definition(f_types_hrl_file_, tstruct);
+  generate_erl_struct_info(f_info_, tstruct);
+  generate_erl_extended_struct_info(f_info_ext_, tstruct);
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_erl_generator::generate_erl_struct_definition(ostream& out, t_struct* tstruct) {
+  indent(out) << "%% struct " << type_name(tstruct) << endl << endl;
+
+  std::stringstream buf;
+  buf << indent() << "-record(" << type_name(tstruct) << ", {";
+  string field_indent(buf.str().size(), ' ');
+
+  const vector<t_field*>& members = tstruct->get_members();
+  for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();) {
+    generate_erl_struct_member(buf, *m_iter);
+    if (++m_iter != members.end()) {
+      buf << "," << endl << field_indent;
+    }
+  }
+  buf << "}).";
+
+  out << buf.str() << endl;
+  out << "-type " + type_name(tstruct) << "() :: #" + type_name(tstruct) + "{}." << endl << endl;
+}
+
+/**
+ * Generates the record field definition
+ */
+
+void t_erl_generator::generate_erl_struct_member(ostream& out, t_field* tmember) {
+  out << atomify(tmember->get_name());
+  if (has_default_value(tmember))
+    out << " = " << render_member_value(tmember);
+  out << " :: " << render_member_type(tmember);
+}
+
+bool t_erl_generator::has_default_value(t_field* field) {
+  t_type* type = field->get_type();
+  if (!field->get_value()) {
+    if (field->get_req() == t_field::T_REQUIRED) {
+      if (type->is_struct() || type->is_xception() || type->is_map() || type->is_set()
+          || type->is_list()) {
+        return true;
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  } else {
+    return true;
+  }
+}
+
+string t_erl_generator::render_member_value(t_field* field) {
+  if (!field->get_value()) {
+    return render_default_value(field);
+  } else {
+    return render_const_value(field->get_type(), field->get_value());
+  }
+}
+
+/**
+ * Generates the read method for a struct
+ */
+void t_erl_generator::generate_erl_struct_info(ostream& out, t_struct* tstruct) {
+  indent(out) << "struct_info(" << type_name(tstruct) << ") ->" << endl;
+  indent_up();
+  out << indent() << render_type_term(tstruct, true) << ";" << endl;
+  indent_down();
+  out << endl;
+}
+
+void t_erl_generator::generate_erl_extended_struct_info(ostream& out, t_struct* tstruct) {
+  indent(out) << "struct_info_ext(" << type_name(tstruct) << ") ->" << endl;
+  indent_up();
+  out << indent() << render_type_term(tstruct, true, true) << ";" << endl;
+  indent_down();
+  out << endl;
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_erl_generator::generate_service(t_service* tservice) {
+  service_name_ = make_safe_for_module_name(service_name_);
+
+  string f_service_hrl_name = get_out_dir() + service_name_ + "_thrift.hrl";
+  string f_service_name = get_out_dir() + service_name_ + "_thrift.erl";
+  f_service_file_.open(f_service_name.c_str());
+  f_service_hrl_.open(f_service_hrl_name.c_str());
+
+  // Reset service text aggregating stream streams
+  f_service_.str("");
+  export_lines_.str("");
+  export_lines_first_ = true;
+
+  hrl_header(f_service_hrl_, service_name_);
+
+  if (tservice->get_extends() != NULL) {
+    f_service_hrl_ << "-include(\""
+                   << make_safe_for_module_name(tservice->get_extends()->get_name())
+                   << "_thrift.hrl\"). % inherit " << endl;
+  }
+
+  f_service_hrl_ << "-include(\"" << make_safe_for_module_name(program_name_) << "_types.hrl\")."
+                 << endl << endl;
+
+  // Generate the three main parts of the service (well, two for now in PHP)
+  generate_service_helpers(tservice); // cpiro: New Erlang Order
+
+  generate_service_interface(tservice);
+
+  generate_service_metadata(tservice);
+
+  // indent_down();
+
+  f_service_file_ << erl_autogen_comment() << endl << "-module(" << service_name_ << "_thrift)."
+                  << endl << "-behaviour(thrift_service)." << endl << endl << erl_imports() << endl;
+
+  f_service_file_ << "-include(\"" << make_safe_for_module_name(tservice->get_name())
+                  << "_thrift.hrl\")." << endl << endl;
+
+  f_service_file_ << "-export([" << export_lines_.str() << "])." << endl << endl;
+
+  f_service_file_ << f_service_.str();
+
+  hrl_footer(f_service_hrl_, f_service_name);
+
+  // Close service file
+  f_service_file_.close();
+  f_service_hrl_.close();
+}
+
+void t_erl_generator::generate_service_metadata(t_service* tservice) {
+  export_string("function_names", 0);
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  size_t num_functions = functions.size();
+
+  indent(f_service_) << "function_names() -> " << endl;
+  indent_up();
+  indent(f_service_) << "[";
+
+  for (size_t i=0; i < num_functions; i++) {
+    t_function* current = functions.at(i);
+    f_service_ << atomify(current->get_name());
+    if (i < num_functions - 1) {
+      f_service_ << ", ";
+    }
+  }
+
+  f_service_ << "].\n\n";
+  indent_down();
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_erl_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  //  indent(f_service_) <<
+  //  "% HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+
+  export_string("struct_info", 1);
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_erl_function_helpers(*f_iter);
+  }
+  f_service_ << "struct_info(_) -> erlang:error(function_clause)." << endl;
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_erl_generator::generate_erl_function_helpers(t_function* tfunction) {
+  (void)tfunction;
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_erl_generator::generate_service_interface(t_service* tservice) {
+
+  export_string("function_info", 2);
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  f_service_ << "%%% interface" << endl;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "% " << function_signature(*f_iter) << endl;
+
+    generate_function_info(tservice, *f_iter);
+  }
+
+  // Inheritance - pass unknown functions to base class
+  if (tservice->get_extends() != NULL) {
+    indent(f_service_) << "function_info(Function, InfoType) ->" << endl;
+    indent_up();
+    indent(f_service_) << make_safe_for_module_name(tservice->get_extends()->get_name())
+                       << "_thrift:function_info(Function, InfoType)." << endl;
+    indent_down();
+  } else {
+    // return function_clause error for non-existent functions
+    indent(f_service_) << "function_info(_Func, _Info) -> erlang:error(function_clause)." << endl;
+  }
+
+  indent(f_service_) << endl;
+}
+
+/**
+ * Generates a function_info(FunctionName, params_type) and
+ * function_info(FunctionName, reply_type)
+ */
+void t_erl_generator::generate_function_info(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  string name_atom = atomify(tfunction->get_name());
+
+  t_struct* xs = tfunction->get_xceptions();
+  t_struct* arg_struct = tfunction->get_arglist();
+
+  // function_info(Function, params_type):
+  indent(f_service_) << "function_info(" << name_atom << ", params_type) ->" << endl;
+  indent_up();
+
+  indent(f_service_) << render_type_term(arg_struct, true) << ";" << endl;
+
+  indent_down();
+
+  // function_info(Function, reply_type):
+  indent(f_service_) << "function_info(" << name_atom << ", reply_type) ->" << endl;
+  indent_up();
+
+  if (!tfunction->get_returntype()->is_void())
+    indent(f_service_) << render_type_term(tfunction->get_returntype(), false) << ";" << endl;
+  else if (tfunction->is_oneway())
+    indent(f_service_) << "oneway_void;" << endl;
+  else
+    indent(f_service_) << "{struct, []}"
+                       << ";" << endl;
+  indent_down();
+
+  // function_info(Function, exceptions):
+  indent(f_service_) << "function_info(" << name_atom << ", exceptions) ->" << endl;
+  indent_up();
+  indent(f_service_) << render_type_term(xs, true) << ";" << endl;
+  indent_down();
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_erl_generator::function_signature(t_function* tfunction, string prefix) {
+  return prefix + tfunction->get_name() + "(This"
+         + capitalize(argument_list(tfunction->get_arglist())) + ")";
+}
+
+/**
+ * Add a function to the exports list
+ */
+void t_erl_generator::export_string(string name, int num) {
+  if (export_lines_first_) {
+    export_lines_first_ = false;
+  } else {
+    export_lines_ << ", ";
+  }
+  export_lines_ << name << "/" << num;
+}
+
+void t_erl_generator::export_types_function(t_function* tfunction, string prefix) {
+
+  export_types_string(prefix + tfunction->get_name(),
+                      1 // This
+                      + ((tfunction->get_arglist())->get_members()).size());
+}
+
+void t_erl_generator::export_types_string(string name, int num) {
+  if (export_types_lines_first_) {
+    export_types_lines_first_ = false;
+  } else {
+    export_types_lines_ << ", ";
+  }
+  export_types_lines_ << name << "/" << num;
+}
+
+void t_erl_generator::export_function(t_function* tfunction, string prefix) {
+
+  export_string(prefix + tfunction->get_name(),
+                1 // This
+                + ((tfunction->get_arglist())->get_members()).size());
+}
+
+/**
+ * Renders a field list
+ */
+string t_erl_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      result += ", "; // initial comma to compensate for initial This
+    } else {
+      result += ", ";
+    }
+    result += capitalize((*f_iter)->get_name());
+  }
+  return result;
+}
+
+string t_erl_generator::type_name(t_type* ttype) {
+  string prefix = "";
+  string erl_namespace = ttype->get_program()->get_namespace("erl");
+
+  if (erl_namespace.length() > 0) {
+    prefix = erl_namespace + ".";
+  }
+
+  string name = ttype->get_name();
+
+  if (ttype->is_struct() || ttype->is_xception() || ttype->is_service()) {
+    name = ttype->get_name();
+  }
+
+  return atomify(prefix + name);
+}
+
+/**
+ * Converts the parse type to a Erlang "type" (macro for int constants)
+ */
+string t_erl_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "?tType_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "?tType_BOOL";
+    case t_base_type::TYPE_I8:
+      return "?tType_I8";
+    case t_base_type::TYPE_I16:
+      return "?tType_I16";
+    case t_base_type::TYPE_I32:
+      return "?tType_I32";
+    case t_base_type::TYPE_I64:
+      return "?tType_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "?tType_DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "?tType_I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "?tType_STRUCT";
+  } else if (type->is_map()) {
+    return "?tType_MAP";
+  } else if (type->is_set()) {
+    return "?tType_SET";
+  } else if (type->is_list()) {
+    return "?tType_LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Generate an Erlang term which represents a thrift type
+ */
+std::string t_erl_generator::render_type_term(t_type* type,
+                                              bool expand_structs,
+                                              bool extended_info) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "string";
+    case t_base_type::TYPE_BOOL:
+      return "bool";
+    case t_base_type::TYPE_I8:
+      return "byte";
+    case t_base_type::TYPE_I16:
+      return "i16";
+    case t_base_type::TYPE_I32:
+      return "i32";
+    case t_base_type::TYPE_I64:
+      return "i64";
+    case t_base_type::TYPE_DOUBLE:
+      return "double";
+    }
+  } else if (type->is_enum()) {
+    return "i32";
+  } else if (type->is_struct() || type->is_xception()) {
+    if (expand_structs) {
+
+      std::stringstream buf;
+      buf << "{struct, [";
+      string field_indent(buf.str().size(), ' ');
+
+      t_struct::members_type const& fields = static_cast<t_struct*>(type)->get_members();
+      t_struct::members_type::const_iterator i, end = fields.end();
+      for (i = fields.begin(); i != end;) {
+        t_struct::members_type::value_type member = *i;
+        int32_t key = member->get_key();
+        string type = render_type_term(member->get_type(), false, false); // recursive call
+
+        if (!extended_info) {
+          // Convert to format: {struct, [{Fid, Type}|...]}
+          buf << "{" << key << ", " << type << "}";
+        } else {
+          // Convert to format: {struct, [{Fid, Req, Type, Name, Def}|...]}
+          string name = member->get_name();
+          string value = render_member_value(member);
+          string requiredness = render_member_requiredness(member);
+          buf << "{" << key << ", " << requiredness << ", " << type << ", " << atomify(name) << ", "
+              << value << "}";
+        }
+
+        if (++i != end) {
+          buf << "," << endl << field_indent;
+        }
+      }
+
+      buf << "]}" << endl;
+      return buf.str();
+    } else {
+      return "{struct, {" + atomify(type_module(type)) + ", " + type_name(type) + "}}";
+    }
+  } else if (type->is_map()) {
+    // {map, KeyType, ValType}
+    t_type* key_type = ((t_map*)type)->get_key_type();
+    t_type* val_type = ((t_map*)type)->get_val_type();
+
+    return "{map, " + render_type_term(key_type, false) + ", " + render_type_term(val_type, false)
+           + "}";
+
+  } else if (type->is_set()) {
+    t_type* elem_type = ((t_set*)type)->get_elem_type();
+
+    return "{set, " + render_type_term(elem_type, false) + "}";
+
+  } else if (type->is_list()) {
+    t_type* elem_type = ((t_list*)type)->get_elem_type();
+
+    return "{list, " + render_type_term(elem_type, false) + "}";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+std::string t_erl_generator::type_module(t_type* ttype) {
+  return make_safe_for_module_name(ttype->get_program()->get_name()) + "_types";
+}
+
+THRIFT_REGISTER_GENERATOR(
+    erl,
+    "Erlang",
+    "    legacynames: Output files retain naming conventions of Thrift 0.9.1 and earlier.\n"
+    "    maps:        Generate maps instead of dicts.\n"
+    "    otp16:       Generate non-namespaced dict and set instead of dict:dict and sets:set.\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_generator.cc b/compiler/cpp/src/thrift/generate/t_generator.cc
new file mode 100644
index 0000000..0c1f49d
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_generator.cc
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include "thrift/generate/t_generator.h"
+using namespace std;
+
+/**
+ * Top level program generation function. Calls the generator subclass methods
+ * for preparing file streams etc. then iterates over all the parts of the
+ * program to perform the correct actions.
+ *
+ * @param program The thrift program to compile into C++ source
+ */
+void t_generator::generate_program() {
+  // Initialize the generator
+  init_generator();
+
+  // Generate enums
+  vector<t_enum*> enums = program_->get_enums();
+  vector<t_enum*>::iterator en_iter;
+  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
+    generate_enum(*en_iter);
+  }
+
+  // Generate typedefs
+  vector<t_typedef*> typedefs = program_->get_typedefs();
+  vector<t_typedef*>::iterator td_iter;
+  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
+    generate_typedef(*td_iter);
+  }
+
+  // Generate structs, exceptions, and unions in declared order
+  vector<t_struct*> objects = program_->get_objects();
+
+  vector<t_struct*>::iterator o_iter;
+  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
+    generate_forward_declaration(*o_iter);
+  }
+  for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
+    if ((*o_iter)->is_xception()) {
+      generate_xception(*o_iter);
+    } else {
+      generate_struct(*o_iter);
+    }
+  }
+
+  // Generate constants
+  vector<t_const*> consts = program_->get_consts();
+  generate_consts(consts);
+
+  // Generate services
+  vector<t_service*> services = program_->get_services();
+  vector<t_service*>::iterator sv_iter;
+  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+    service_name_ = get_service_name(*sv_iter);
+    generate_service(*sv_iter);
+  }
+
+  // Close the generator
+  close_generator();
+}
+
+string t_generator::escape_string(const string& in) const {
+  string result = "";
+  for (string::const_iterator it = in.begin(); it < in.end(); it++) {
+    std::map<char, std::string>::const_iterator res = escape_.find(*it);
+    if (res != escape_.end()) {
+      result.append(res->second);
+    } else {
+      result.push_back(*it);
+    }
+  }
+  return result;
+}
+
+void t_generator::generate_consts(vector<t_const*> consts) {
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    generate_const(*c_iter);
+  }
+}
+
+void t_generator::generate_docstring_comment(ostream& out,
+                                             const string& comment_start,
+                                             const string& line_prefix,
+                                             const string& contents,
+                                             const string& comment_end) {
+  if (comment_start != "")
+    indent(out) << comment_start;
+  stringstream docs(contents, ios_base::in);
+  while (!(docs.eof() || docs.fail())) {
+    char line[1024];
+    docs.getline(line, 1024);
+
+    // Just prnt a newline when the line & prefix are empty.
+    if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) {
+      out << std::endl;
+    } else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line
+      indent(out) << line_prefix << line << std::endl;
+    }
+  }
+  if (comment_end != "")
+    indent(out) << comment_end;
+}
+
+void t_generator_registry::register_generator(t_generator_factory* factory) {
+  gen_map_t& the_map = get_generator_map();
+  if (the_map.find(factory->get_short_name()) != the_map.end()) {
+    failure("Duplicate generators for language \"%s\"!\n", factory->get_short_name().c_str());
+  }
+  the_map[factory->get_short_name()] = factory;
+}
+
+void t_generator::parse_options(const string& options,
+                                string& language,
+                                map<string, string>& parsed_options) {
+  string::size_type colon = options.find(':');
+  language = options.substr(0, colon);
+
+  if (colon != string::npos) {
+    string::size_type pos = colon + 1;
+    while (pos != string::npos && pos < options.size()) {
+      string::size_type next_pos = options.find(',', pos);
+      string option = options.substr(pos, next_pos - pos);
+      pos = ((next_pos == string::npos) ? next_pos : next_pos + 1);
+
+      string::size_type separator = option.find('=');
+      string key, value;
+      if (separator == string::npos) {
+        key = option;
+        value = "";
+      } else {
+        key = option.substr(0, separator);
+        value = option.substr(separator + 1);
+      }
+
+      parsed_options[key] = value;
+    }
+  }
+}
+
+t_generator* t_generator_registry::get_generator(t_program* program,
+                                                 const string& language,
+                                                 const map<string, string>& parsed_options,
+                                                 const std::string& options) {
+  gen_map_t& the_map = get_generator_map();
+  gen_map_t::iterator iter = the_map.find(language);
+
+  if (iter == the_map.end()) {
+    return NULL;
+  }
+
+  return iter->second->get_generator(program, parsed_options, options);
+}
+
+t_generator* t_generator_registry::get_generator(t_program* program, const string& options) {
+  string language;
+  map<string, string> parsed_options;
+  t_generator::parse_options(options, language, parsed_options);
+  return get_generator(program, language, parsed_options, options);
+}
+
+t_generator_registry::gen_map_t& t_generator_registry::get_generator_map() {
+  // http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
+  static gen_map_t* the_map = new gen_map_t();
+  return *the_map;
+}
+
+t_generator_factory::t_generator_factory(const std::string& short_name,
+                                         const std::string& long_name,
+                                         const std::string& documentation)
+  : short_name_(short_name), long_name_(long_name), documentation_(documentation) {
+  t_generator_registry::register_generator(this);
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_generator.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_generator.h b/compiler/cpp/src/thrift/generate/t_generator.h
new file mode 100644
index 0000000..051bbc4
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_generator.h
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef T_GENERATOR_H
+#define T_GENERATOR_H
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include "thrift/common.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_generator_registry.h"
+#include "thrift/parse/t_program.h"
+
+/**
+ * Base class for a thrift code generator. This class defines the basic
+ * routines for code generation and contains the top level method that
+ * dispatches code generation across various components.
+ *
+ */
+class t_generator {
+public:
+  t_generator(t_program* program) {
+    tmp_ = 0;
+    indent_ = 0;
+    program_ = program;
+    program_name_ = get_program_name(program);
+    escape_['\n'] = "\\n";
+    escape_['\r'] = "\\r";
+    escape_['\t'] = "\\t";
+    escape_['"'] = "\\\"";
+    escape_['\\'] = "\\\\";
+  }
+
+  virtual ~t_generator() {}
+
+  /**
+   * Framework generator method that iterates over all the parts of a program
+   * and performs general actions. This is implemented by the base class and
+   * should not normally be overwritten in the subclasses.
+   */
+  virtual void generate_program();
+
+  const t_program* get_program() const { return program_; }
+
+  void generate_docstring_comment(std::ostream& out,
+                                  const std::string& comment_start,
+                                  const std::string& line_prefix,
+                                  const std::string& contents,
+                                  const std::string& comment_end);
+
+  static void parse_options(const std::string& options, std::string& language,
+                     std::map<std::string, std::string>& parsed_options);
+
+  /**
+   * check whether sub-namespace declaraction is used by generator.
+   * e.g. allow
+   * namespace py.twisted bar
+   * to specify namespace to use when -gen py:twisted is specified.
+   * Will be called with subnamespace, i.e. is_valid_namespace("twisted")
+   * will be called for the above example.
+   */
+  static bool is_valid_namespace(const std::string& sub_namespace) {
+    (void)sub_namespace;
+    return false;
+  }
+
+  /**
+   * Escape string to use one in generated sources.
+   */
+  virtual std::string escape_string(const std::string& in) const;
+
+  std::string get_escaped_string(t_const_value* constval) {
+    return escape_string(constval->get_string());
+  }
+
+protected:
+  /**
+   * Optional methods that may be imlemented by subclasses to take necessary
+   * steps at the beginning or end of code generation.
+   */
+
+  virtual void init_generator() {}
+  virtual void close_generator() {}
+
+  virtual void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Pure virtual methods implemented by the generator subclasses.
+   */
+
+  virtual void generate_typedef(t_typedef* ttypedef) = 0;
+  virtual void generate_enum(t_enum* tenum) = 0;
+  virtual void generate_const(t_const* tconst) { (void)tconst; }
+  virtual void generate_struct(t_struct* tstruct) = 0;
+  virtual void generate_service(t_service* tservice) = 0;
+  virtual void generate_forward_declaration(t_struct*) {}
+  virtual void generate_xception(t_struct* txception) {
+    // By default exceptions are the same as structs
+    generate_struct(txception);
+  }
+
+  /**
+   * Method to get the program name, may be overridden
+   */
+  virtual std::string get_program_name(t_program* tprogram) { return tprogram->get_name(); }
+
+  /**
+   * Method to get the service name, may be overridden
+   */
+  virtual std::string get_service_name(t_service* tservice) { return tservice->get_name(); }
+
+  /**
+   * Get the current output directory
+   */
+  virtual std::string get_out_dir() const {
+    if (program_->is_out_path_absolute()) {
+      return program_->get_out_path() + "/";
+    }
+
+    return program_->get_out_path() + out_dir_base_ + "/";
+  }
+
+  /**
+   * Creates a unique temporary variable name, which is just "name" with a
+   * number appended to it (i.e. name35)
+   */
+  std::string tmp(std::string name) {
+    std::ostringstream out;
+    out << name << tmp_++;
+    return out.str();
+  }
+
+  /**
+   * Generates a comment about this code being autogenerated, using C++ style
+   * comments, which are also fair game in Java / PHP, yay!
+   *
+   * @return C-style comment mentioning that this file is autogenerated.
+   */
+  virtual std::string autogen_comment() {
+    return std::string("/**\n") + " * " + autogen_summary() + "\n" + " *\n"
+           + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
+           + " *  @generated\n" + " */\n";
+  }
+
+  virtual std::string autogen_summary() {
+    return std::string("Autogenerated by Thrift Compiler (") + THRIFT_VERSION + ")";
+  }
+
+  /**
+   * Indentation level modifiers
+   */
+
+  void indent_up() { ++indent_; }
+
+  void indent_down() { --indent_; }
+
+  /**
+   * Indentation print function
+   */
+  std::string indent() {
+    std::string ind = "";
+    int i;
+    for (i = 0; i < indent_; ++i) {
+      ind += indent_str();
+    }
+    return ind;
+  }
+
+  /**
+   * Indentation utility wrapper
+   */
+  std::ostream& indent(std::ostream& os) { return os << indent(); }
+
+  /**
+   * Capitalization helpers
+   */
+  std::string capitalize(std::string in) {
+    in[0] = toupper(in[0]);
+    return in;
+  }
+  std::string decapitalize(std::string in) {
+    in[0] = tolower(in[0]);
+    return in;
+  }
+  static std::string lowercase(std::string in) {
+    for (size_t i = 0; i < in.size(); ++i) {
+      in[i] = tolower(in[i]);
+    }
+    return in;
+  }
+  static std::string uppercase(std::string in) {
+    for (size_t i = 0; i < in.size(); ++i) {
+      in[i] = toupper(in[i]);
+    }
+    return in;
+  }
+  /**
+   * Transforms a camel case string to an equivalent one separated by underscores
+   * e.g. aMultiWord -> a_multi_word
+   *      someName   -> some_name
+   *      CamelCase  -> camel_case
+   *      name       -> name
+   *      Name       -> name
+   */
+  std::string underscore(std::string in) {
+    in[0] = tolower(in[0]);
+    for (size_t i = 1; i < in.size(); ++i) {
+      if (isupper(in[i])) {
+        in[i] = tolower(in[i]);
+        in.insert(i, "_");
+      }
+    }
+    return in;
+  }
+  /**
+    * Transforms a string with words separated by underscores to a camel case equivalent
+    * e.g. a_multi_word -> aMultiWord
+    *      some_name    ->  someName
+    *      name         ->  name
+    */
+  std::string camelcase(std::string in) {
+    std::ostringstream out;
+    bool underscore = false;
+
+    for (size_t i = 0; i < in.size(); i++) {
+      if (in[i] == '_') {
+        underscore = true;
+        continue;
+      }
+      if (underscore) {
+        out << (char)toupper(in[i]);
+        underscore = false;
+        continue;
+      }
+      out << in[i];
+    }
+
+    return out.str();
+  }
+
+public:
+  /**
+   * Get the true type behind a series of typedefs.
+   */
+  static const t_type* get_true_type(const t_type* type) { return type->get_true_type(); }
+  static t_type* get_true_type(t_type* type) { return type->get_true_type(); }
+
+protected:
+  /**
+   * The program being generated
+   */
+  t_program* program_;
+
+  /**
+   * Quick accessor for formatted program name that is currently being
+   * generated.
+   */
+  std::string program_name_;
+
+  /**
+   * Quick accessor for formatted service name that is currently being
+   * generated.
+   */
+  std::string service_name_;
+
+  /**
+   * Output type-specifc directory name ("gen-*")
+   */
+  std::string out_dir_base_;
+
+  /**
+   * Map of characters to escape in string literals.
+   */
+  std::map<char, std::string> escape_;
+
+  virtual std::string indent_str() const {
+    return "  ";
+  }
+
+private:
+  /**
+   * Current code indentation level
+   */
+  int indent_;
+
+  /**
+   * Temporary variable counter, for making unique variable names
+   */
+  int tmp_;
+};
+
+#endif

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_generator_registry.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_generator_registry.h b/compiler/cpp/src/thrift/generate/t_generator_registry.h
new file mode 100644
index 0000000..1f02167
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_generator_registry.h
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef T_GENERATOR_REGISTRY_H
+#define T_GENERATOR_REGISTRY_H
+
+class t_generator;
+
+/**
+ * A factory for producing generator classes of a particular language.
+ *
+ * This class is also responsible for:
+ *  - Registering itself with the generator registry.
+ *  - Providing documentation for the generators it produces.
+ */
+class t_generator_factory {
+public:
+  t_generator_factory(const std::string& short_name,
+                      const std::string& long_name,
+                      const std::string& documentation);
+
+  virtual ~t_generator_factory() {}
+
+  virtual t_generator* get_generator(
+      // The program to generate.
+      t_program* program,
+      // Note: parsed_options will not exist beyond the call to get_generator.
+      const std::map<std::string, std::string>& parsed_options,
+      // Note: option_string might not exist beyond the call to get_generator.
+      const std::string& option_string) = 0;
+
+  virtual bool is_valid_namespace(const std::string& sub_namespace) = 0;
+
+  std::string get_short_name() { return short_name_; }
+  std::string get_long_name() { return long_name_; }
+  std::string get_documentation() { return documentation_; }
+
+private:
+  std::string short_name_;
+  std::string long_name_;
+  std::string documentation_;
+};
+
+template <typename generator>
+class t_generator_factory_impl : public t_generator_factory {
+public:
+  t_generator_factory_impl(const std::string& short_name,
+                           const std::string& long_name,
+                           const std::string& documentation)
+    : t_generator_factory(short_name, long_name, documentation) {}
+
+  virtual t_generator* get_generator(t_program* program,
+                                     const std::map<std::string, std::string>& parsed_options,
+                                     const std::string& option_string) {
+    return new generator(program, parsed_options, option_string);
+  }
+
+  virtual bool is_valid_namespace(const std::string& sub_namespace) {
+    return generator::is_valid_namespace(sub_namespace);
+  }
+};
+
+class t_generator_registry {
+public:
+  static void register_generator(t_generator_factory* factory);
+
+  static t_generator* get_generator(t_program* program, const std::string& options);
+  static t_generator* get_generator(t_program* program,
+                                    const std::string& laugnage,
+                                    const std::map<std::string, std::string>& parsed_options,
+                                    const std::string& options);
+
+  typedef std::map<std::string, t_generator_factory*> gen_map_t;
+  static gen_map_t& get_generator_map();
+
+private:
+  t_generator_registry();
+  t_generator_registry(const t_generator_registry&);
+};
+
+#define THRIFT_REGISTER_GENERATOR(language, long_name, doc)                                        \
+  class t_##language##_generator_factory_impl                                                      \
+      : public t_generator_factory_impl<t_##language##_generator> {                                \
+  public:                                                                                          \
+    t_##language##_generator_factory_impl()                                                        \
+      : t_generator_factory_impl<t_##language##_generator>(#language, long_name, doc) {}           \
+  };                                                                                               \
+  static t_##language##_generator_factory_impl _registerer;
+
+#endif


[32/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_ocaml_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_ocaml_generator.cc b/compiler/cpp/src/generate/t_ocaml_generator.cc
deleted file mode 100644
index fc82ebc..0000000
--- a/compiler/cpp/src/generate/t_ocaml_generator.cc
+++ /dev/null
@@ -1,1762 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sstream>
-#include "t_oop_generator.h"
-#include "platform.h"
-#include "version.h"
-
-using std::ios;
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/**
- * OCaml code generator.
- *
- */
-class t_ocaml_generator : public t_oop_generator {
-public:
-  t_ocaml_generator(t_program* program,
-                    const std::map<std::string, std::string>& parsed_options,
-                    const std::string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option ocaml:" + iter->first; 
-    }
-
-    out_dir_base_ = "gen-ocaml";
-  }
-
-  /**
-   * Init and close methods
-   */
-
-  void init_generator();
-  void close_generator();
-
-  /**
-   * Program-level generation functions
-   */
-  void generate_program();
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_const(t_const* tconst);
-  void generate_struct(t_struct* tstruct);
-  void generate_xception(t_struct* txception);
-  void generate_service(t_service* tservice);
-
-  std::string render_const_value(t_type* type, t_const_value* value);
-  bool struct_member_persistent(t_field* tmember);
-  bool struct_member_omitable(t_field* tmember);
-  bool struct_member_default_cheaply_comparable(t_field* tmember);
-  std::string struct_member_copy_of(t_type* type, string what);
-
-  /**
-   * Struct generation code
-   */
-
-  void generate_ocaml_struct(t_struct* tstruct, bool is_exception);
-  void generate_ocaml_struct_definition(std::ofstream& out,
-                                        t_struct* tstruct,
-                                        bool is_xception = false);
-  void generate_ocaml_struct_member(std::ofstream& out, string tname, t_field* tmember);
-  void generate_ocaml_struct_sig(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_ocaml_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_ocaml_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_ocaml_function_helpers(t_function* tfunction);
-  void generate_ocaml_method_copy(std::ofstream& out, const vector<t_field*>& members);
-  void generate_ocaml_member_copy(std::ofstream& out, t_field* member);
-
-  /**
-   * Service-level generation functions
-   */
-
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_interface(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_process_function(t_service* tservice, t_function* tfunction);
-
-  /**
-   * Serialization constructs
-   */
-
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix);
-
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct);
-
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype);
-
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset);
-
-  void generate_deserialize_list_element(std::ofstream& out,
-                                         t_list* tlist,
-                                         std::string prefix = "");
-  void generate_deserialize_type(std::ofstream& out, t_type* type);
-
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string name = "");
-
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-
-  void generate_serialize_map_element(std::ofstream& out,
-                                      t_map* tmap,
-                                      std::string kiter,
-                                      std::string viter);
-
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-
-  /**
-   * Helper rendering functions
-   */
-
-  std::string ocaml_autogen_comment();
-  std::string ocaml_imports();
-  std::string type_name(t_type* ttype);
-  std::string function_signature(t_function* tfunction, std::string prefix = "");
-  std::string function_type(t_function* tfunc, bool method = false, bool options = false);
-  std::string argument_list(t_struct* tstruct);
-  std::string type_to_enum(t_type* ttype);
-  std::string render_ocaml_type(t_type* type);
-
-private:
-  /**
-   * File streams
-   */
-
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_service_;
-
-  std::ofstream f_types_i_;
-  std::ofstream f_service_i_;
-};
-
-/*
- * This is necessary because we want typedefs to appear later,
- * after all the types have been declared.
- */
-void t_ocaml_generator::generate_program() {
-  // Initialize the generator
-  init_generator();
-
-  // Generate enums
-  vector<t_enum*> enums = program_->get_enums();
-  vector<t_enum*>::iterator en_iter;
-  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
-    generate_enum(*en_iter);
-  }
-
-  // Generate structs
-  vector<t_struct*> structs = program_->get_structs();
-  vector<t_struct*>::iterator st_iter;
-  for (st_iter = structs.begin(); st_iter != structs.end(); ++st_iter) {
-    generate_struct(*st_iter);
-  }
-
-  // Generate xceptions
-  vector<t_struct*> xceptions = program_->get_xceptions();
-  vector<t_struct*>::iterator x_iter;
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-    generate_xception(*x_iter);
-  }
-
-  // Generate typedefs
-  vector<t_typedef*> typedefs = program_->get_typedefs();
-  vector<t_typedef*>::iterator td_iter;
-  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
-    generate_typedef(*td_iter);
-  }
-
-  // Generate services
-  vector<t_service*> services = program_->get_services();
-  vector<t_service*>::iterator sv_iter;
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    service_name_ = get_service_name(*sv_iter);
-    generate_service(*sv_iter);
-  }
-
-  // Generate constants
-  vector<t_const*> consts = program_->get_consts();
-  generate_consts(consts);
-
-  // Close the generator
-  close_generator();
-}
-
-/**
- * Prepares for file generation by opening up the necessary file output
- * streams.
- *
- * @param tprogram The program to generate
- */
-void t_ocaml_generator::init_generator() {
-  // Make output directory
-  MKDIR(get_out_dir().c_str());
-
-  // Make output file
-  string f_types_name = get_out_dir() + program_name_ + "_types.ml";
-  f_types_.open(f_types_name.c_str());
-  string f_types_i_name = get_out_dir() + program_name_ + "_types.mli";
-  f_types_i_.open(f_types_i_name.c_str());
-
-  string f_consts_name = get_out_dir() + program_name_ + "_consts.ml";
-  f_consts_.open(f_consts_name.c_str());
-
-  // Print header
-  f_types_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
-  f_types_i_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
-  f_consts_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl << "open "
-            << capitalize(program_name_) << "_types" << endl;
-}
-
-/**
- * Autogen'd comment
- */
-string t_ocaml_generator::ocaml_autogen_comment() {
-  return std::string("(*\n") + " Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "\n"
-         + " DO NOT EDIT UNLESS YOU ARE SURE YOU KNOW WHAT YOU ARE DOING\n" + "*)\n";
-}
-
-/**
- * Prints standard thrift imports
- */
-string t_ocaml_generator::ocaml_imports() {
-  return "open Thrift";
-}
-
-/**
- * Closes the type files
- */
-void t_ocaml_generator::close_generator() {
-  // Close types file
-  f_types_.close();
-}
-
-/**
- * Generates a typedef. Ez.
- *
- * @param ttypedef The type definition
- */
-void t_ocaml_generator::generate_typedef(t_typedef* ttypedef) {
-  f_types_ << indent() << "type " << decapitalize(ttypedef->get_symbolic()) << " = "
-           << render_ocaml_type(ttypedef->get_type()) << endl << endl;
-  f_types_i_ << indent() << "type " << decapitalize(ttypedef->get_symbolic()) << " = "
-             << render_ocaml_type(ttypedef->get_type()) << endl << endl;
-}
-
-/**
- * Generates code for an enumerated type.
- * the values.
- *
- * @param tenum The enumeration
- */
-void t_ocaml_generator::generate_enum(t_enum* tenum) {
-  indent(f_types_) << "module " << capitalize(tenum->get_name()) << " = " << endl << "struct"
-                   << endl;
-  indent(f_types_i_) << "module " << capitalize(tenum->get_name()) << " : " << endl << "sig"
-                     << endl;
-  indent_up();
-  indent(f_types_) << "type t = " << endl;
-  indent(f_types_i_) << "type t = " << endl;
-  indent_up();
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    string name = capitalize((*c_iter)->get_name());
-    indent(f_types_) << "| " << name << endl;
-    indent(f_types_i_) << "| " << name << endl;
-  }
-  indent_down();
-
-  indent(f_types_) << "let to_i = function" << endl;
-  indent(f_types_i_) << "val to_i : t -> Int32.t" << endl;
-  indent_up();
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    string name = capitalize((*c_iter)->get_name());
-    indent(f_types_) << "| " << name << " -> " << value << "l" << endl;
-  }
-  indent_down();
-
-  indent(f_types_) << "let of_i = function" << endl;
-  indent(f_types_i_) << "val of_i : Int32.t -> t" << endl;
-  indent_up();
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    string name = capitalize((*c_iter)->get_name());
-    indent(f_types_) << "| " << value << "l -> " << name << endl;
-  }
-  indent(f_types_) << "| _ -> raise Thrift_error" << endl;
-  indent_down();
-  indent_down();
-  indent(f_types_) << "end" << endl;
-  indent(f_types_i_) << "end" << endl;
-}
-
-/**
- * Generate a constant value
- */
-void t_ocaml_generator::generate_const(t_const* tconst) {
-  t_type* type = tconst->get_type();
-  string name = decapitalize(tconst->get_name());
-  t_const_value* value = tconst->get_value();
-
-  indent(f_consts_) << "let " << name << " = " << render_const_value(type, value) << endl << endl;
-}
-
-/**
- * Prints the value of a constant with the given type. Note that type checking
- * is NOT performed in this function as it is always run beforehand using the
- * validate_types method in main.cc
- */
-string t_ocaml_generator::render_const_value(t_type* type, t_const_value* value) {
-  type = get_true_type(type);
-  std::ostringstream out;
-  // OCaml requires all floating point numbers contain a decimal point
-  out.setf(ios::showpoint);
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      out << '"' << get_escaped_string(value) << '"';
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-      out << value->get_integer();
-      break;
-    case t_base_type::TYPE_I32:
-      out << value->get_integer() << "l";
-      break;
-    case t_base_type::TYPE_I64:
-      out << value->get_integer() << "L";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer() << ".0";
-      } else {
-        out << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    t_enum* tenum = (t_enum*)type;
-    vector<t_enum_value*> constants = tenum->get_constants();
-    vector<t_enum_value*>::iterator c_iter;
-    for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-      int val = (*c_iter)->get_value();
-      if (val == value->get_integer()) {
-        indent(out) << capitalize(tenum->get_name()) << "." << capitalize((*c_iter)->get_name());
-        break;
-      }
-    }
-  } else if (type->is_struct() || type->is_xception()) {
-    string cname = type_name(type);
-    string ct = tmp("_c");
-    out << endl;
-    indent_up();
-    indent(out) << "(let " << ct << " = new " << cname << " in" << endl;
-    indent_up();
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
-      }
-      string fname = v_iter->first->get_string();
-      out << indent();
-      out << ct << "#set_" << fname << " ";
-      out << render_const_value(field_type, v_iter->second);
-      out << ";" << endl;
-    }
-    indent(out) << ct << ")";
-    indent_down();
-    indent_down();
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    string hm = tmp("_hm");
-    out << endl;
-    indent_up();
-    indent(out) << "(let " << hm << " = Hashtbl.create " << val.size() << " in" << endl;
-    indent_up();
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(ktype, v_iter->first);
-      string val = render_const_value(vtype, v_iter->second);
-      indent(out) << "Hashtbl.add " << hm << " " << key << " " << val << ";" << endl;
-    }
-    indent(out) << hm << ")";
-    indent_down();
-    indent_down();
-  } else if (type->is_list()) {
-    t_type* etype;
-    etype = ((t_list*)type)->get_elem_type();
-    out << "[" << endl;
-    indent_up();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      out << indent();
-      out << render_const_value(etype, *v_iter);
-      out << ";" << endl;
-    }
-    indent_down();
-    indent(out) << "]";
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    string hm = tmp("_hm");
-    indent(out) << "(let " << hm << " = Hashtbl.create " << val.size() << " in" << endl;
-    indent_up();
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(etype, *v_iter);
-      indent(out) << "Hashtbl.add " << hm << " " << val << " true;" << endl;
-    }
-    indent(out) << hm << ")" << endl;
-    indent_down();
-    out << endl;
-  } else {
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
-  }
-  return out.str();
-}
-
-/**
- * Generates a "struct"
- */
-void t_ocaml_generator::generate_struct(t_struct* tstruct) {
-  generate_ocaml_struct(tstruct, false);
-}
-
-/**
- * Generates a struct definition for a thrift exception. Basically the same
- * as a struct, but also has an exception declaration.
- *
- * @param txception The struct definition
- */
-void t_ocaml_generator::generate_xception(t_struct* txception) {
-  generate_ocaml_struct(txception, true);
-}
-
-/**
- * Generates an OCaml struct
- */
-void t_ocaml_generator::generate_ocaml_struct(t_struct* tstruct, bool is_exception) {
-  generate_ocaml_struct_definition(f_types_, tstruct, is_exception);
-  generate_ocaml_struct_sig(f_types_i_, tstruct, is_exception);
-}
-
-void t_ocaml_generator::generate_ocaml_method_copy(ofstream& out, const vector<t_field*>& members) {
-  vector<t_field*>::const_iterator m_iter;
-
-  /* Create a copy of the current object */
-  indent(out) << "method copy =" << endl;
-  indent_up();
-  indent_up();
-  indent(out) << "let _new = Oo.copy self in" << endl;
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
-    generate_ocaml_member_copy(out, *m_iter);
-
-  indent_down();
-  indent(out) << "_new" << endl;
-  indent_down();
-}
-
-string t_ocaml_generator::struct_member_copy_of(t_type* type, string what) {
-  if (type->is_struct() || type->is_xception()) {
-    return what + string("#copy");
-  }
-  if (type->is_map()) {
-    string copy_of_k = struct_member_copy_of(((t_map*)type)->get_key_type(), "k");
-    string copy_of_v = struct_member_copy_of(((t_map*)type)->get_val_type(), "v");
-
-    if (copy_of_k == "k" && copy_of_v == "v") {
-      return string("(Hashtbl.copy ") + what + string(")");
-    } else {
-      return string(
-                 "((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v "
-                 "-> Hashtbl.add nh ") + copy_of_k + string(" ") + copy_of_v + string(") oh; nh) ")
-             + what + ")";
-    }
-  }
-  if (type->is_set()) {
-    string copy_of = struct_member_copy_of(((t_set*)type)->get_elem_type(), "k");
-
-    if (copy_of == "k") {
-      return string("(Hashtbl.copy ") + what + string(")");
-    } else {
-      return string(
-                 "((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v "
-                 "-> Hashtbl.add nh ") + copy_of + string(" true") + string(") oh; nh) ") + what
-             + ")";
-    }
-  }
-  if (type->is_list()) {
-    string copy_of = struct_member_copy_of(((t_list*)type)->get_elem_type(), "x");
-    if (copy_of != "x") {
-      return string("(List.map (fun x -> ") + copy_of + string(") ") + what + string(")");
-    } else {
-      return what;
-    }
-  }
-  return what;
-}
-
-void t_ocaml_generator::generate_ocaml_member_copy(ofstream& out, t_field* tmember) {
-  string mname = decapitalize(tmember->get_name());
-  t_type* type = get_true_type(tmember->get_type());
-
-  string grab_field = string("self#grab_") + mname;
-  string copy_of = struct_member_copy_of(type, grab_field);
-  if (copy_of != grab_field) {
-    indent(out);
-    if (!struct_member_persistent(tmember)) {
-      out << "if _" << mname << " <> None then" << endl;
-      indent(out) << "  ";
-    }
-    out << "_new#set_" << mname << " " << copy_of << ";" << endl;
-  }
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_ocaml_generator::generate_ocaml_struct_definition(ofstream& out,
-                                                         t_struct* tstruct,
-                                                         bool is_exception) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  string tname = type_name(tstruct);
-  indent(out) << "class " << tname << " =" << endl;
-  indent(out) << "object (self)" << endl;
-
-  indent_up();
-
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      generate_ocaml_struct_member(out, tname, (*m_iter));
-      out << endl;
-    }
-  }
-  generate_ocaml_method_copy(out, members);
-  generate_ocaml_struct_writer(out, tstruct);
-  indent_down();
-  indent(out) << "end" << endl;
-
-  if (is_exception) {
-    indent(out) << "exception " << capitalize(tname) << " of " << tname << endl;
-  }
-
-  generate_ocaml_struct_reader(out, tstruct);
-}
-
-/**
- * Generates a structure member for a thrift data type.
- *
- * @param tname Name of the parent structure for the member
- * @param tmember Member definition
- */
-void t_ocaml_generator::generate_ocaml_struct_member(ofstream& out,
-                                                     string tname,
-                                                     t_field* tmember) {
-  string x = tmp("_x");
-  string mname = decapitalize(tmember->get_name());
-
-  indent(out) << "val mutable _" << mname << " : " << render_ocaml_type(tmember->get_type());
-  t_const_value* val = tmember->get_value();
-  if (val) {
-    if (struct_member_persistent(tmember))
-      out << " = " << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
-    else
-      out << " option = Some " << render_const_value(tmember->get_type(), tmember->get_value())
-          << endl;
-  } else {
-    // assert(!struct_member_persistent(tmember))
-    out << " option = None" << endl;
-  }
-
-  if (struct_member_persistent(tmember)) {
-    indent(out) << "method get_" << mname << " = Some _" << mname << endl;
-    indent(out) << "method grab_" << mname << " = _" << mname << endl;
-    indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- " << x << endl;
-  } else {
-    indent(out) << "method get_" << mname << " = _" << mname << endl;
-    indent(out) << "method grab_" << mname << " = match _" << mname
-                << " with None->raise (Field_empty \"" << tname << "." << mname << "\") | Some "
-                << x << " -> " << x << endl;
-    indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- Some " << x
-                << endl;
-    indent(out) << "method unset_" << mname << " = _" << mname << " <- None" << endl;
-  }
-
-  indent(out) << "method reset_" << mname << " = _" << mname << " <- ";
-  if (val) {
-    if (struct_member_persistent(tmember))
-      out << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
-    else
-      out << "Some " << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
-  } else {
-    out << "None" << endl;
-  }
-}
-
-/**
- * Check whether a member of the structure can not have undefined value
- *
- * @param tmember Member definition
- */
-bool t_ocaml_generator::struct_member_persistent(t_field* tmember) {
-  t_const_value* val = tmember->get_value();
-  return (val ? true : false);
-}
-
-/**
- * Check whether a member of the structure can be skipped during encoding
- *
- * @param tmember Member definition
- */
-bool t_ocaml_generator::struct_member_omitable(t_field* tmember) {
-  return (tmember->get_req() != t_field::T_REQUIRED);
-}
-
-/**
- * Figure out whether a member of the structure has
- * a cheaply comparable default value.
- *
- * @param tmember Member definition
- */
-bool t_ocaml_generator::struct_member_default_cheaply_comparable(t_field* tmember) {
-  t_type* type = get_true_type(tmember->get_type());
-  t_const_value* val = tmember->get_value();
-  if (!val) {
-    return false;
-  } else if (type->is_base_type()) {
-    // Base types are generally cheaply compared for structural equivalence.
-    switch (((t_base_type*)type)->get_base()) {
-    case t_base_type::TYPE_DOUBLE:
-      if (val->get_double() == 0.0)
-        return true;
-      else
-        return false;
-    default:
-      return true;
-    }
-  } else if (type->is_list()) {
-    // Empty lists are cheaply compared for structural equivalence.
-    // Is empty list?
-    if (val->get_list().size() == 0)
-      return true;
-    else
-      return false;
-  } else {
-    return false;
-  }
-}
-
-/**
- * Generates a struct definition for a thrift data type.
- *
- * @param tstruct The struct definition
- */
-void t_ocaml_generator::generate_ocaml_struct_sig(ofstream& out,
-                                                  t_struct* tstruct,
-                                                  bool is_exception) {
-  const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
-  string tname = type_name(tstruct);
-  indent(out) << "class " << tname << " :" << endl;
-  indent(out) << "object ('a)" << endl;
-
-  indent_up();
-
-  string x = tmp("_x");
-  if (members.size() > 0) {
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      string mname = decapitalize((*m_iter)->get_name());
-      string type = render_ocaml_type((*m_iter)->get_type());
-      indent(out) << "method get_" << mname << " : " << type << " option" << endl;
-      indent(out) << "method grab_" << mname << " : " << type << endl;
-      indent(out) << "method set_" << mname << " : " << type << " -> unit" << endl;
-      if (!struct_member_persistent(*m_iter))
-        indent(out) << "method unset_" << mname << " : unit" << endl;
-      indent(out) << "method reset_" << mname << " : unit" << endl;
-    }
-  }
-  indent(out) << "method copy : 'a" << endl;
-  indent(out) << "method write : Protocol.t -> unit" << endl;
-  indent_down();
-  indent(out) << "end" << endl;
-
-  if (is_exception) {
-    indent(out) << "exception " << capitalize(tname) << " of " << tname << endl;
-  }
-
-  indent(out) << "val read_" << tname << " : Protocol.t -> " << tname << endl;
-}
-
-/**
- * Generates the read method for a struct
- */
-void t_ocaml_generator::generate_ocaml_struct_reader(ofstream& out, t_struct* tstruct) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  string sname = type_name(tstruct);
-  string str = tmp("_str");
-  string t = tmp("_t");
-  string id = tmp("_id");
-  indent(out) << "let rec read_" << sname << " (iprot : Protocol.t) =" << endl;
-  indent_up();
-  indent(out) << "let " << str << " = new " << sname << " in" << endl;
-  indent_up();
-  indent(out) << "ignore(iprot#readStructBegin);" << endl;
-
-  // Loop over reading in fields
-  indent(out) << "(try while true do" << endl;
-  indent_up();
-  indent_up();
-
-  // Read beginning field marker
-  indent(out) << "let (_," << t << "," << id << ") = iprot#readFieldBegin in" << endl;
-
-  // Check for field STOP marker and break
-  indent(out) << "if " << t << " = Protocol.T_STOP then" << endl;
-  indent_up();
-  indent(out) << "raise Break" << endl;
-  indent_down();
-  indent(out) << "else ();" << endl;
-
-  indent(out) << "(match " << id << " with " << endl;
-  indent_up();
-  // Generate deserialization code for known cases
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(out) << "| " << (*f_iter)->get_key() << " -> (";
-    out << "if " << t << " = " << type_to_enum((*f_iter)->get_type()) << " then" << endl;
-    indent_up();
-    indent_up();
-    generate_deserialize_field(out, *f_iter, str);
-    indent_down();
-    out << indent() << "else" << endl << indent() << "  iprot#skip " << t << ")" << endl;
-    indent_down();
-  }
-
-  // In the default case we skip the field
-  out << indent() << "| _ -> "
-      << "iprot#skip " << t << ");" << endl;
-  indent_down();
-  // Read field end marker
-  indent(out) << "iprot#readFieldEnd;" << endl;
-  indent_down();
-  indent(out) << "done; ()" << endl;
-  indent_down();
-  indent(out) << "with Break -> ());" << endl;
-
-  indent(out) << "iprot#readStructEnd;" << endl;
-
-  indent(out) << str << endl << endl;
-  indent_down();
-  indent_down();
-}
-
-void t_ocaml_generator::generate_ocaml_struct_writer(ofstream& out, t_struct* tstruct) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-  string str = tmp("_str");
-  string f = tmp("_f");
-
-  indent(out) << "method write (oprot : Protocol.t) =" << endl;
-  indent_up();
-  indent(out) << "oprot#writeStructBegin \"" << name << "\";" << endl;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    t_field* tmember = (*f_iter);
-    string mname = "_" + decapitalize(tmember->get_name());
-    string _v;
-
-    if (struct_member_persistent(tmember)) {
-
-      if (struct_member_omitable(tmember) && struct_member_default_cheaply_comparable(tmember)) {
-        _v = "_v";
-        // Avoid redundant encoding of members having default values.
-        indent(out) << "(match " << mname << " with "
-                    << render_const_value(tmember->get_type(), tmember->get_value()) << " -> () | "
-                    << _v << " -> " << endl;
-      } else {
-        _v = mname;
-        indent(out) << "(" << endl;
-      }
-
-    } else {
-
-      indent(out) << "(match " << mname << " with ";
-
-      if (struct_member_omitable(tmember)) {
-        out << "None -> ()";
-
-        if (struct_member_default_cheaply_comparable(tmember)) {
-          // Avoid redundant encoding of members having default values.
-          out << " | Some " << render_const_value(tmember->get_type(), tmember->get_value())
-              << " -> ()";
-        }
-        out << " | Some _v -> " << endl;
-      } else {
-        out << endl;
-        indent(out) << "| None -> raise (Field_empty \"" << type_name(tstruct) << "." << mname
-                    << "\")" << endl;
-        indent(out) << "| Some _v -> " << endl;
-      }
-
-      _v = "_v";
-    }
-    indent_up();
-    // Write field header
-    indent(out) << "oprot#writeFieldBegin(\"" << tmember->get_name() << "\","
-                << type_to_enum(tmember->get_type()) << "," << tmember->get_key() << ");" << endl;
-
-    // Write field contents
-    generate_serialize_field(out, tmember, _v);
-
-    // Write field closer
-    indent(out) << "oprot#writeFieldEnd" << endl;
-
-    indent_down();
-    indent(out) << ");" << endl;
-  }
-
-  // Write the struct map
-  out << indent() << "oprot#writeFieldStop;" << endl << indent() << "oprot#writeStructEnd" << endl;
-
-  indent_down();
-}
-
-/**
- * Generates a thrift service.
- *
- * @param tservice The service definition
- */
-void t_ocaml_generator::generate_service(t_service* tservice) {
-  string f_service_name = get_out_dir() + capitalize(service_name_) + ".ml";
-  f_service_.open(f_service_name.c_str());
-  string f_service_i_name = get_out_dir() + capitalize(service_name_) + ".mli";
-  f_service_i_.open(f_service_i_name.c_str());
-
-  f_service_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
-  f_service_i_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
-
-  /* if (tservice->get_extends() != NULL) {
-    f_service_ <<
-      "open " << capitalize(tservice->get_extends()->get_name()) << endl;
-    f_service_i_ <<
-      "open " << capitalize(tservice->get_extends()->get_name()) << endl;
-  }
-  */
-  f_service_ << "open " << capitalize(program_name_) << "_types" << endl << endl;
-
-  f_service_i_ << "open " << capitalize(program_name_) << "_types" << endl << endl;
-
-  // Generate the three main parts of the service
-  generate_service_helpers(tservice);
-  generate_service_interface(tservice);
-  generate_service_client(tservice);
-  generate_service_server(tservice);
-
-  // Close service file
-  f_service_.close();
-  f_service_i_.close();
-}
-
-/**
- * Generates helper functions for a service.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_ocaml_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  indent(f_service_) << "(* HELPER FUNCTIONS AND STRUCTURES *)" << endl << endl;
-
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* ts = (*f_iter)->get_arglist();
-    generate_ocaml_struct_definition(f_service_, ts, false);
-    generate_ocaml_function_helpers(*f_iter);
-  }
-}
-
-/**
- * Generates a struct and helpers for a function.
- *
- * @param tfunction The function
- */
-void t_ocaml_generator::generate_ocaml_function_helpers(t_function* tfunction) {
-  t_struct result(program_, decapitalize(tfunction->get_name()) + "_result");
-  t_field success(tfunction->get_returntype(), "success", 0);
-  if (!tfunction->get_returntype()->is_void()) {
-    result.append(&success);
-  }
-
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& fields = xs->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result.append(*f_iter);
-  }
-  generate_ocaml_struct_definition(f_service_, &result, false);
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_ocaml_generator::generate_service_interface(t_service* tservice) {
-  f_service_ << indent() << "class virtual iface =" << endl << "object (self)" << endl;
-  f_service_i_ << indent() << "class virtual iface :" << endl << "object" << endl;
-
-  indent_up();
-
-  if (tservice->get_extends() != NULL) {
-    string extends = type_name(tservice->get_extends());
-    indent(f_service_) << "inherit " << extends << ".iface" << endl;
-    indent(f_service_i_) << "inherit " << extends << ".iface" << endl;
-  }
-
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string ft = function_type(*f_iter, true, true);
-    f_service_ << indent() << "method virtual " << decapitalize((*f_iter)->get_name()) << " : "
-               << ft << endl;
-    f_service_i_ << indent() << "method virtual " << decapitalize((*f_iter)->get_name()) << " : "
-                 << ft << endl;
-  }
-  indent_down();
-  indent(f_service_) << "end" << endl << endl;
-  indent(f_service_i_) << "end" << endl << endl;
-}
-
-/**
- * Generates a service client definition. Note that in OCaml, the client doesn't implement iface.
- *This is because
- * The client does not (and should not have to) deal with arguments being None.
- *
- * @param tservice The service to generate a server for.
- */
-void t_ocaml_generator::generate_service_client(t_service* tservice) {
-  string extends = "";
-  indent(f_service_) << "class client (iprot : Protocol.t) (oprot : Protocol.t) =" << endl
-                     << "object (self)" << endl;
-  indent(f_service_i_) << "class client : Protocol.t -> Protocol.t -> " << endl << "object" << endl;
-  indent_up();
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    indent(f_service_) << "inherit " << extends << ".client iprot oprot as super" << endl;
-    indent(f_service_i_) << "inherit " << extends << ".client" << endl;
-  }
-  indent(f_service_) << "val mutable seqid = 0" << endl;
-
-  // Generate client method implementations
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    string funname = (*f_iter)->get_name();
-
-    // Open function
-    indent(f_service_) << "method " << function_signature(*f_iter) << " = " << endl;
-    indent(f_service_i_) << "method " << decapitalize((*f_iter)->get_name()) << " : "
-                         << function_type(*f_iter, true, false) << endl;
-    indent_up();
-    indent(f_service_) << "self#send_" << funname;
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << " " << decapitalize((*fld_iter)->get_name());
-    }
-    f_service_ << ";" << endl;
-
-    if (!(*f_iter)->is_oneway()) {
-      f_service_ << indent();
-      f_service_ << "self#recv_" << funname << endl;
-    }
-    indent_down();
-
-    indent(f_service_) << "method private send_" << function_signature(*f_iter) << " = " << endl;
-    indent_up();
-
-    std::string argsname = decapitalize((*f_iter)->get_name() + "_args");
-
-    // Serialize the request header
-    f_service_ << indent() << "oprot#writeMessageBegin (\"" << (*f_iter)->get_name() << "\", "
-               << ((*f_iter)->is_oneway() ? "Protocol.ONEWAY" : "Protocol.CALL") << ", seqid);"
-               << endl;
-
-    f_service_ << indent() << "let args = new " << argsname << " in" << endl;
-    indent_up();
-
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << indent() << "args#set_" << (*fld_iter)->get_name() << " "
-                 << (*fld_iter)->get_name() << ";" << endl;
-    }
-
-    // Write to the stream
-    f_service_ << indent() << "args#write oprot;" << endl << indent() << "oprot#writeMessageEnd;"
-               << endl << indent() << "oprot#getTransport#flush" << endl;
-
-    indent_down();
-    indent_down();
-
-    if (!(*f_iter)->is_oneway()) {
-      std::string resultname = decapitalize((*f_iter)->get_name() + "_result");
-      t_struct noargs(program_);
-
-      t_function recv_function((*f_iter)->get_returntype(),
-                               string("recv_") + (*f_iter)->get_name(),
-                               &noargs);
-      // Open function
-      f_service_ << indent() << "method private " << function_signature(&recv_function) << " ="
-                 << endl;
-      indent_up();
-
-      // TODO(mcslee): Validate message reply here, seq ids etc.
-
-      f_service_ << indent() << "let (fname, mtype, rseqid) = iprot#readMessageBegin in" << endl;
-      indent_up();
-      f_service_ << indent() << "(if mtype = Protocol.EXCEPTION then" << endl << indent()
-                 << "  let x = Application_Exn.read iprot in" << endl;
-      indent_up();
-      f_service_ << indent() << "  (iprot#readMessageEnd;" << indent()
-                 << "   raise (Application_Exn.E x))" << endl;
-      indent_down();
-      f_service_ << indent() << "else ());" << endl;
-      string res = "_";
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-
-      if (!(*f_iter)->get_returntype()->is_void() || xceptions.size() > 0) {
-        res = "result";
-      }
-      f_service_ << indent() << "let " << res << " = read_" << resultname << " iprot in" << endl;
-      indent_up();
-      f_service_ << indent() << "iprot#readMessageEnd;" << endl;
-
-      // Careful, only return _result if not a void function
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << indent() << "match result#get_success with Some v -> v | None -> (" << endl;
-        indent_up();
-      }
-
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        f_service_ << indent() << "(match result#get_" << (*x_iter)->get_name()
-                   << " with None -> () | Some _v ->" << endl;
-        indent(f_service_) << "  raise (" << capitalize(type_name((*x_iter)->get_type()))
-                           << " _v));" << endl;
-      }
-
-      // Careful, only return _result if not a void function
-      if ((*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) << "()" << endl;
-      } else {
-        f_service_
-            << indent()
-            << "raise (Application_Exn.E (Application_Exn.create Application_Exn.MISSING_RESULT \""
-            << (*f_iter)->get_name() << " failed: unknown result\")))" << endl;
-        indent_down();
-      }
-
-      // Close function
-      indent_down();
-      indent_down();
-      indent_down();
-    }
-  }
-
-  indent_down();
-  indent(f_service_) << "end" << endl << endl;
-  indent(f_service_i_) << "end" << endl << endl;
-}
-
-/**
- * Generates a service server definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_ocaml_generator::generate_service_server(t_service* tservice) {
-  // Generate the dispatch methods
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
-
-  // Generate the header portion
-  indent(f_service_) << "class processor (handler : iface) =" << endl << indent() << "object (self)"
-                     << endl;
-  indent(f_service_i_) << "class processor : iface ->" << endl << indent() << "object" << endl;
-  indent_up();
-
-  f_service_ << indent() << "inherit Processor.t" << endl << endl;
-  f_service_i_ << indent() << "inherit Processor.t" << endl << endl;
-  string extends = "";
-
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    indent(f_service_) << "inherit " + extends + ".processor (handler :> " + extends + ".iface)"
-                       << endl;
-    indent(f_service_i_) << "inherit " + extends + ".processor" << endl;
-  }
-
-  if (extends.empty()) {
-    indent(f_service_) << "val processMap = Hashtbl.create " << functions.size() << endl;
-  }
-  indent(f_service_i_)
-      << "val processMap : (string, int * Protocol.t * Protocol.t -> unit) Hashtbl.t" << endl;
-
-  // Generate the server implementation
-  indent(f_service_) << "method process iprot oprot =" << endl;
-  indent(f_service_i_) << "method process : Protocol.t -> Protocol.t -> bool" << endl;
-  indent_up();
-
-  f_service_ << indent() << "let (name, typ, seqid)  = iprot#readMessageBegin in" << endl;
-  indent_up();
-  // TODO(mcslee): validate message
-
-  // HOT: dictionary function lookup
-  f_service_ << indent() << "if Hashtbl.mem processMap name then" << endl << indent()
-             << "  (Hashtbl.find processMap name) (seqid, iprot, oprot)" << endl << indent()
-             << "else (" << endl << indent() << "  iprot#skip(Protocol.T_STRUCT);" << endl
-             << indent() << "  iprot#readMessageEnd;" << endl << indent()
-             << "  let x = Application_Exn.create Application_Exn.UNKNOWN_METHOD (\"Unknown "
-                "function \"^name) in" << endl << indent()
-             << "    oprot#writeMessageBegin(name, Protocol.EXCEPTION, seqid);" << endl << indent()
-             << "    x#write oprot;" << endl << indent() << "    oprot#writeMessageEnd;" << endl
-             << indent() << "    oprot#getTransport#flush" << endl << indent() << ");" << endl;
-
-  // Read end of args field, the T_STOP, and the struct close
-  f_service_ << indent() << "true" << endl;
-  indent_down();
-  indent_down();
-  // Generate the process subfunctions
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    generate_process_function(tservice, *f_iter);
-  }
-
-  indent(f_service_) << "initializer" << endl;
-  indent_up();
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    f_service_ << indent() << "Hashtbl.add processMap \"" << (*f_iter)->get_name()
-               << "\" self#process_" << (*f_iter)->get_name() << ";" << endl;
-  }
-  indent_down();
-
-  indent_down();
-  indent(f_service_) << "end" << endl << endl;
-  indent(f_service_i_) << "end" << endl << endl;
-}
-
-/**
- * Generates a process function definition.
- *
- * @param tfunction The function to write a dispatcher for
- */
-void t_ocaml_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  (void)tservice;
-  // Open function
-  indent(f_service_) << "method private process_" << tfunction->get_name()
-                     << " (seqid, iprot, oprot) =" << endl;
-  indent_up();
-
-  string argsname = decapitalize(tfunction->get_name()) + "_args";
-  string resultname = decapitalize(tfunction->get_name()) + "_result";
-
-  // Generate the function call
-  t_struct* arg_struct = tfunction->get_arglist();
-  const std::vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  string args = "args";
-  if (fields.size() == 0) {
-    args = "_";
-  }
-
-  f_service_ << indent() << "let " << args << " = read_" << argsname << " iprot in" << endl;
-  indent_up();
-  f_service_ << indent() << "iprot#readMessageEnd;" << endl;
-
-  t_struct* xs = tfunction->get_xceptions();
-  const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
-
-  // Declare result for non oneway function
-  if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "let result = new " << resultname << " in" << endl;
-    indent_up();
-  }
-
-  // Try block for a function with exceptions
-  if (xceptions.size() > 0) {
-    f_service_ << indent() << "(try" << endl;
-    indent_up();
-  }
-
-  f_service_ << indent();
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "result#set_success ";
-  }
-  f_service_ << "(handler#" << tfunction->get_name();
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    f_service_ << " args#get_" << (*f_iter)->get_name();
-  }
-  f_service_ << ");" << endl;
-
-  if (xceptions.size() > 0) {
-    indent_down();
-    indent(f_service_) << "with" << endl;
-    indent_up();
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << indent() << "| " << capitalize(type_name((*x_iter)->get_type())) << " "
-                 << (*x_iter)->get_name() << " -> " << endl;
-      indent_up();
-      indent_up();
-      if (!tfunction->is_oneway()) {
-        f_service_ << indent() << "result#set_" << (*x_iter)->get_name() << " "
-                   << (*x_iter)->get_name() << endl;
-      } else {
-        indent(f_service_) << "()";
-      }
-      indent_down();
-      indent_down();
-    }
-    indent_down();
-    f_service_ << indent() << ");" << endl;
-  }
-
-  // Shortcut out here for oneway functions
-  if (tfunction->is_oneway()) {
-    f_service_ << indent() << "()" << endl;
-    indent_down();
-    indent_down();
-    return;
-  }
-
-  f_service_ << indent() << "oprot#writeMessageBegin (\"" << tfunction->get_name()
-             << "\", Protocol.REPLY, seqid);" << endl << indent() << "result#write oprot;" << endl
-             << indent() << "oprot#writeMessageEnd;" << endl << indent()
-             << "oprot#getTransport#flush" << endl;
-
-  // Close function
-  indent_down();
-  indent_down();
-  indent_down();
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_ocaml_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
-  t_type* type = tfield->get_type();
-
-  string name = decapitalize(tfield->get_name());
-  indent(out) << prefix << "#set_" << name << " ";
-  generate_deserialize_type(out, type);
-  out << endl;
-}
-
-/**
- * Deserializes a field of any type.
- */
-void t_ocaml_generator::generate_deserialize_type(ofstream& out, t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_void()) {
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE";
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_deserialize_struct(out, (t_struct*)type);
-  } else if (type->is_container()) {
-    generate_deserialize_container(out, type);
-  } else if (type->is_base_type()) {
-    out << "iprot#";
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "compiler error: cannot serialize void field in a struct";
-      break;
-    case t_base_type::TYPE_STRING:
-      out << "readString";
-      break;
-    case t_base_type::TYPE_BOOL:
-      out << "readBool";
-      break;
-    case t_base_type::TYPE_I8:
-      out << "readByte";
-      break;
-    case t_base_type::TYPE_I16:
-      out << "readI16";
-      break;
-    case t_base_type::TYPE_I32:
-      out << "readI32";
-      break;
-    case t_base_type::TYPE_I64:
-      out << "readI64";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      out << "readDouble";
-      break;
-    default:
-      throw "compiler error: no ocaml name for base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    string ename = capitalize(type->get_name());
-    out << "(" << ename << ".of_i iprot#readI32)";
-  } else {
-    printf("DO NOT KNOW HOW TO DESERIALIZE TYPE '%s'\n", type->get_name().c_str());
-  }
-}
-
-/**
- * Generates an unserializer for a struct, calling read()
- */
-void t_ocaml_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct) {
-  string prefix = "";
-  t_program* program = tstruct->get_program();
-  if (program != NULL && program != program_) {
-    prefix = capitalize(program->get_name()) + "_types.";
-  }
-  string name = decapitalize(tstruct->get_name());
-  out << "(" << prefix << "read_" << name << " iprot)";
-}
-
-/**
- * Serialize a container by writing out the header followed by
- * data and then a footer.
- */
-void t_ocaml_generator::generate_deserialize_container(ofstream& out, t_type* ttype) {
-  string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
-  string con = tmp("_con");
-
-  t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  out << endl;
-  indent_up();
-  // Declare variables, read header
-  if (ttype->is_map()) {
-    indent(out) << "(let (" << ktype << "," << vtype << "," << size << ") = iprot#readMapBegin in"
-                << endl;
-    indent(out) << "let " << con << " = Hashtbl.create " << size << " in" << endl;
-    indent_up();
-    indent(out) << "for i = 1 to " << size << " do" << endl;
-    indent_up();
-    indent(out) << "let _k = ";
-    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type());
-    out << " in" << endl;
-    indent(out) << "let _v = ";
-    generate_deserialize_type(out, ((t_map*)ttype)->get_val_type());
-    out << " in" << endl;
-    indent_up();
-    indent(out) << "Hashtbl.add " << con << " _k _v" << endl;
-    indent_down();
-    indent_down();
-    indent(out) << "done; iprot#readMapEnd; " << con << ")";
-    indent_down();
-  } else if (ttype->is_set()) {
-    indent(out) << "(let (" << etype << "," << size << ") = iprot#readSetBegin in" << endl;
-    indent(out) << "let " << con << " = Hashtbl.create " << size << " in" << endl;
-    indent_up();
-    indent(out) << "for i = 1 to " << size << " do" << endl;
-    indent_up();
-    indent(out) << "Hashtbl.add " << con << " ";
-    generate_deserialize_type(out, ((t_set*)ttype)->get_elem_type());
-    out << " true" << endl;
-    indent_down();
-    indent(out) << "done; iprot#readSetEnd; " << con << ")";
-    indent_down();
-  } else if (ttype->is_list()) {
-    indent(out) << "(let (" << etype << "," << size << ") = iprot#readListBegin in" << endl;
-    indent_up();
-    indent(out) << "let " << con << " = (Array.to_list (Array.init " << size << " (fun _ -> ";
-    generate_deserialize_type(out, ((t_list*)ttype)->get_elem_type());
-    out << "))) in" << endl;
-    indent_up();
-    indent(out) << "iprot#readListEnd; " << con << ")";
-    indent_down();
-    indent_down();
-  }
-  indent_down();
-}
-
-/**
- * Serializes a field of any type.
- *
- * @param tfield The field to serialize
- * @param prefix Name to prepend to field name
- */
-void t_ocaml_generator::generate_serialize_field(ofstream& out, t_field* tfield, string name) {
-  t_type* type = get_true_type(tfield->get_type());
-
-  // Do nothing for void types
-  if (type->is_void()) {
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + tfield->get_name();
-  }
-
-  if (name.length() == 0) {
-    name = decapitalize(tfield->get_name());
-  }
-
-  if (type->is_struct() || type->is_xception()) {
-    generate_serialize_struct(out, (t_struct*)type, name);
-  } else if (type->is_container()) {
-    generate_serialize_container(out, type, name);
-  } else if (type->is_base_type() || type->is_enum()) {
-
-    indent(out) << "oprot#";
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot serialize void field in a struct: " + name;
-        break;
-      case t_base_type::TYPE_STRING:
-        out << "writeString(" << name << ")";
-        break;
-      case t_base_type::TYPE_BOOL:
-        out << "writeBool(" << name << ")";
-        break;
-      case t_base_type::TYPE_I8:
-        out << "writeByte(" << name << ")";
-        break;
-      case t_base_type::TYPE_I16:
-        out << "writeI16(" << name << ")";
-        break;
-      case t_base_type::TYPE_I32:
-        out << "writeI32(" << name << ")";
-        break;
-      case t_base_type::TYPE_I64:
-        out << "writeI64(" << name << ")";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(" << name << ")";
-        break;
-      default:
-        throw "compiler error: no ocaml name for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      string ename = capitalize(type->get_name());
-      out << "writeI32(" << ename << ".to_i " << name << ")";
-    }
-
-  } else {
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
-           tfield->get_name().c_str(),
-           type->get_name().c_str());
-  }
-  out << ";" << endl;
-}
-
-/**
- * Serializes all the members of a struct.
- *
- * @param tstruct The struct to serialize
- * @param prefix  String prefix to attach to all fields
- */
-void t_ocaml_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
-  (void)tstruct;
-  indent(out) << prefix << "#write(oprot)";
-}
-
-void t_ocaml_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  if (ttype->is_map()) {
-    indent(out) << "oprot#writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ",";
-    out << type_to_enum(((t_map*)ttype)->get_val_type()) << ",";
-    out << "Hashtbl.length " << prefix << ");" << endl;
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot#writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ",";
-    out << "Hashtbl.length " << prefix << ");" << endl;
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot#writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
-                << ",";
-    out << "List.length " << prefix << ");" << endl;
-  }
-
-  if (ttype->is_map()) {
-    string kiter = tmp("_kiter");
-    string viter = tmp("_viter");
-    indent(out) << "Hashtbl.iter (fun " << kiter << " -> fun " << viter << " -> " << endl;
-    indent_up();
-    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
-    indent_down();
-    indent(out) << ") " << prefix << ";" << endl;
-  } else if (ttype->is_set()) {
-    string iter = tmp("_iter");
-    indent(out) << "Hashtbl.iter (fun " << iter << " -> fun _ -> ";
-    indent_up();
-    generate_serialize_set_element(out, (t_set*)ttype, iter);
-    indent_down();
-    indent(out) << ") " << prefix << ";" << endl;
-  } else if (ttype->is_list()) {
-    string iter = tmp("_iter");
-    indent(out) << "List.iter (fun " << iter << " -> ";
-    indent_up();
-    generate_serialize_list_element(out, (t_list*)ttype, iter);
-    indent_down();
-    indent(out) << ") " << prefix << ";" << endl;
-  }
-
-  if (ttype->is_map()) {
-    indent(out) << "oprot#writeMapEnd";
-  } else if (ttype->is_set()) {
-    indent(out) << "oprot#writeSetEnd";
-  } else if (ttype->is_list()) {
-    indent(out) << "oprot#writeListEnd";
-  }
-}
-
-/**
- * Serializes the members of a map.
- *
- */
-void t_ocaml_generator::generate_serialize_map_element(ofstream& out,
-                                                       t_map* tmap,
-                                                       string kiter,
-                                                       string viter) {
-  t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(out, &kfield);
-
-  t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(out, &vfield);
-}
-
-/**
- * Serializes the members of a set.
- */
-void t_ocaml_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
-  t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(out, &efield);
-}
-
-/**
- * Serializes the members of a list.
- */
-void t_ocaml_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
-  t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(out, &efield);
-}
-
-/**
- * Renders a function signature of the form 'name args'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_ocaml_generator::function_signature(t_function* tfunction, string prefix) {
-  return prefix + decapitalize(tfunction->get_name()) + " "
-         + argument_list(tfunction->get_arglist());
-}
-
-string t_ocaml_generator::function_type(t_function* tfunc, bool method, bool options) {
-  string result = "";
-
-  const vector<t_field*>& fields = tfunc->get_arglist()->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    result += render_ocaml_type((*f_iter)->get_type());
-    if (options)
-      result += " option";
-    result += " -> ";
-  }
-  if (fields.empty() && !method) {
-    result += "unit -> ";
-  }
-  result += render_ocaml_type(tfunc->get_returntype());
-  return result;
-}
-
-/**
- * Renders a field list
- */
-string t_ocaml_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += " ";
-    }
-    result += (*f_iter)->get_name();
-  }
-  return result;
-}
-
-string t_ocaml_generator::type_name(t_type* ttype) {
-  string prefix = "";
-  t_program* program = ttype->get_program();
-  if (program != NULL && program != program_) {
-    if (!ttype->is_service()) {
-      prefix = capitalize(program->get_name()) + "_types.";
-    }
-  }
-
-  string name = ttype->get_name();
-  if (ttype->is_service()) {
-    name = capitalize(name);
-  } else {
-    name = decapitalize(name);
-  }
-  return prefix + name;
-}
-
-/**
- * Converts the parse type to a Protocol.t_type enum
- */
-string t_ocaml_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      return "Protocol.T_VOID";
-    case t_base_type::TYPE_STRING:
-      return "Protocol.T_STRING";
-    case t_base_type::TYPE_BOOL:
-      return "Protocol.T_BOOL";
-    case t_base_type::TYPE_I8:
-      return "Protocol.T_BYTE";
-    case t_base_type::TYPE_I16:
-      return "Protocol.T_I16";
-    case t_base_type::TYPE_I32:
-      return "Protocol.T_I32";
-    case t_base_type::TYPE_I64:
-      return "Protocol.T_I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "Protocol.T_DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "Protocol.T_I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return "Protocol.T_STRUCT";
-  } else if (type->is_map()) {
-    return "Protocol.T_MAP";
-  } else if (type->is_set()) {
-    return "Protocol.T_SET";
-  } else if (type->is_list()) {
-    return "Protocol.T_LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-/**
- * Converts the parse type to an ocaml type
- */
-string t_ocaml_generator::render_ocaml_type(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      return "unit";
-    case t_base_type::TYPE_STRING:
-      return "string";
-    case t_base_type::TYPE_BOOL:
-      return "bool";
-    case t_base_type::TYPE_I8:
-      return "int";
-    case t_base_type::TYPE_I16:
-      return "int";
-    case t_base_type::TYPE_I32:
-      return "Int32.t";
-    case t_base_type::TYPE_I64:
-      return "Int64.t";
-    case t_base_type::TYPE_DOUBLE:
-      return "float";
-    }
-  } else if (type->is_enum()) {
-    return capitalize(((t_enum*)type)->get_name()) + ".t";
-  } else if (type->is_struct() || type->is_xception()) {
-    return type_name((t_struct*)type);
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    return "(" + render_ocaml_type(ktype) + "," + render_ocaml_type(vtype) + ") Hashtbl.t";
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    return "(" + render_ocaml_type(etype) + ",bool) Hashtbl.t";
-  } else if (type->is_list()) {
-    t_type* etype = ((t_list*)type)->get_elem_type();
-    return render_ocaml_type(etype) + " list";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-THRIFT_REGISTER_GENERATOR(ocaml, "OCaml", "")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_oop_generator.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_oop_generator.h b/compiler/cpp/src/generate/t_oop_generator.h
deleted file mode 100644
index e5a4698..0000000
--- a/compiler/cpp/src/generate/t_oop_generator.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_OOP_GENERATOR_H
-#define T_OOP_GENERATOR_H
-
-#include <string>
-#include <iostream>
-
-#include "common.h"
-#include "t_generator.h"
-
-#include <algorithm>
-
-/**
- * Class with utility methods shared across common object oriented languages.
- * Specifically, most of this stuff is for C++/Java.
- *
- */
-class t_oop_generator : public t_generator {
-public:
-  t_oop_generator(t_program* program) : t_generator(program) {}
-
-  /**
-   * Scoping, using curly braces!
-   */
-
-  void scope_up(std::ostream& out) {
-    indent(out) << "{" << std::endl;
-    indent_up();
-  }
-
-  void scope_down(std::ostream& out) {
-    indent_down();
-    indent(out) << "}" << std::endl;
-  }
-
-  std::string upcase_string(std::string original) {
-    std::transform(original.begin(), original.end(), original.begin(), (int (*)(int))toupper);
-    return original;
-  }
-
-  virtual std::string get_enum_class_name(t_type* type) {
-    std::string package = "";
-    t_program* program = type->get_program();
-    if (program != NULL && program != program_) {
-      package = program->get_namespace("java") + ".";
-    }
-    return package + type->get_name();
-  }
-
-  virtual void generate_java_docstring_comment(std::ofstream& out, std::string contents) {
-    generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
-  }
-
-  virtual void generate_java_doc(std::ofstream& out, t_field* field) {
-    if (field->get_type()->is_enum()) {
-      std::string combined_message = field->get_doc() + "\n@see "
-                                     + get_enum_class_name(field->get_type());
-      generate_java_docstring_comment(out, combined_message);
-    } else {
-      generate_java_doc(out, (t_doc*)field);
-    }
-  }
-
-  /**
-   * Emits a JavaDoc comment if the provided object has a doc in Thrift
-   */
-  virtual void generate_java_doc(std::ofstream& out, t_doc* tdoc) {
-    if (tdoc->has_doc()) {
-      generate_java_docstring_comment(out, tdoc->get_doc());
-    }
-  }
-
-  /**
-   * Emits a JavaDoc comment if the provided function object has a doc in Thrift
-   */
-  virtual void generate_java_doc(std::ofstream& out, t_function* tfunction) {
-    if (tfunction->has_doc()) {
-      std::stringstream ss;
-      ss << tfunction->get_doc();
-      const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
-      std::vector<t_field*>::const_iterator p_iter;
-      for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
-        t_field* p = *p_iter;
-        ss << "\n@param " << p->get_name();
-        if (p->has_doc()) {
-          ss << " " << p->get_doc();
-        }
-      }
-      generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n");
-    }
-  }
-};
-
-#endif


[49/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/generate/t_c_glib_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_c_glib_generator.cc b/compiler/cpp/src/generate/t_c_glib_generator.cc
deleted file mode 100644
index 3a3fe54..0000000
--- a/compiler/cpp/src/generate/t_c_glib_generator.cc
+++ /dev/null
@@ -1,4562 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- *
- * Contains some contributions under the Thrift Software License.
- * Please see doc/old-thrift-license.txt in the Thrift distribution for
- * details.
- */
-
-#include <fstream>
-#include <iostream>
-#include <stdexcept>
-#include <string>
-#include <vector>
-
-#include <ctype.h>
-
-#include "platform.h"
-#include "t_oop_generator.h"
-
-using std::map;
-using std::ofstream;
-using std::ostringstream;
-using std::string;
-using std::stringstream;
-using std::vector;
-
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-/* forward declarations */
-string initial_caps_to_underscores(string name);
-string underscores_to_initial_caps(string name);
-string to_upper_case(string name);
-string to_lower_case(string name);
-
-/**
- * C code generator, using glib for C typing.
- */
-class t_c_glib_generator : public t_oop_generator {
-public:
-  /* constructor */
-  t_c_glib_generator(t_program* program,
-                     const map<string, string>& parsed_options,
-                     const string& option_string)
-    : t_oop_generator(program) {
-    (void)option_string;
-    std::map<std::string, std::string>::const_iterator iter;
-
-    /* set the output directory */
-    this->out_dir_base_ = "gen-c_glib";
-
-    /* no options yet */
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
-      throw "unknown option c_glib:" + iter->first; 
-    }
-
-    /* set the namespace */
-    this->nspace = program_->get_namespace("c_glib");
-
-    if (this->nspace.empty()) {
-      this->nspace = "";
-      this->nspace_u = "";
-      this->nspace_uc = "";
-      this->nspace_lc = "";
-    } else {
-      /* replace dots with underscores */
-      char* tmp = strdup(this->nspace.c_str());
-      for (unsigned int i = 0; i < strlen(tmp); i++) {
-        if (tmp[i] == '.') {
-          tmp[i] = '_';
-        }
-      }
-      this->nspace = string(tmp, strlen(tmp));
-      free(tmp);
-
-      /* clean up the namespace for C.
-       * An input of 'namespace foo' should result in:
-       *  - nspace = foo       - for thrift objects and typedefs
-       *  - nspace_u = Foo     - for internal GObject prefixes
-       *  - nspace_uc = FOO_   - for macro prefixes
-       *  - nspace_lc = foo_   - for filename and method prefixes
-       * The underscores are there since uc and lc strings are used as file and
-       * variable prefixes.
-       */
-      this->nspace_u = initial_caps_to_underscores(this->nspace);
-      this->nspace_uc = to_upper_case(this->nspace_u) + "_";
-      this->nspace_lc = to_lower_case(this->nspace_u) + "_";
-    }
-  }
-
-  /* initialization and destruction */
-  void init_generator();
-  void close_generator();
-
-  /* generation functions */
-  void generate_typedef(t_typedef* ttypedef);
-  void generate_enum(t_enum* tenum);
-  void generate_consts(vector<t_const*> consts);
-  void generate_struct(t_struct* tstruct);
-  void generate_service(t_service* tservice);
-  void generate_xception(t_struct* tstruct);
-
-private:
-  /* file streams */
-  ofstream f_types_;
-  ofstream f_types_impl_;
-  ofstream f_header_;
-  ofstream f_service_;
-
-  /* namespace variables */
-  string nspace;
-  string nspace_u;
-  string nspace_uc;
-  string nspace_lc;
-
-  /* helper functions */
-  bool is_complex_type(t_type* ttype);
-  bool is_numeric(t_type* ttype);
-  string type_name(t_type* ttype, bool in_typedef = false, bool is_const = false);
-  string property_type_name(t_type* ttype, bool in_typedef = false, bool is_const = false);
-  string base_type_name(t_type* type);
-  string type_to_enum(t_type* type);
-  string constant_literal(t_type* type, t_const_value* value);
-  string constant_value(string name, t_type* type, t_const_value* value);
-  string constant_value_with_storage(string name, t_type* type, t_const_value* value);
-  string function_signature(t_function* tfunction);
-  string argument_list(t_struct* tstruct);
-  string xception_list(t_struct* tstruct);
-  string declare_field(t_field* tfield,
-                       bool init = false,
-                       bool pointer = false,
-                       bool constant = false,
-                       bool reference = false);
-  void declare_local_variable(ofstream& out, t_type* ttype, string& base_name, bool for_hash_table);
-  void declore_local_variable_for_write(ofstream& out, t_type* ttype, string& base_name);
-
-  /* generation functions */
-  void generate_const_initializer(string name,
-                                  t_type* type,
-                                  t_const_value* value,
-                                  bool top_level = false);
-  void generate_service_helpers(t_service* tservice);
-  void generate_service_client(t_service* tservice);
-  void generate_service_handler(t_service* tservice);
-  void generate_service_processor(t_service* tservice);
-  void generate_service_server(t_service* tservice);
-  void generate_object(t_struct* tstruct);
-  void generate_struct_writer(ofstream& out,
-                              t_struct* tstruct,
-                              string this_name,
-                              string this_get = "",
-                              bool is_function = true);
-  void generate_struct_reader(ofstream& out,
-                              t_struct* tstruct,
-                              string this_name,
-                              string this_get = "",
-                              bool is_function = true);
-
-  void generate_serialize_field(ofstream& out,
-                                t_field* tfield,
-                                string prefix,
-                                string suffix,
-                                int error_ret);
-  void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix, int error_ret);
-  void generate_serialize_container(ofstream& out, t_type* ttype, string prefix, int error_ret);
-  void generate_serialize_map_element(ofstream& out,
-                                      t_map* tmap,
-                                      string key,
-                                      string value,
-                                      int error_ret);
-  void generate_serialize_set_element(ofstream& out, t_set* tset, string element, int error_ret);
-  void generate_serialize_list_element(ofstream& out,
-                                       t_list* tlist,
-                                       string list,
-                                       string index,
-                                       int error_ret);
-
-  void generate_deserialize_field(ofstream& out,
-                                  t_field* tfield,
-                                  string prefix,
-                                  string suffix,
-                                  int error_ret,
-                                  bool allocate = true);
-  void generate_deserialize_struct(ofstream& out,
-                                   t_struct* tstruct,
-                                   string prefix,
-                                   int error_ret,
-                                   bool allocate = true);
-  void generate_deserialize_container(ofstream& out, t_type* ttype, string prefix, int error_ret);
-  void generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix, int error_ret);
-  void generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix, int error_ret);
-  void generate_deserialize_list_element(ofstream& out,
-                                         t_list* tlist,
-                                         string prefix,
-                                         string index,
-                                         int error_ret);
-
-  string generate_new_hash_from_type(t_type* key, t_type* value);
-  string generate_new_array_from_type(t_type* ttype);
-
-  string generate_free_func_from_type(t_type* ttype);
-  string generate_hash_func_from_type(t_type* ttype);
-  string generate_cmp_func_from_type(t_type* ttype);
-};
-
-/**
- * Prepare for file generation by opening up the necessary file
- * output streams.
- */
-void t_c_glib_generator::init_generator() {
-  /* create output directory */
-  MKDIR(get_out_dir().c_str());
-
-  string program_name_u = initial_caps_to_underscores(program_name_);
-  string program_name_uc = to_upper_case(program_name_u);
-  string program_name_lc = to_lower_case(program_name_u);
-
-  /* create output files */
-  string f_types_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.h";
-  f_types_.open(f_types_name.c_str());
-  string f_types_impl_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.c";
-  f_types_impl_.open(f_types_impl_name.c_str());
-
-  /* add thrift boilerplate headers */
-  f_types_ << autogen_comment();
-  f_types_impl_ << autogen_comment();
-
-  /* include inclusion guard */
-  f_types_ << "#ifndef " << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << "#define "
-           << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << endl;
-
-  /* include base types */
-  f_types_ << "/* base includes */" << endl << "#include <glib-object.h>" << endl
-           << "#include <thrift/c_glib/thrift_struct.h>" << endl
-           << "#include <thrift/c_glib/protocol/thrift_protocol.h>" << endl;
-
-  /* include other thrift includes */
-  const vector<t_program*>& includes = program_->get_includes();
-  for (size_t i = 0; i < includes.size(); ++i) {
-    f_types_ << "/* other thrift includes */" << endl << "#include \"" << this->nspace_lc
-             << initial_caps_to_underscores(includes[i]->get_name()) << "_types.h\"" << endl;
-  }
-  f_types_ << endl;
-
-  /* include custom headers */
-  const vector<string>& c_includes = program_->get_c_includes();
-  f_types_ << "/* custom thrift includes */" << endl;
-  for (size_t i = 0; i < c_includes.size(); ++i) {
-    if (c_includes[i][0] == '<') {
-      f_types_ << "#include " << c_includes[i] << endl;
-    } else {
-      f_types_ << "#include \"" << c_includes[i] << "\"" << endl;
-    }
-  }
-  f_types_ << endl;
-
-  /* include math.h (for "INFINITY") in the implementation file, in case we
-     encounter a struct with a member of type double */
-  f_types_impl_ << endl << "#include <math.h>" << endl;
-
-  // include the types file
-  f_types_impl_ << endl << "#include \"" << this->nspace_lc << program_name_u << "_types.h\""
-                << endl << "#include <thrift/c_glib/thrift.h>" << endl << endl;
-
-  f_types_ << "/* begin types */" << endl << endl;
-}
-
-/**
- *  Finish up generation and close all file streams.
- */
-void t_c_glib_generator::close_generator() {
-  string program_name_uc = to_upper_case(initial_caps_to_underscores(program_name_));
-
-  /* end the header inclusion guard */
-  f_types_ << "#endif /* " << this->nspace_uc << program_name_uc << "_TYPES_H */" << endl;
-
-  /* close output file */
-  f_types_.close();
-  f_types_impl_.close();
-}
-
-/**
- * Generates a Thrift typedef in C code.  For example:
- *
- * Thrift:
- * typedef map<i32,i32> SomeMap
- *
- * C:
- * typedef GHashTable * ThriftSomeMap;
- */
-void t_c_glib_generator::generate_typedef(t_typedef* ttypedef) {
-  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << this->nspace
-           << ttypedef->get_symbolic() << ";" << endl << endl;
-}
-
-/**
- * Generates a C enumeration.  For example:
- *
- * Thrift:
- * enum MyEnum {
- *   ONE = 1,
- *   TWO
- * }
- *
- * C:
- * enum _ThriftMyEnum {
- *   THRIFT_MY_ENUM_ONE = 1,
- *   THRIFT_MY_ENUM_TWO
- * };
- * typedef enum _ThriftMyEnum ThriftMyEnum;
- */
-void t_c_glib_generator::generate_enum(t_enum* tenum) {
-  string name = tenum->get_name();
-  string name_uc = to_upper_case(initial_caps_to_underscores(name));
-
-  f_types_ << indent() << "enum _" << this->nspace << name << " {" << endl;
-
-  indent_up();
-
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
-  bool first = true;
-
-  /* output each of the enumeration elements */
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    if (first) {
-      first = false;
-    } else {
-      f_types_ << "," << endl;
-    }
-
-    f_types_ << indent() << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name();
-    f_types_ << " = " << (*c_iter)->get_value();
-  }
-
-  indent_down();
-  f_types_ << endl << "};" << endl << "typedef enum _" << this->nspace << name << " "
-           << this->nspace << name << ";" << endl << endl;
-
-  f_types_ << "/* return the name of the constant */" << endl;
-  f_types_ << "const char *" << endl;
-  f_types_ << "toString_" << name << "(int value); " << endl << endl;
-  ;
-  f_types_impl_ << "/* return the name of the constant */" << endl;
-  f_types_impl_ << "const char *" << endl;
-  f_types_impl_ << "toString_" << name << "(int value) " << endl;
-  f_types_impl_ << "{" << endl;
-  f_types_impl_ << "  static __thread char buf[16] = {0};" << endl;
-  f_types_impl_ << "  switch(value) {" << endl;
-  std::set<int> done;
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
-    int value = (*c_iter)->get_value();
-    // Skipping duplicate value
-    if (done.find(value) == done.end()) {
-      done.insert(value);
-      f_types_impl_ << "  case " << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name()
-                    << ":"
-                    << "return \"" << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name()
-                    << "\";" << endl;
-    }
-  }
-  f_types_impl_ << "  default: g_snprintf(buf, 16, \"%d\", value); return buf;" << endl;
-  f_types_impl_ << "  }" << endl;
-  f_types_impl_ << "}" << endl << endl;
-}
-
-/**
- * Generates Thrift constants in C code.
- */
-void t_c_glib_generator::generate_consts(vector<t_const*> consts) {
-  f_types_ << "/* constants */" << endl;
-  f_types_impl_ << "/* constants */" << endl;
-
-  vector<t_const*>::iterator c_iter;
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    string name = (*c_iter)->get_name();
-    string name_uc = to_upper_case(name);
-    string name_lc = to_lower_case(name);
-    t_type* type = (*c_iter)->get_type();
-    t_const_value* value = (*c_iter)->get_value();
-
-    if (is_complex_type(type)) {
-      f_types_ << type_name(type) << indent() << this->nspace_lc << name_lc
-               << "_constant();" << endl;
-    }
-
-    f_types_ << indent() << "#define " << this->nspace_uc << name_uc << " "
-             << constant_value(name_lc, type, value) << endl;
-
-    generate_const_initializer(name_lc, type, value, true);
-  }
-
-  f_types_ << endl;
-  f_types_impl_ << endl;
-}
-
-/**
- * Generate Thrift structs in C code, as GObjects.  Example:
- *
- * Thrift:
- * struct Bonk
- * {
- *   1: string message,
- *   2: i32 type
- * }
- *
- * C GObject instance header:
- * struct _ThriftBonk
- * {
- *   GObject parent;
- *
- *   gchar * message;
- *   gint32 type;
- * };
- * typedef struct _ThriftBonk ThriftBonk
- * // ... additional GObject boilerplate ...
- */
-void t_c_glib_generator::generate_struct(t_struct* tstruct) {
-  f_types_ << "/* struct " << tstruct->get_name() << " */" << endl;
-  generate_object(tstruct);
-}
-
-/**
- * Generate C code to represent Thrift services.  Creates a new GObject
- * which can be used to access the service.
- */
-void t_c_glib_generator::generate_service(t_service* tservice) {
-  string svcname_u = initial_caps_to_underscores(tservice->get_name());
-  string svcname_uc = this->nspace_uc + to_upper_case(svcname_u);
-  string filename = this->nspace_lc + to_lower_case(svcname_u);
-
-  // make output files
-  string f_header_name = get_out_dir() + filename + ".h";
-  f_header_.open(f_header_name.c_str());
-
-  string program_name_u = initial_caps_to_underscores(program_name_);
-  string program_name_lc = to_lower_case(program_name_u);
-
-  // add header file boilerplate
-  f_header_ << autogen_comment();
-
-  // add an inclusion guard
-  f_header_ << "#ifndef " << svcname_uc << "_H" << endl << "#define " << svcname_uc << "_H" << endl
-            << endl;
-
-  // add standard includes
-  f_header_ << "#include <thrift/c_glib/processor/thrift_dispatch_processor.h>" << endl << endl;
-  f_header_ << "#include \"" << this->nspace_lc << program_name_lc << "_types.h\"" << endl;
-
-  // if we are inheriting from another service, include its header
-  t_service* extends_service = tservice->get_extends();
-  if (extends_service != NULL) {
-    f_header_ << "#include \"" << this->nspace_lc
-              << to_lower_case(initial_caps_to_underscores(extends_service->get_name())) << ".h\""
-              << endl;
-  }
-  f_header_ << endl;
-
-  // create the service implementation
-  string f_service_name = get_out_dir() + filename + ".c";
-  f_service_.open(f_service_name.c_str());
-
-  // add the boilerplace header
-  f_service_ << autogen_comment();
-
-  // include the headers
-  f_service_ << "#include <string.h>" << endl << "#include <thrift/c_glib/thrift.h>" << endl
-             << "#include <thrift/c_glib/thrift_application_exception.h>" << endl << "#include \""
-             << filename << ".h\"" << endl << endl;
-
-  // generate the service-helper classes
-  generate_service_helpers(tservice);
-
-  // generate the client objects
-  generate_service_client(tservice);
-
-  // generate the server objects
-  generate_service_server(tservice);
-
-  // end the header inclusion guard
-  f_header_ << "#endif /* " << svcname_uc << "_H */" << endl;
-
-  // close the files
-  f_service_.close();
-  f_header_.close();
-}
-
-/**
- *
- */
-void t_c_glib_generator::generate_xception(t_struct* tstruct) {
-  string name = tstruct->get_name();
-  string name_u = initial_caps_to_underscores(name);
-  string name_lc = to_lower_case(name_u);
-  string name_uc = to_upper_case(name_u);
-
-  generate_object(tstruct);
-
-  f_types_ << "/* exception */" << endl
-           << "typedef enum" << endl
-           << "{" << endl;
-  indent_up();
-  f_types_ << indent() << this->nspace_uc << name_uc << "_ERROR_CODE" << endl;
-  indent_down();
-  f_types_ << "} " << this->nspace << name << "Error;" << endl
-           << endl
-           << "GQuark " << this->nspace_lc << name_lc
-           << "_error_quark (void);" << endl
-           << "#define " << this->nspace_uc << name_uc << "_ERROR ("
-           << this->nspace_lc << name_lc << "_error_quark())" << endl
-           << endl
-           << endl;
-
-  f_types_impl_ << "/* define the GError domain for exceptions */" << endl << "#define "
-                << this->nspace_uc << name_uc << "_ERROR_DOMAIN \"" << this->nspace_lc << name_lc
-                << "_error_quark\"" << endl << "GQuark" << endl << this->nspace_lc << name_lc
-                << "_error_quark (void)" << endl << "{" << endl
-                << "  return g_quark_from_static_string (" << this->nspace_uc << name_uc
-                << "_ERROR_DOMAIN);" << endl << "}" << endl << endl;
-}
-
-/********************
- * HELPER FUNCTIONS *
- ********************/
-
-/**
- * Returns true if ttype is not a primitive.
- */
-bool t_c_glib_generator::is_complex_type(t_type* ttype) {
-  ttype = get_true_type(ttype);
-
-  return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
-}
-
-bool t_c_glib_generator::is_numeric(t_type* ttype) {
-  return ttype->is_enum() || (ttype->is_base_type() && !ttype->is_string());
-}
-
-/**
- * Maps a Thrift t_type to a C type.
- */
-string t_c_glib_generator::type_name(t_type* ttype, bool in_typedef, bool is_const) {
-  if (ttype->is_base_type()) {
-    string bname = base_type_name(ttype);
-
-    if (is_const) {
-      return "const " + bname;
-    } else {
-      return bname;
-    }
-  }
-
-  if (ttype->is_container()) {
-    string cname;
-
-    t_container* tcontainer = (t_container*)ttype;
-    if (tcontainer->has_cpp_name()) {
-      cname = tcontainer->get_cpp_name();
-    } else if (ttype->is_map()) {
-      cname = "GHashTable";
-    } else if (ttype->is_set()) {
-      // since a set requires unique elements, use a GHashTable, and
-      // populate the keys and values with the same data, using keys for
-      // the actual writes and reads.
-      // TODO: discuss whether or not to implement TSet, THashSet or GHashSet
-      cname = "GHashTable";
-    } else if (ttype->is_list()) {
-      t_type* etype = ((t_list*)ttype)->get_elem_type();
-      if (etype->is_void()) {
-        throw std::runtime_error("compiler error: list element type cannot be void");
-      }
-      // TODO: investigate other implementations besides GPtrArray
-      cname = is_numeric(etype) ? "GArray" : "GPtrArray";
-    }
-
-    /* Omit the dereference operator if we are aliasing this type within a
-       typedef, to allow the type to be used more naturally in client code;
-       otherwise, include it */
-    if (!in_typedef) {
-      cname += " *";
-    }
-
-    if (is_const) {
-      return "const " + cname;
-    } else {
-      return cname;
-    }
-  }
-
-  // check for a namespace
-  string pname = this->nspace + ttype->get_name();
-
-  if (is_complex_type(ttype)) {
-    pname += " *";
-  }
-
-  if (is_const) {
-    return "const " + pname;
-  } else {
-    return pname;
-  }
-}
-
-/**
- * Maps a Thrift primitive to the type needed to hold its value when used as an
- * object property.
- *
- * This method is needed because all integer properties of width less than 64
- * bits map to the same type, gint, as opposed to their width-specific type
- * (gint8, gint16 or gint32).
- */
-string t_c_glib_generator::property_type_name(t_type* ttype, bool in_typedef, bool is_const) {
-  string result;
-
-  if (ttype->is_base_type()) {
-    switch (((t_base_type*)ttype)->get_base()) {
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-      if (is_const) {
-        result = "const gint";
-      } else {
-        result = "gint";
-      }
-      break;
-
-    default:
-      result = type_name(ttype, in_typedef, is_const);
-    }
-  } else {
-    result = type_name(ttype, in_typedef, is_const);
-  }
-
-  return result;
-}
-
-/**
- * Maps a Thrift primitive to a C primitive.
- */
-string t_c_glib_generator::base_type_name(t_type* type) {
-  if (type->is_enum()) {
-    return type_name(type);
-  }
-  if (!type->is_base_type()) {
-    throw std::invalid_argument("Only base types are suppported.");
-  }
-  t_base_type* base_type = reinterpret_cast<t_base_type*>(type);
-  t_base_type::t_base tbase = base_type->get_base();
-  switch (tbase) {
-  case t_base_type::TYPE_VOID:
-    return "void";
-  case t_base_type::TYPE_STRING:
-    if (base_type->is_binary()) {
-      return "GByteArray *";
-    } else {
-      return "gchar *";
-    }
-  case t_base_type::TYPE_BOOL:
-    return "gboolean";
-  case t_base_type::TYPE_I8:
-    return "gint8";
-  case t_base_type::TYPE_I16:
-    return "gint16";
-  case t_base_type::TYPE_I32:
-    return "gint32";
-  case t_base_type::TYPE_I64:
-    return "gint64";
-  case t_base_type::TYPE_DOUBLE:
-    return "gdouble";
-  default:
-    throw std::logic_error("compiler error: no C base type name for base type "
-                           + t_base_type::t_base_name(tbase));
-  }
-}
-
-/**
- * Returns a member of the ThriftType C enumeration in thrift_protocol.h
- * for a Thrift type.
- */
-string t_c_glib_generator::type_to_enum(t_type* type) {
-  type = get_true_type(type);
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return "T_STRING";
-    case t_base_type::TYPE_BOOL:
-      return "T_BOOL";
-    case t_base_type::TYPE_I8:
-      return "T_BYTE";
-    case t_base_type::TYPE_I16:
-      return "T_I16";
-    case t_base_type::TYPE_I32:
-      return "T_I32";
-    case t_base_type::TYPE_I64:
-      return "T_I64";
-    case t_base_type::TYPE_DOUBLE:
-      return "T_DOUBLE";
-    }
-  } else if (type->is_enum()) {
-    return "T_I32";
-  } else if (type->is_struct()) {
-    return "T_STRUCT";
-  } else if (type->is_xception()) {
-    return "T_STRUCT";
-  } else if (type->is_map()) {
-    return "T_MAP";
-  } else if (type->is_set()) {
-    return "T_SET";
-  } else if (type->is_list()) {
-    return "T_LIST";
-  }
-
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
-}
-
-/**
- * Returns a Thrift constant formatted as a literal for inclusion in C code.
- */
-string t_c_glib_generator::constant_literal(t_type* type, t_const_value* value) {
-  ostringstream render;
-
-  if (type->is_base_type()) {
-    /* primitives */
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << "\"" + value->get_string() + "\"";
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() != 0) ? "TRUE" : "FALSE");
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      render << value->get_double();
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else {
-    t_const_value::t_const_value_type value_type = value->get_type();
-
-    switch (value_type) {
-    case t_const_value::CV_IDENTIFIER:
-      render << value->get_integer();
-      break;
-    case t_const_value::CV_LIST:
-      render << "{ ";
-      {
-        t_type* elem_type = ((t_list*)type)->get_elem_type();
-        const vector<t_const_value*>& list = value->get_list();
-        vector<t_const_value*>::const_iterator list_iter;
-
-        if (list.size() > 0) {
-          list_iter = list.begin();
-          render << constant_literal(elem_type, *list_iter);
-
-          while (++list_iter != list.end()) {
-            render << ", " << constant_literal(elem_type, *list_iter);
-          }
-        }
-      }
-      render << " }";
-      break;
-    case t_const_value::CV_MAP:
-    default:
-      render << "NULL /* not supported */";
-    }
-  }
-
-  return render.str();
-}
-
-/**
- * Returns C code that represents a Thrift constant.
- */
-string t_c_glib_generator::constant_value(string name, t_type* type, t_const_value* value) {
-  ostringstream render;
-
-  if (type->is_base_type()) {
-    /* primitives */
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_STRING:
-      render << "g_strdup (\"" + value->get_string() + "\")";
-      break;
-    case t_base_type::TYPE_BOOL:
-      render << ((value->get_integer() != 0) ? 1 : 0);
-      break;
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-      render << value->get_integer();
-      break;
-    case t_base_type::TYPE_I64:
-      render << "G_GINT64_CONSTANT (" << value->get_integer() << ")";
-      break;
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << value->get_integer();
-      } else {
-        render << value->get_double();
-      }
-      break;
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
-    }
-  } else if (type->is_enum()) {
-    render << "(" << type_name(type) << ")" << value->get_integer();
-  } else if (is_complex_type(type)) {
-    render << "(" << this->nspace_lc << to_lower_case(name) << "_constant())";
-  } else {
-    render << "NULL /* not supported */";
-  }
-
-  return render.str();
-}
-
-/**
- * Renders a function signature of the form 'type name(args)'
- *
- * @param tfunction Function definition
- * @return String of rendered function definition
- */
-string t_c_glib_generator::function_signature(t_function* tfunction) {
-  t_type* ttype = tfunction->get_returntype();
-  t_struct* arglist = tfunction->get_arglist();
-  t_struct* xlist = tfunction->get_xceptions();
-  string fname = initial_caps_to_underscores(tfunction->get_name());
-
-  bool has_return = !ttype->is_void();
-  bool has_args = arglist->get_members().size() == 0;
-  bool has_xceptions = xlist->get_members().size() == 0;
-  return "gboolean " + this->nspace_lc + fname + " (" + this->nspace + service_name_ + "If * iface"
-         + (has_return ? ", " + type_name(ttype) + "* _return" : "")
-         + (has_args ? "" : (", " + argument_list(arglist)))
-         + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError ** error)";
-}
-
-/**
- * Renders a field list
- *
- * @param tstruct The struct definition
- * @return Comma sepearated list of all field names in that struct
- */
-string t_c_glib_generator::argument_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    result += type_name((*f_iter)->get_type(), false, true) + " " + (*f_iter)->get_name();
-  }
-  return result;
-}
-
-/**
- * Renders mutable exception lists
- *
- * @param tstruct The struct definition
- * @return Comma sepearated list of all field names in that struct
- */
-string t_c_glib_generator::xception_list(t_struct* tstruct) {
-  string result = "";
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  bool first = true;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    if (first) {
-      first = false;
-    } else {
-      result += ", ";
-    }
-    result += type_name((*f_iter)->get_type(), false, false) + "* " + (*f_iter)->get_name();
-  }
-  return result;
-}
-
-/**
- * Declares a field, including any necessary initialization.
- */
-string t_c_glib_generator::declare_field(t_field* tfield,
-                                         bool init,
-                                         bool pointer,
-                                         bool constant,
-                                         bool reference) {
-  string result = "";
-  if (constant) {
-    result += "const ";
-  }
-  result += type_name(tfield->get_type());
-  if (pointer) {
-    result += "*";
-  }
-  if (reference) {
-    result += "*";
-  }
-  result += " " + tfield->get_name();
-  if (init) {
-    t_type* type = get_true_type(tfield->get_type());
-
-    if (type->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        break;
-      case t_base_type::TYPE_BOOL:
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-        result += " = 0";
-        break;
-      case t_base_type::TYPE_DOUBLE:
-        result += " = (gdouble) 0";
-        break;
-      case t_base_type::TYPE_STRING:
-        result += " = NULL";
-        break;
-      default:
-        throw "compiler error: no C intializer for base type " + t_base_type::t_base_name(tbase);
-      }
-    } else if (type->is_enum()) {
-      result += " = (" + type_name(type) + ") 0";
-    } else if (type->is_struct() || type->is_container()) {
-      result += " = NULL";
-    }
-  }
-
-  if (!reference) {
-    result += ";";
-  }
-
-  return result;
-}
-
-string t_c_glib_generator::constant_value_with_storage(string fname,
-                                                       t_type* etype,
-                                                       t_const_value* value) {
-  ostringstream render;
-  if (is_numeric(etype)) {
-    render << "    " << type_name(etype) << " *" << fname << " = "
-           << "g_new (" << base_type_name(etype) << ", 1);" << endl
-           << "    *" << fname << " = " << constant_value(fname, (t_type*)etype, value) << ";"
-           << endl;
-  } else {
-    render << "    " << type_name(etype) << " " << fname << " = "
-           << constant_value(fname, (t_type*)etype, value) << ";" << endl;
-  }
-  return render.str();
-}
-
-/**
- * Generates C code that initializes complex constants.
- */
-void t_c_glib_generator::generate_const_initializer(string name,
-                                                    t_type* type,
-                                                    t_const_value* value,
-                                                    bool top_level) {
-  string name_u = initial_caps_to_underscores(name);
-  string name_lc = to_lower_case(name_u);
-  string type_u = initial_caps_to_underscores(type->get_name());
-  string type_uc = to_upper_case(type_u);
-  string maybe_static = top_level ? "" : "static ";
-
-  if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    ostringstream initializers;
-
-    // initialize any constants that may be referenced by this initializer
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      string field_name = "";
-
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-          field_name = (*f_iter)->get_name();
-          break;
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field "
-          + v_iter->first->get_string();
-      }
-      field_name = tmp(field_name);
-
-      generate_const_initializer(name + "_constant_" + field_name,
-                                 field_type,
-                                 v_iter->second);
-      initializers << "    constant->" << v_iter->first->get_string() << " = "
-                   << constant_value(name + "_constant_" + field_name,
-                                     field_type,
-                                     v_iter->second) << ";" << endl
-                   << "    constant->__isset_" << v_iter->first->get_string()
-                   << " = TRUE;" << endl;
-    }
-
-    // implement the initializer
-    f_types_impl_ << maybe_static << this->nspace << type->get_name() << " *"
-                  << endl
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << indent() << "static " << this->nspace << type->get_name()
-                  << " *constant = NULL;" << endl
-                  << indent() << "if (constant == NULL)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << indent() << "constant = g_object_new (" << this->nspace_uc
-                  << "TYPE_" << type_uc << ", NULL);" << endl
-                  << initializers.str();
-    scope_down(f_types_impl_);
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      t_type* field_type = NULL;
-      string field_name = "";
-
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
-          field_type = (*f_iter)->get_type();
-          field_name = (*f_iter)->get_name();
-          break;
-        }
-      }
-      if (field_type == NULL) {
-        throw "type error: " + type->get_name() + " has no field "
-          + v_iter->first->get_string();
-      }
-      field_name = tmp(field_name);
-    }
-
-    f_types_impl_ << indent() << "return constant;" << endl;
-    scope_down(f_types_impl_);
-    f_types_impl_ << endl;
-  } else if (type->is_list()) {
-    string list_type = "GPtrArray *";
-    string free_func
-        = generate_free_func_from_type(reinterpret_cast<t_list*>(type)->get_elem_type());
-    string list_initializer = "g_ptr_array_new_with_free_func (" + free_func + ");";
-    string list_appender = "g_ptr_array_add";
-    bool list_variable = false;
-
-    t_type* etype = ((t_list*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    ostringstream initializers;
-    ostringstream appenders;
-
-    list_initializer = generate_new_array_from_type(etype);
-    if (etype->is_base_type()) {
-      t_base_type::t_base tbase = ((t_base_type*)etype)->get_base();
-      switch (tbase) {
-      case t_base_type::TYPE_VOID:
-        throw "compiler error: cannot determine array type";
-      case t_base_type::TYPE_BOOL:
-      case t_base_type::TYPE_I8:
-      case t_base_type::TYPE_I16:
-      case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_I64:
-      case t_base_type::TYPE_DOUBLE:
-        list_type = "GArray *";
-        list_appender = "g_array_append_val";
-        list_variable = true;
-        break;
-      case t_base_type::TYPE_STRING:
-        break;
-      default:
-        throw "compiler error: no array info for type";
-      }
-    } else if (etype->is_enum()) {
-      list_type = "GArray *";
-      list_appender = "g_array_append_val";
-      list_variable = true;
-    }
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string fname = tmp(name);
-
-      generate_const_initializer(fname, etype, (*v_iter));
-      if (list_variable) {
-        initializers << "    " << type_name(etype) << " " << fname << " = "
-                     << constant_value(fname, (t_type*)etype, (*v_iter)) << ";"
-                     << endl;
-        appenders << "    " << list_appender << "(constant, " << fname << ");"
-                  << endl;
-      } else {
-        appenders << "    " << list_appender << "(constant, "
-                  << constant_value(fname, (t_type*)etype, (*v_iter)) << ");"
-                  << endl;
-      }
-    }
-
-    f_types_impl_ << maybe_static << list_type << endl
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << indent() << "static " << list_type << " constant = NULL;"
-                  << endl
-                  << indent() << "if (constant == NULL)" << endl;
-    scope_up(f_types_impl_);
-    if (!initializers.str().empty()) {
-      f_types_impl_ << initializers.str()
-                    << endl;
-    }
-    f_types_impl_ << indent() << "constant = " << list_initializer << endl
-                  << appenders.str();
-    scope_down(f_types_impl_);
-    f_types_impl_ << indent() << "return constant;" << endl;
-    scope_down(f_types_impl_);
-    f_types_impl_ << endl;
-  } else if (type->is_set()) {
-    t_type* etype = ((t_set*)type)->get_elem_type();
-    const vector<t_const_value*>& val = value->get_list();
-    vector<t_const_value*>::const_iterator v_iter;
-    ostringstream initializers;
-    ostringstream appenders;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string fname = tmp(name);
-      string ptr = is_numeric(etype) ? "*" : "";
-      generate_const_initializer(fname, etype, (*v_iter));
-      initializers << constant_value_with_storage(fname, (t_type*)etype, *v_iter);
-      appenders << "    g_hash_table_insert (constant, " << fname << ", 0);" << endl;
-    }
-
-    f_types_impl_ << maybe_static << "GHashTable *" << endl
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl
-                  << indent() << "if (constant == NULL)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << initializers.str() << endl
-                  << indent() << "constant = " << generate_new_hash_from_type(etype, NULL) << endl
-                  << appenders.str();
-    scope_down(f_types_impl_);
-    f_types_impl_ << indent() << "return constant;" << endl;
-    scope_down(f_types_impl_);
-    f_types_impl_ << endl;
-  } else if (type->is_map()) {
-    t_type* ktype = ((t_map*)type)->get_key_type();
-    t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
-    ostringstream initializers;
-    ostringstream appenders;
-
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string fname = tmp(name);
-      string kname = fname + "key";
-      string vname = fname + "val";
-      generate_const_initializer(kname, ktype, v_iter->first);
-      generate_const_initializer(vname, vtype, v_iter->second);
-
-      initializers << constant_value_with_storage(kname, (t_type*)ktype, v_iter->first);
-      initializers << constant_value_with_storage(vname, (t_type*)vtype, v_iter->second);
-      appenders << "    g_hash_table_insert (constant, " << kname << ", " << vname << ");" << endl;
-    }
-
-    f_types_impl_ << maybe_static << "GHashTable *" << endl
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl
-                  << indent() << "if (constant == NULL)" << endl;
-    scope_up(f_types_impl_);
-    f_types_impl_ << initializers.str() << endl
-                  << indent() << "constant = " << generate_new_hash_from_type(ktype, vtype) << endl
-                  << appenders.str();
-    scope_down(f_types_impl_);
-    f_types_impl_ << indent() << "return constant;" << endl;
-    scope_down(f_types_impl_);
-    f_types_impl_ << endl;
-  }
-}
-
-/**
- * Generates helper classes for a service, consisting of a ThriftStruct subclass
- * for the arguments to and the result from each method.
- *
- * @param tservice The service for which to generate helper classes
- */
-void t_c_glib_generator::generate_service_helpers(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator function_iter;
-
-  // Iterate through the service's methods
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
-    string function_name = (*function_iter)->get_name();
-    t_struct* arg_list = (*function_iter)->get_arglist();
-    string arg_list_name_orig = arg_list->get_name();
-
-    // Generate the arguments class
-    arg_list->set_name(tservice->get_name() + underscores_to_initial_caps(function_name) + "Args");
-    generate_struct(arg_list);
-
-    arg_list->set_name(arg_list_name_orig);
-
-    // Generate the result class
-    if (!(*function_iter)->is_oneway()) {
-      t_struct result(program_,
-                      tservice->get_name() + underscores_to_initial_caps(function_name) + "Result");
-      t_field success((*function_iter)->get_returntype(), "success", 0);
-      success.set_req(t_field::T_OPTIONAL);
-      if (!(*function_iter)->get_returntype()->is_void()) {
-        result.append(&success);
-      }
-
-      t_struct* xs = (*function_iter)->get_xceptions();
-      const vector<t_field*>& fields = xs->get_members();
-      vector<t_field*>::const_iterator field_iter;
-      for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) {
-        (*field_iter)->set_req(t_field::T_OPTIONAL);
-        result.append(*field_iter);
-      }
-
-      generate_struct(&result);
-    }
-  }
-}
-
-/**
- * Generates C code that represents a Thrift service client.
- */
-void t_c_glib_generator::generate_service_client(t_service* tservice) {
-  /* get some C friendly service names */
-  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
-  string service_name_uc = to_upper_case(service_name_lc);
-
-  string parent_service_name;
-  string parent_service_name_lc;
-  string parent_service_name_uc;
-
-  string parent_class_name = "GObject";
-  string parent_type_name = "G_TYPE_OBJECT";
-
-  // The service this service extends, or NULL if it extends no
-  // service
-  t_service* extends_service = tservice->get_extends();
-  if (extends_service) {
-    // The name of the parent service
-    parent_service_name = extends_service->get_name();
-    parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
-    parent_service_name_uc = to_upper_case(parent_service_name_lc);
-
-    // The names of the client class' parent class and type
-    parent_class_name = this->nspace + parent_service_name + "Client";
-    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_CLIENT";
-  }
-
-  // The base service (the topmost in the "extends" hierarchy), on
-  // whose client class the "input_protocol" and "output_protocol"
-  // properties are defined
-  t_service* base_service = tservice;
-  while (base_service->get_extends()) {
-    base_service = base_service->get_extends();
-  }
-
-  string base_service_name = base_service->get_name();
-  string base_service_name_lc = to_lower_case(initial_caps_to_underscores(base_service_name));
-  string base_service_name_uc = to_upper_case(base_service_name_lc);
-
-  // Generate the client interface dummy object in the header.
-  f_header_ << "/* " << service_name_ << " service interface */" << endl << "typedef struct _"
-            << this->nspace << service_name_ << "If " << this->nspace << service_name_ << "If; "
-            << " /* dummy object */" << endl << endl;
-
-  // Generate the client interface object in the header.
-  f_header_ << "struct _" << this->nspace << service_name_ << "IfInterface" << endl << "{" << endl
-            << "  GTypeInterface parent;" << endl << endl;
-
-  /* write out the functions for this interface */
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    /* make the function name C friendly */
-    string funname = initial_caps_to_underscores((*f_iter)->get_name());
-    t_type* ttype = (*f_iter)->get_returntype();
-    t_struct* arglist = (*f_iter)->get_arglist();
-    t_struct* xlist = (*f_iter)->get_xceptions();
-    bool has_return = !ttype->is_void();
-    bool has_args = arglist->get_members().size() == 0;
-    bool has_xceptions = xlist->get_members().size() == 0;
-
-    string params = "(" + this->nspace + service_name_ + "If *iface"
-                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
-                    + (has_args ? "" : (", " + argument_list(arglist)))
-                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
-
-    indent(f_header_) << "gboolean (*" << funname << ") " << params << ";" << endl;
-  }
-  indent_down();
-
-  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "IfInterface "
-            << this->nspace << service_name_ << "IfInterface;" << endl << endl;
-
-  // generate all the interface boilerplate
-  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_if_get_type (void);" << endl
-            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF "
-            << "(" << this->nspace_lc << service_name_lc << "_if_get_type())" << endl << "#define "
-            << this->nspace_uc << service_name_uc << "_IF(obj) "
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_IF, " << this->nspace << service_name_ << "If))" << endl
-            << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_IF(obj) "
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_IF))" << endl << "#define " << this->nspace_uc
-            << service_name_uc << "_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), "
-            << this->nspace_uc << "TYPE_" << service_name_uc << "_IF, " << this->nspace
-            << service_name_ << "IfInterface))" << endl << endl;
-
-  // write out all the interface function prototypes
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    /* make the function name C friendly */
-    string funname = initial_caps_to_underscores((*f_iter)->get_name());
-    t_type* ttype = (*f_iter)->get_returntype();
-    t_struct* arglist = (*f_iter)->get_arglist();
-    t_struct* xlist = (*f_iter)->get_xceptions();
-    bool has_return = !ttype->is_void();
-    bool has_args = arglist->get_members().size() == 0;
-    bool has_xceptions = xlist->get_members().size() == 0;
-
-    string params = "(" + this->nspace + service_name_ + "If *iface"
-                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
-                    + (has_args ? "" : (", " + argument_list(arglist)))
-                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
-
-    f_header_ << "gboolean " << this->nspace_lc << service_name_lc << "_if_" << funname << " "
-              << params << ";" << endl;
-  }
-  f_header_ << endl;
-
-  // Generate the client object instance definition in the header.
-  f_header_ << "/* " << service_name_ << " service client */" << endl << "struct _" << this->nspace
-            << service_name_ << "Client" << endl << "{" << endl << "  " << parent_class_name
-            << " parent;" << endl;
-  if (!extends_service) {
-    // Define "input_protocol" and "output_protocol" properties only
-    // for base services; child service-client classes will inherit
-    // these
-    f_header_ << endl << "  ThriftProtocol *input_protocol;" << endl
-              << "  ThriftProtocol *output_protocol;" << endl;
-  }
-  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "Client "
-            << this->nspace << service_name_ << "Client;" << endl << endl;
-
-  // Generate the class definition in the header.
-  f_header_ << "struct _" << this->nspace << service_name_ << "ClientClass" << endl << "{" << endl
-            << "  " << parent_class_name << "Class parent;" << endl << "};" << endl
-            << "typedef struct _" << this->nspace << service_name_ << "ClientClass " << this->nspace
-            << service_name_ << "ClientClass;" << endl << endl;
-
-  // Create all the GObject boilerplate
-  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_client_get_type (void);" << endl
-            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT "
-            << "(" << this->nspace_lc << service_name_lc << "_client_get_type())" << endl
-            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT(obj) "
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "Client))" << endl
-            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT_CLASS(c) "
-            << "(G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
-            << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" << endl << "#define "
-            << this->nspace_uc << service_name_uc << "_IS_CLIENT(obj) "
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_CLIENT))" << endl << "#define " << this->nspace_uc
-            << service_name_uc << "_IS_CLIENT_CLASS(c) "
-            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
-            << "_CLIENT))" << endl << "#define " << this->nspace_uc << service_name_uc
-            << "_CLIENT_GET_CLASS(obj) "
-            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))"
-            << endl << endl;
-
-  /* write out the function prototypes */
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    /* make the function name C friendly */
-    string funname = to_lower_case(initial_caps_to_underscores((*f_iter)->get_name()));
-
-    t_function service_function((*f_iter)->get_returntype(),
-                                service_name_lc + string("_client_") + funname,
-                                (*f_iter)->get_arglist(),
-                                (*f_iter)->get_xceptions());
-    indent(f_header_) << function_signature(&service_function) << ";" << endl;
-
-    t_function send_function(g_type_void,
-                             service_name_lc + string("_client_send_") + funname,
-                             (*f_iter)->get_arglist());
-    indent(f_header_) << function_signature(&send_function) << ";" << endl;
-
-    // implement recv if not a oneway service
-    if (!(*f_iter)->is_oneway()) {
-      t_struct noargs(program_);
-      t_function recv_function((*f_iter)->get_returntype(),
-                               service_name_lc + string("_client_recv_") + funname,
-                               &noargs,
-                               (*f_iter)->get_xceptions());
-      indent(f_header_) << function_signature(&recv_function) << ";" << endl;
-    }
-  }
-
-  /* write out the get/set function prototypes */
-  f_header_ << "void " + service_name_lc + "_client_set_property (GObject *object, guint "
-                                           "property_id, const GValue *value, GParamSpec *pspec);"
-            << endl;
-  f_header_ << "void " + service_name_lc + "_client_get_property (GObject *object, guint "
-                                           "property_id, GValue *value, GParamSpec *pspec);"
-            << endl;
-
-  f_header_ << endl;
-  // end of header code
-
-  // Generate interface method implementations
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    /* make the function name C friendly */
-    string funname = initial_caps_to_underscores((*f_iter)->get_name());
-    t_type* ttype = (*f_iter)->get_returntype();
-    t_struct* arglist = (*f_iter)->get_arglist();
-    t_struct* xlist = (*f_iter)->get_xceptions();
-    bool has_return = !ttype->is_void();
-    bool has_args = arglist->get_members().size() == 0;
-    bool has_xceptions = xlist->get_members().size() == 0;
-
-    string params = "(" + this->nspace + service_name_ + "If *iface"
-                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
-                    + (has_args ? "" : (", " + argument_list(arglist)))
-                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
-
-    string params_without_type = string("iface, ") + (has_return ? "_return, " : "");
-
-    const vector<t_field*>& fields = arglist->get_members();
-    vector<t_field*>::const_iterator f_iter_field;
-    for (f_iter_field = fields.begin(); f_iter_field != fields.end(); ++f_iter_field) {
-      params_without_type += (*f_iter_field)->get_name();
-      params_without_type += ", ";
-    }
-
-    const vector<t_field*>& xceptions = xlist->get_members();
-    vector<t_field*>::const_iterator x_iter;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      params_without_type += (*x_iter)->get_name();
-      params_without_type += ", ";
-    }
-
-    f_service_ << "gboolean" << endl << this->nspace_lc << service_name_lc << "_if_" << funname
-               << " " << params << endl << "{" << endl << "  return " << this->nspace_uc
-               << service_name_uc << "_IF_GET_INTERFACE (iface)->" << funname << " ("
-               << params_without_type << "error);" << endl << "}" << endl << endl;
-  }
-
-  // Generate interface boilerplate
-  f_service_ << "GType" << endl << this->nspace_lc << service_name_lc << "_if_get_type (void)"
-             << endl << "{" << endl << "  static GType type = 0;" << endl << "  if (type == 0)"
-             << endl << "  {" << endl << "    static const GTypeInfo type_info =" << endl << "    {"
-             << endl << "      sizeof (" << this->nspace << service_name_ << "IfInterface)," << endl
-             << "      NULL,  /* base_init */" << endl << "      NULL,  /* base_finalize */" << endl
-             << "      NULL,  /* class_init */" << endl << "      NULL,  /* class_finalize */"
-             << endl << "      NULL,  /* class_data */" << endl
-             << "      0,     /* instance_size */" << endl << "      0,     /* n_preallocs */"
-             << endl << "      NULL,  /* instance_init */" << endl
-             << "      NULL   /* value_table */" << endl << "    };" << endl
-             << "    type = g_type_register_static (G_TYPE_INTERFACE," << endl
-             << "                                   \"" << this->nspace << service_name_ << "If\","
-             << endl << "                                   &type_info, 0);" << endl << "  }"
-             << endl << "  return type;" << endl << "}" << endl << endl;
-
-  // Generate client boilerplate
-  f_service_ << "static void " << endl << this->nspace_lc << service_name_lc
-             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
-             << endl << endl << "G_DEFINE_TYPE_WITH_CODE (" << this->nspace << service_name_
-             << "Client, " << this->nspace_lc << service_name_lc << "_client," << endl
-             << "                         " << parent_type_name << ", " << endl
-             << "                         G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
-             << service_name_uc << "_IF," << endl
-             << "                                                " << this->nspace_lc
-             << service_name_lc << "_if_interface_init))" << endl << endl;
-
-  // Generate property-related code only for base services---child
-  // service-client classes have only properties inherited from their
-  // parent class
-  if (!extends_service) {
-    // Generate client properties
-    f_service_ << "enum _" << this->nspace << service_name_ << "ClientProperties" << endl << "{"
-               << endl << "  PROP_0," << endl << "  PROP_" << this->nspace_uc << service_name_uc
-               << "_CLIENT_INPUT_PROTOCOL," << endl << "  PROP_" << this->nspace_uc
-               << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL" << endl << "};" << endl << endl;
-
-    // generate property setter
-    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_set_property ("
-               << "GObject *object, guint property_id, const GValue *value, "
-               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace
-               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc
-               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl
-               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_"
-               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl
-               << "      client->input_protocol = g_value_get_object (value);" << endl
-               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc
-               << "_CLIENT_OUTPUT_PROTOCOL:" << endl
-               << "      client->output_protocol = g_value_get_object (value);" << endl
-               << "      break;" << endl << "  }" << endl << "}" << endl << endl;
-
-    // generate property getter
-    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_get_property ("
-               << "GObject *object, guint property_id, GValue *value, "
-               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace
-               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc
-               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl
-               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_"
-               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl
-               << "      g_value_set_object (value, client->input_protocol);" << endl
-               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc
-               << "_CLIENT_OUTPUT_PROTOCOL:" << endl
-               << "      g_value_set_object (value, client->output_protocol);" << endl
-               << "      break;" << endl << "  }" << endl << "}" << endl << endl;
-  }
-
-  // Generate client method implementations
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    string name = (*f_iter)->get_name();
-    string funname = initial_caps_to_underscores(name);
-
-    // Get the struct of function call params and exceptions
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    // Function for sending
-    t_function send_function(g_type_void,
-                             service_name_lc + string("_client_send_") + funname,
-                             (*f_iter)->get_arglist());
-
-    // Open the send function
-    indent(f_service_) << function_signature(&send_function) << endl;
-    scope_up(f_service_);
-
-    string reqType = (*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL";
-
-    // Serialize the request
-    f_service_ << indent() << "gint32 cseqid = 0;" << endl << indent()
-               << "ThriftProtocol * protocol = " << this->nspace_uc << base_service_name_uc
-               << "_CLIENT (iface)->output_protocol;" << endl << endl << indent()
-               << "if (thrift_protocol_write_message_begin (protocol, \"" << name << "\", "
-               << reqType << ", cseqid, error) < 0)" << endl << indent() << "  return FALSE;"
-               << endl << endl;
-
-    generate_struct_writer(f_service_, arg_struct, "", "", false);
-
-    f_service_ << indent() << "if (thrift_protocol_write_message_end (protocol, error) < 0)" << endl
-               << indent() << "  return FALSE;" << endl << indent()
-               << "if (!thrift_transport_flush (protocol->transport, error))" << endl << indent()
-               << "  return FALSE;" << endl << indent()
-               << "if (!thrift_transport_write_end (protocol->transport, error))" << endl
-               << indent() << "  return FALSE;" << endl << endl << indent() << "return TRUE;"
-               << endl;
-
-    scope_down(f_service_);
-    f_service_ << endl;
-
-    // Generate recv function only if not an async function
-    if (!(*f_iter)->is_oneway()) {
-      t_struct noargs(program_);
-      t_function recv_function((*f_iter)->get_returntype(),
-                               service_name_lc + string("_client_recv_") + funname,
-                               &noargs,
-                               (*f_iter)->get_xceptions());
-      // Open function
-      indent(f_service_) << function_signature(&recv_function) << endl;
-      scope_up(f_service_);
-
-      f_service_ << indent() << "gint32 rseqid;" << endl
-                 << indent() << "gchar * fname = NULL;" << endl
-                 << indent() << "ThriftMessageType mtype;" << endl
-                 << indent() << "ThriftProtocol * protocol = "
-                 << this->nspace_uc << base_service_name_uc
-                 << "_CLIENT (iface)->input_protocol;" << endl
-                 << indent() << "ThriftApplicationException *xception;" << endl
-                 << endl
-                 << indent() << "if (thrift_protocol_read_message_begin "
-                    "(protocol, &fname, &mtype, &rseqid, error) < 0) {" << endl;
-      indent_up();
-      f_service_ << indent() << "if (fname) g_free (fname);" << endl
-                 << indent() << "return FALSE;" << endl;
-      indent_down();
-      f_service_ << indent() << "}" << endl
-                 << endl
-                 << indent() << "if (mtype == T_EXCEPTION) {" << endl;
-      indent_up();
-      f_service_ << indent() << "if (fname) g_free (fname);" << endl
-                 << indent() << "xception = g_object_new "
-                    "(THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);" << endl
-                 << indent() << "thrift_struct_read (THRIFT_STRUCT (xception), "
-                    "protocol, NULL);" << endl
-                 << indent() << "thrift_protocol_read_message_end "
-                    "(protocol, NULL);" << endl
-                 << indent() << "thrift_transport_read_end "
-                    "(protocol->transport, NULL);" << endl
-                 << indent() << "g_set_error (error, "
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR,xception->type, "
-                    "\"application error: %s\", xception->message);" << endl
-                 << indent() << "g_object_unref (xception);" << endl
-                 << indent() << "return FALSE;" << endl;
-      indent_down();
-      f_service_ << indent() << "} else if (mtype != T_REPLY) {" << endl;
-      indent_up();
-      f_service_ << indent() << "if (fname) g_free (fname);" << endl
-                 << indent() << "thrift_protocol_skip (protocol, T_STRUCT, "
-                    "NULL);" << endl
-                 << indent() << "thrift_protocol_read_message_end (protocol, "
-                    "NULL);" << endl
-                 << indent() << "thrift_transport_read_end ("
-                    "protocol->transport, NULL);" << endl
-                 << indent() << "g_set_error (error, "
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR, "
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, "
-                    "\"invalid message type %d, expected T_REPLY\", mtype);"
-                 << endl
-                 << indent() << "return FALSE;" << endl;
-      indent_down();
-      f_service_ << indent() << "} else if (strncmp (fname, \"" << name
-                 << "\", " << name.length() << ") != 0) {" << endl;
-      indent_up();
-      f_service_ << indent() << "thrift_protocol_skip (protocol, T_STRUCT, "
-                    "NULL);" << endl
-                 << indent() << "thrift_protocol_read_message_end (protocol,"
-                    "error);" << endl
-                 << indent() << "thrift_transport_read_end ("
-                    "protocol->transport, error);" << endl
-                 << indent() << "g_set_error (error, "
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR, "
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, "
-                    "\"wrong method name %s, expected " << name
-                    << "\", fname);" << endl
-                 << indent() << "if (fname) g_free (fname);" << endl
-                 << indent() << "return FALSE;" << endl;
-      indent_down();
-      f_service_ << indent() << "}" << endl
-                 << indent() << "if (fname) g_free (fname);" << endl
-                 << endl;
-
-      t_struct* xs = (*f_iter)->get_xceptions();
-      const std::vector<t_field*>& xceptions = xs->get_members();
-      vector<t_field*>::const_iterator x_iter;
-
-      {
-        t_struct result(program_, tservice->get_name() + "_" + (*f_iter)->get_name() + "_result");
-        t_field success((*f_iter)->get_returntype(), "*_return", 0);
-        if (!(*f_iter)->get_returntype()->is_void()) {
-          result.append(&success);
-        }
-
-        // add readers for exceptions, dereferencing the pointer.
-        for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) {
-          t_field* xception = new t_field((*x_iter)->get_type(),
-                                          "*" + (*x_iter)->get_name(),
-                                          (*x_iter)->get_key());
-          result.append(xception);
-        }
-
-        generate_struct_reader(f_service_, &result, "", "", false);
-      }
-
-      f_service_ << indent() << "if (thrift_protocol_read_message_end (protocol, error) < 0)"
-                 << endl << indent() << "  return FALSE;" << endl << endl << indent()
-                 << "if (!thrift_transport_read_end (protocol->transport, error))" << endl
-                 << indent() << "  return FALSE;" << endl << endl;
-
-      // copy over any throw exceptions and return failure
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) {
-        f_service_ << indent() << "if (*" << (*x_iter)->get_name() << " != NULL)" << endl
-                   << indent() << "{" << endl << indent() << "    g_set_error (error, "
-                   << this->nspace_uc
-                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name()))
-                   << "_ERROR, " << this->nspace_uc
-                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name()))
-                   << "_ERROR_CODE, \"" << (*x_iter)->get_type()->get_name() << "\");" << endl
-                   << indent() << "    return FALSE;" << endl << indent() << "}" << endl;
-      }
-      // Close function
-      indent(f_service_) << "return TRUE;" << endl;
-      scope_down(f_service_);
-      f_service_ << endl;
-    }
-
-    // Open function
-    t_function service_function((*f_iter)->get_returntype(),
-                                service_name_lc + string("_client_") + funname,
-                                (*f_iter)->get_arglist(),
-                                (*f_iter)->get_xceptions());
-    indent(f_service_) << function_signature(&service_function) << endl;
-    scope_up(f_service_);
-
-    // wrap each function
-    f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_send_"
-               << funname << " (iface";
-
-    // Declare the function arguments
-    const vector<t_field*>& fields = arg_struct->get_members();
-    vector<t_field*>::const_iterator fld_iter;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << ", " << (*fld_iter)->get_name();
-    }
-    f_service_ << ", error))" << endl << indent() << "  return FALSE;" << endl;
-
-    // if not oneway, implement recv
-    if (!(*f_iter)->is_oneway()) {
-      string ret = (*f_iter)->get_returntype()->is_void() ? "" : "_return, ";
-
-      const vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
-      vector<t_field*>::const_iterator x_iter;
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        ret += (*x_iter)->get_name();
-        ret += ", ";
-      }
-
-      f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_recv_"
-                 << funname << " (iface, " << ret << "error))" << endl << indent()
-                 << "  return FALSE;" << endl;
-    }
-
-    // return TRUE which means all functions were called OK
-    indent(f_service_) << "return TRUE;" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  // create the interface initializer
-  f_service_ << "static void" << endl
-             << this->nspace_lc << service_name_lc << "_if_interface_init ("
-             << this->nspace << service_name_ << "IfInterface *iface)" << endl;
-  scope_up(f_service_);
-  if (functions.size() > 0) {
-    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-      /* make the function name C friendly */
-      string funname = initial_caps_to_underscores((*f_iter)->get_name());
-
-      f_service_ << indent() << "iface->" << funname << " = " << this->nspace_lc
-                 << service_name_lc << "_client_" << funname << ";" << endl;
-    }
-  }
-  else {
-    f_service_ << indent() << "THRIFT_UNUSED_VAR (iface);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // create the client instance initializer
-  f_service_ << "static void" << endl
-             << this->nspace_lc << service_name_lc << "_client_init ("
-             << this->nspace << service_name_ << "Client *client)" << endl;
-  scope_up(f_service_);
-  if (!extends_service) {
-    f_service_ << indent() << "client->input_protocol = NULL;" << endl
-               << indent() << "client->output_protocol = NULL;" << endl;
-  }
-  else {
-    f_service_ << indent() << "THRIFT_UNUSED_VAR (client);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // create the client class initializer
-  f_service_ << "static void" << endl << this->nspace_lc << service_name_lc
-             << "_client_class_init (" << this->nspace << service_name_ << "ClientClass *cls)"
-             << endl << "{" << endl;
-  if (!extends_service) {
-    f_service_ << "  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl
-               << "  GParamSpec *param_spec;" << endl << endl
-               << "  gobject_class->set_property = " << this->nspace_lc << service_name_lc
-               << "_client_set_property;" << endl
-               << "  gobject_class->get_property = " << this->nspace_lc << service_name_lc
-               << "_client_get_property;" << endl << endl
-               << "  param_spec = g_param_spec_object (\"input_protocol\"," << endl
-               << "                                    \"input protocol (construct)\"," << endl
-               << "                                    \"Set the client input protocol\"," << endl
-               << "                                    THRIFT_TYPE_PROTOCOL," << endl
-               << "                                    G_PARAM_READWRITE);" << endl
-               << "  g_object_class_install_property (gobject_class," << endl
-               << "                                   PROP_" << this->nspace_uc << service_name_uc
-               << "_CLIENT_INPUT_PROTOCOL, param_spec);" << endl << endl
-               << "  param_spec = g_param_spec_object (\"output_protocol\"," << endl
-               << "                                    \"output protocol (construct)\"," << endl
-               << "                                    \"Set the client output protocol\"," << endl
-               << "                                    THRIFT_TYPE_PROTOCOL," << endl
-               << "                                    G_PARAM_READWRITE);" << endl
-               << "  g_object_class_install_property (gobject_class," << endl
-               << "                                   PROP_" << this->nspace_uc << service_name_uc
-               << "_CLIENT_OUTPUT_PROTOCOL, param_spec);" << endl;
-  }
-  else {
-    f_service_ << "  THRIFT_UNUSED_VAR (cls);" << endl;
-  }
-  f_service_ << "}" << endl << endl;
-}
-
-/**
- * Generates C code that represents a Thrift service handler.
- *
- * @param tservice The service for which to generate a handler.
- */
-void t_c_glib_generator::generate_service_handler(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator function_iter;
-
-  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
-  string service_name_uc = to_upper_case(service_name_lc);
-
-  string class_name = this->nspace + service_name_ + "Handler";
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
-  string class_name_uc = to_upper_case(class_name_lc);
-
-  string parent_class_name;
-  string parent_type_name;
-
-  string args_indent;
-
-  // The service this service extends, or NULL if it extends no service
-  t_service* extends_service = tservice->get_extends();
-
-  // Determine the name of our parent service (if any) and the handler class'
-  // parent class name and type
-  if (extends_service) {
-    string parent_service_name = extends_service->get_name();
-    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
-    string parent_service_name_uc = to_upper_case(parent_service_name_lc);
-
-    parent_class_name = this->nspace + parent_service_name + "Handler";
-    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_HANDLER";
-  } else {
-    parent_class_name = "GObject";
-    parent_type_name = "G_TYPE_OBJECT";
-  }
-
-  // Generate the handler class' definition in the header file
-
-  // Generate the handler instance definition
-  f_header_ << "/* " << service_name_ << " handler (abstract base class) */" << endl << "struct _"
-            << class_name << endl << "{" << endl;
-  indent_up();
-  f_header_ << indent() << parent_class_name << " parent;" << endl;
-  indent_down();
-  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl
-            << endl;
-
-  // Generate the handler class definition, including its class members
-  // (methods)
-  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl;
-  indent_up();
-  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl;
-
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
-    string method_name = initial_caps_to_underscores((*function_iter)->get_name());
-    t_type* return_type = (*function_iter)->get_returntype();
-    t_struct* arg_list = (*function_iter)->get_arglist();
-    t_struct* x_list = (*function_iter)->get_xceptions();
-    bool has_return = !return_type->is_void();
-    bool has_args = arg_list->get_members().size() == 0;
-    bool has_xceptions = x_list->get_members().size() == 0;
-
-    string params = "(" + this->nspace + service_name_ + "If *iface"
-                    + (has_return ? ", " + type_name(return_type) + "* _return" : "")
-                    + (has_args ? "" : (", " + argument_list(arg_list)))
-                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
-
-    indent(f_header_) << "gboolean (*" << method_name << ") " << params << ";" << endl;
-  }
-  indent_down();
-
-  f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name
-            << "Class;" << endl << endl;
-
-  // Generate the remaining header boilerplate
-  f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define "
-            << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER "
-            << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc
-            << "(obj) "
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_HANDLER, " << class_name << "))" << endl << "#define "
-            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER(obj) "
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_HANDLER))" << endl << "#define " << class_name_uc
-            << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << "#define "
-            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER_CLASS(c) "
-            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
-            << "_HANDLER))" << endl << "#define " << this->nspace_uc << service_name_uc
-            << "_HANDLER_GET_CLASS(obj) "
-            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
-            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << endl;
-
-  // Generate the handler class' method definitions
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
-    string method_name = initial_caps_to_underscores((*function_iter)->get_name());
-    t_type* return_type = (*function_iter)->get_returntype();
-    t_struct* arg_list = (*function_iter)->get_arglist();
-    t_struct* x_list = (*function_iter)->get_xceptions();
-    bool has_return = !return_type->is_void();
-    bool has_args = arg_list->get_members().size() == 0;
-    bool has_xceptions = x_list->get_members().size() == 0;
-
-    string params = "(" + this->nspace + service_name_ + "If *iface"
-                    + (has_return ? ", " + type_name(return_type) + "* _return" : "")
-                    + (has_args ? "" : (", " + argument_list(arg_list)))
-                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
-
-    f_header_ << "gboolean " << class_name_lc << "_" << method_name << " " << params << ";" << endl;
-  }
-  f_header_ << endl;
-
-  // Generate the handler's implementation in the implementation file
-
-  // Generate the implementation boilerplate
-  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc
-             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
-             << endl << endl;
-
-  args_indent = string(25, ' ');
-  f_service_ << "G_DEFINE_TYPE_WITH_CODE (" << class_name << ", " << endl << args_indent
-             << class_name_lc << "," << endl << args_indent << parent_type_name << "," << endl
-             << args_indent << "G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
-             << service_name_uc << "_IF," << endl;
-  args_indent += string(23, ' ');
-  f_service_ << args_indent << class_name_lc << "_" << service_name_lc << "_if_interface_init))"
-             << endl << endl;
-
-  // Generate the handler method implementations
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
-    string function_name = (*function_iter)->get_name();
-    string method_name = initial_caps_to_underscores(function_name);
-    t_type* return_type = (*function_iter)->get_returntype();
-    t_struct* arg_list = (*function_iter)->get_arglist();
-    t_struct* x_list = (*function_iter)->get_xceptions();
-
-    const vector<t_field*>& args = arg_list->get_members();
-    const vector<t_field*>& xceptions = x_list->get_members();
-
-    vector<t_field*>::const_iterator field_iter;
-
-    t_function implementing_function(return_type,
-                                     service_name_lc + "_handler_" + method_name,
-                                     arg_list,
-                                     x_list,
-                                     (*function_iter)->is_oneway());
-
-    indent(f_service_) << function_signature(&implementing_function) << endl;
-    scope_up(f_service_);
-    f_service_ << indent() << "g_return_val_if_fail (" << this->nspace_uc << "IS_"
-               << service_name_uc << "_HANDLER (iface), FALSE);" << endl << endl << indent()
-               << "return " << class_name_uc << "_GET_CLASS (iface)"
-               << "->" << method_name << " (iface, ";
-
-    if (!return_type->is_void()) {
-      f_service_ << "_return, ";
-    }
-    for (field_iter = args.begin(); field_iter != args.end(); ++field_iter) {
-      f_service_ << (*field_iter)->get_name() << ", ";
-    }
-    for (field_iter = xceptions.begin(); field_iter != xceptions.end(); ++field_iter) {
-      f_service_ << (*field_iter)->get_name() << ", ";
-    }
-    f_service_ << "error);" << endl;
-    scope_down(f_service_);
-    f_service_ << endl;
-  }
-
-  // Generate the handler interface initializer
-  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc
-             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)"
-             << endl;
-  scope_up(f_service_);
-  if (functions.size() > 0) {
-    for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
-      string method_name = initial_caps_to_underscores((*function_iter)->get_name());
-
-      f_service_ << indent() << "iface->" << method_name << " = " << class_name_lc << "_"
-                 << method_name << ";" << endl;
-    }
-  }
-  else {
-    f_service_ << "THRIFT_UNUSED_VAR (iface);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the handler instance initializer
-  f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)"
-             << endl;
-  scope_up(f_service_);
-  f_service_ << indent() << "THRIFT_UNUSED_VAR (self);" << endl;
-  scope_down(f_service_);
-  f_service_ << endl;
-
-  // Generate the handler class initializer
-  f_service_ << "static void" << endl
-             << class_name_lc << "_class_init (" << class_name << "Class *cls)"
-             << endl;
-  scope_up(f_service_);
-  if (functions.size() > 0) {
-    for (function_iter = functions.begin();
-         function_iter != functions.end();
-         ++function_iter) {
-      string function_name = (*function_iter)->get_name();
-      string method_name = initial_caps_to_underscores(function_name);
-
-      // All methods are pure virtual and must be implemented by subclasses
-      f_service_ << indent() << "cls->" << method_name << " = NULL;" << endl;
-    }
-  }
-  else {
-    f_service_ << indent() << "THRIFT_UNUSED_VAR (cls);" << endl;
-  }
-  scope_down(f_service_);
-  f_service_ << endl;
-}
-
-/**
- * Generates C code that represents a Thrift service processor.
- *
- * @param tservice The service for which to generate a processor
- */
-void t_c_glib_generator::generate_service_processor(t_service* tservice) {
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator function_iter;
-
-  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
-  string service_name_uc = to_upper_case(service_name_lc);
-
-  string class_name = this->nspace + service_name_ + "Processor";
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
-  string class_name_uc = to_upper_case(class_name_lc);
-
-  string parent_class_name;
-  string parent_type_name;
-
-  string handler_class_name = this->nspace + service_name_ + "Handler";
-  string handler_class_name_lc = initial_caps_to_underscores(handler_class_name);
-
-  string process_function_type_name = class_name + "ProcessFunction";
-  string process_function_def_type_name =
-    class_name_lc + "_process_function_def";
-
-  string function_name;
-  string args_indent;
-
-  // The service this service extends, or NULL if it extends no service
-  t_service* extends_service = tservice->get_extends();
-
-  // Determine the name of our parent service (if any) and the
-  // processor class' parent class name and type
-  if (extends_service) {
-    string parent_service_name = extends_service->get_name();
-    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
-    string parent_service_name_uc = to_upper_case(parent_service_name_lc);
-
-    parent_class_name = this->nspace + parent_service_name + "Processor";
-    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_PROCESSOR";
-  } else {
-    parent_class_name = "ThriftDispatchProcessor";
-    parent_type_name = "THRIFT_TYPE_DISPATCH_PROCESSOR";
-  }
-
-  // Generate the processor class' definition in the header file
-
-  // Generate the processor instance definition
-  f_header_ << "/* " << service_name_ << " processor */" << endl << "struct _" << class_name << endl
-            << "{" << endl;
-  indent_up();
-  f_header_ << indent() << parent_class_name << " parent;" << endl << endl << indent()
-            << "/* protected */" << endl << indent()
-            << this->nspace + service_name_ + "Handler *handler;" << endl << indent()
-            << "GHashTable *process_map;" << endl;
-  indent_down();
-  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl
-            << endl;
-
-  // Generate the processor class definition
-  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl;
-  indent_up();
-  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl << indent()
-            << "/* protected */" << endl << indent()
-            << "gboolea

<TRUNCATED>

[04/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_perl_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_perl_generator.cc b/compiler/cpp/src/thrift/generate/t_perl_generator.cc
new file mode 100644
index 0000000..bfe08f9
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_perl_generator.cc
@@ -0,0 +1,1648 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <list>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * PERL code generator.
+ *
+ */
+class t_perl_generator : public t_oop_generator {
+public:
+  t_perl_generator(t_program* program,
+                   const std::map<std::string, std::string>& parsed_options,
+                   const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option perl:" + iter->first;
+    }
+
+    out_dir_base_ = "gen-perl";
+    escape_['$'] = "\\$";
+    escape_['@'] = "\\@";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+  /**
+   * Structs!
+   */
+
+  void generate_perl_struct(t_struct* tstruct, bool is_exception);
+  void generate_perl_struct_definition(std::ofstream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false);
+  void generate_perl_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_perl_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_perl_function_helpers(t_function* tfunction);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_rest(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_processor(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool inclass = false);
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string perl_includes();
+  std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+
+  std::string autogen_comment() {
+    return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+           + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n";
+  }
+
+  void perl_namespace_dirs(t_program* p, std::list<std::string>& dirs) {
+    std::string ns = p->get_namespace("perl");
+    std::string::size_type loc;
+
+    if (ns.size() > 0) {
+      while ((loc = ns.find(".")) != std::string::npos) {
+        dirs.push_back(ns.substr(0, loc));
+        ns = ns.substr(loc + 1);
+      }
+    }
+
+    if (ns.size() > 0) {
+      dirs.push_back(ns);
+    }
+  }
+
+  std::string perl_namespace(t_program* p) {
+    std::string ns = p->get_namespace("perl");
+    std::string result = "";
+    std::string::size_type loc;
+
+    if (ns.size() > 0) {
+      while ((loc = ns.find(".")) != std::string::npos) {
+        result += ns.substr(0, loc);
+        result += "::";
+        ns = ns.substr(loc + 1);
+      }
+
+      if (ns.size() > 0) {
+        result += ns + "::";
+      }
+    }
+
+    return result;
+  }
+
+  std::string get_namespace_out_dir() {
+    std::string outdir = get_out_dir();
+    std::list<std::string> dirs;
+    perl_namespace_dirs(program_, dirs);
+    std::list<std::string>::iterator it;
+    for (it = dirs.begin(); it != dirs.end(); it++) {
+      outdir += *it + "/";
+    }
+    return outdir;
+  }
+
+private:
+  /**
+   * File streams
+   */
+  std::ofstream f_types_;
+  std::ofstream f_consts_;
+  std::ofstream f_helpers_;
+  std::ofstream f_service_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_perl_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  string outdir = get_out_dir();
+  std::list<std::string> dirs;
+  perl_namespace_dirs(program_, dirs);
+  std::list<std::string>::iterator it;
+  for (it = dirs.begin(); it != dirs.end(); it++) {
+    outdir += *it + "/";
+    MKDIR(outdir.c_str());
+  }
+
+  // Make output file
+  string f_types_name = outdir + "Types.pm";
+  f_types_.open(f_types_name.c_str());
+  string f_consts_name = outdir + "Constants.pm";
+  f_consts_.open(f_consts_name.c_str());
+
+  // Print header
+  f_types_ << autogen_comment() << perl_includes();
+
+  // Print header
+  f_consts_ << autogen_comment() << "package " << perl_namespace(program_) << "Constants;" << endl
+            << perl_includes() << endl;
+}
+
+/**
+ * Prints standard java imports
+ */
+string t_perl_generator::perl_includes() {
+  string inc;
+
+  inc = "require 5.6.0;\n";
+  inc += "use strict;\n";
+  inc += "use warnings;\n";
+  inc += "use Thrift;\n\n";
+
+  return inc;
+}
+
+/**
+ * Close up (or down) some filez.
+ */
+void t_perl_generator::close_generator() {
+  // Close types file
+  f_types_ << "1;" << endl;
+  f_types_.close();
+
+  f_consts_ << "1;" << endl;
+  f_consts_.close();
+}
+
+/**
+ * Generates a typedef. This is not done in PERL, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_perl_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Generates code for an enumerated type. Since define is expensive to lookup
+ * in PERL, we use a global array for this.
+ *
+ * @param tenum The enumeration
+ */
+void t_perl_generator::generate_enum(t_enum* tenum) {
+  f_types_ << "package " << perl_namespace(program_) << tenum->get_name() << ";" << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    f_types_ << "use constant " << (*c_iter)->get_name() << " => " << value << ";" << endl;
+  }
+}
+
+/**
+ * Generate a constant value
+ */
+void t_perl_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  f_consts_ << "use constant " << name << " => ";
+  f_consts_ << render_const_value(type, value);
+  f_consts_ << ";" << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_perl_generator::render_const_value(t_type* type, t_const_value* value) {
+  std::ostringstream out;
+
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "1" : "0");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    out << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << "new " << perl_namespace(type->get_program()) << type->get_name() << "({" << endl;
+    indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      out << render_const_value(g_type_string, v_iter->first);
+      out << " => ";
+      out << render_const_value(field_type, v_iter->second);
+      out << ",";
+      out << endl;
+    }
+
+    out << "})";
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    out << "{" << endl;
+
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << render_const_value(ktype, v_iter->first);
+      out << " => ";
+      out << render_const_value(vtype, v_iter->second);
+      out << "," << endl;
+    }
+
+    out << "}";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    out << "[" << endl;
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+
+      out << render_const_value(etype, *v_iter);
+      if (type->is_set()) {
+        out << " => 1";
+      }
+      out << "," << endl;
+    }
+    out << "]";
+  }
+  return out.str();
+}
+
+/**
+ * Make a struct
+ */
+void t_perl_generator::generate_struct(t_struct* tstruct) {
+  generate_perl_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_perl_generator::generate_xception(t_struct* txception) {
+  generate_perl_struct(txception, true);
+}
+
+/**
+ * Structs can be normal or exceptions.
+ */
+void t_perl_generator::generate_perl_struct(t_struct* tstruct, bool is_exception) {
+  generate_perl_struct_definition(f_types_, tstruct, is_exception);
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is nothing in PERL
+ * where the objects are all just associative arrays (unless of course we
+ * decide to start using objects for them...)
+ *
+ * @param tstruct The struct definition
+ */
+void t_perl_generator::generate_perl_struct_definition(ofstream& out,
+                                                       t_struct* tstruct,
+                                                       bool is_exception) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << "package " << perl_namespace(tstruct->get_program()) << tstruct->get_name() << ";\n";
+  if (is_exception) {
+    out << "use base qw(Thrift::TException);\n";
+  }
+
+  // Create simple acessor methods
+  out << "use base qw(Class::Accessor);\n";
+
+  if (members.size() > 0) {
+    out << perl_namespace(tstruct->get_program()) << tstruct->get_name() << "->mk_accessors( qw( ";
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      if (!t->is_xception()) {
+        out << (*m_iter)->get_name() << " ";
+      }
+    }
+
+    out << ") );\n";
+  }
+
+  out << endl;
+
+  // new()
+  indent_up();
+  out << "sub new {" << endl << indent() << "my $classname = shift;" << endl << indent()
+      << "my $self      = {};" << endl << indent() << "my $vals      = shift || {};" << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    string dval = "undef";
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
+      dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
+    }
+    out << indent() << "$self->{" << (*m_iter)->get_name() << "} = " << dval << ";" << endl;
+  }
+
+  // Generate constructor from array
+  if (members.size() > 0) {
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->get_type());
+      if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
+        indent(out) << "$self->{" << (*m_iter)->get_name()
+                    << "} = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
+      }
+    }
+
+    out << indent() << "if (UNIVERSAL::isa($vals,'HASH')) {" << endl;
+    indent_up();
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << indent() << "if (defined $vals->{" << (*m_iter)->get_name() << "}) {" << endl
+          << indent() << "  $self->{" << (*m_iter)->get_name() << "} = $vals->{"
+          << (*m_iter)->get_name() << "};" << endl << indent() << "}" << endl;
+    }
+    indent_down();
+    out << indent() << "}" << endl;
+  }
+
+  out << indent() << "return bless ($self, $classname);" << endl;
+  indent_down();
+  out << "}\n\n";
+
+  out << "sub getName {" << endl << indent() << "  return '" << tstruct->get_name() << "';" << endl
+      << indent() << "}" << endl << endl;
+
+  generate_perl_struct_reader(out, tstruct);
+  generate_perl_struct_writer(out, tstruct);
+}
+
+/**
+ * Generates the read() method for a struct
+ */
+void t_perl_generator::generate_perl_struct_reader(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << "sub read {" << endl;
+
+  indent_up();
+
+  out << indent() << "my ($self, $input) = @_;" << endl << indent() << "my $xfer  = 0;" << endl
+      << indent() << "my $fname;" << endl << indent() << "my $ftype = 0;" << endl << indent()
+      << "my $fid   = 0;" << endl;
+
+  indent(out) << "$xfer += $input->readStructBegin(\\$fname);" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (1) " << endl;
+
+  scope_up(out);
+
+  indent(out) << "$xfer += $input->readFieldBegin(\\$fname, \\$ftype, \\$fid);" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if ($ftype == TType::STOP) {" << endl;
+  indent_up();
+  indent(out) << "last;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "SWITCH: for($fid)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+
+    indent(out) << "/^" << (*f_iter)->get_key() << "$/ && do{";
+    indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+
+    indent_up();
+    generate_deserialize_field(out, *f_iter, "self->");
+    indent_down();
+
+    indent(out) << "} else {" << endl;
+
+    indent(out) << "  $xfer += $input->skip($ftype);" << endl;
+
+    out << indent() << "}" << endl << indent() << "last; };" << endl;
+  }
+  // In the default case we skip the field
+
+  indent(out) << "  $xfer += $input->skip($ftype);" << endl;
+
+  scope_down(out);
+
+  indent(out) << "$xfer += $input->readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  indent(out) << "$xfer += $input->readStructEnd();" << endl;
+
+  indent(out) << "return $xfer;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates the write() method for a struct
+ */
+void t_perl_generator::generate_perl_struct_writer(ofstream& out, t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << "sub write {" << endl;
+
+  indent_up();
+  indent(out) << "my ($self, $output) = @_;" << endl;
+  indent(out) << "my $xfer   = 0;" << endl;
+
+  indent(out) << "$xfer += $output->writeStructBegin('" << name << "');" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out << indent() << "if (defined $self->{" << (*f_iter)->get_name() << "}) {" << endl;
+    indent_up();
+
+    indent(out) << "$xfer += $output->writeFieldBegin("
+                << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type())
+                << ", " << (*f_iter)->get_key() << ");" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "self->");
+
+    indent(out) << "$xfer += $output->writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}" << endl;
+  }
+
+  out << indent() << "$xfer += $output->writeFieldStop();" << endl << indent()
+      << "$xfer += $output->writeStructEnd();" << endl;
+
+  out << indent() << "return $xfer;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_perl_generator::generate_service(t_service* tservice) {
+  string f_service_name = get_namespace_out_dir() + service_name_ + ".pm";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ <<
+      ///      "package "<<service_name_<<";"<<endl<<
+      autogen_comment() << perl_includes();
+
+  f_service_ << "use " << perl_namespace(tservice->get_program()) << "Types;" << endl;
+
+  t_service* extends_s = tservice->get_extends();
+  if (extends_s != NULL) {
+    f_service_ << "use " << perl_namespace(extends_s->get_program()) << extends_s->get_name() << ";"
+               << endl;
+  }
+
+  f_service_ << endl;
+
+  // Generate the three main parts of the service (well, two for now in PERL)
+  generate_service_helpers(tservice);
+  generate_service_interface(tservice);
+  generate_service_rest(tservice);
+  generate_service_client(tservice);
+  generate_service_processor(tservice);
+
+  // Close service file
+  f_service_ << "1;" << endl;
+  f_service_.close();
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_perl_generator::generate_service_processor(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  t_service* extends_s = tservice->get_extends();
+  if (extends_s != NULL) {
+    extends = perl_namespace(extends_s->get_program()) + extends_s->get_name();
+    extends_processor = "use base qw(" + extends + "Processor);";
+  }
+
+  indent_up();
+
+  // Generate the header portion
+  f_service_ << "package " << perl_namespace(program_) << service_name_ << "Processor;" << endl
+             << endl << "use strict;" << endl << extends_processor << endl << endl;
+
+  if (extends.empty()) {
+    f_service_ << "sub new {" << endl;
+
+    indent_up();
+
+    f_service_ << indent() << "my ($classname, $handler) = @_;" << endl << indent()
+               << "my $self      = {};" << endl;
+
+    f_service_ << indent() << "$self->{handler} = $handler;" << endl;
+
+    f_service_ << indent() << "return bless ($self, $classname);" << endl;
+
+    indent_down();
+
+    f_service_ << "}" << endl << endl;
+  }
+
+  // Generate the server implementation
+  f_service_ << "sub process {" << endl;
+  indent_up();
+
+  f_service_ << indent() << "my ($self, $input, $output) = @_;" << endl;
+
+  f_service_ << indent() << "my $rseqid = 0;" << endl << indent() << "my $fname  = undef;" << endl
+             << indent() << "my $mtype  = 0;" << endl << endl;
+
+  f_service_ << indent() << "$input->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);" << endl;
+
+  // HOT: check for method implementation
+  f_service_ << indent() << "my $methodname = 'process_'.$fname;" << endl << indent()
+             << "if (!$self->can($methodname)) {" << endl;
+  indent_up();
+
+  f_service_ << indent() << "$input->skip(TType::STRUCT);" << endl << indent()
+             << "$input->readMessageEnd();" << endl << indent()
+             << "my $x = new TApplicationException('Function '.$fname.' not implemented.', "
+                "TApplicationException::UNKNOWN_METHOD);" << endl << indent()
+             << "$output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);" << endl
+             << indent() << "$x->write($output);" << endl << indent()
+             << "$output->writeMessageEnd();" << endl << indent()
+             << "$output->getTransport()->flush();" << endl << indent() << "return;" << endl;
+
+  indent_down();
+  f_service_ << indent() << "}" << endl << indent()
+             << "$self->$methodname($rseqid, $input, $output);" << endl << indent() << "return 1;"
+             << endl;
+
+  indent_down();
+
+  f_service_ << "}" << endl << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_perl_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  // Open function
+  f_service_ << "sub process_" << tfunction->get_name() << " {" << endl;
+
+  indent_up();
+
+  f_service_ << indent() << "my ($self, $seqid, $input, $output) = @_;" << endl;
+
+  string argsname = perl_namespace(tservice->get_program()) + service_name_ + "_"
+                    + tfunction->get_name() + "_args";
+  string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_"
+                      + tfunction->get_name() + "_result";
+
+  f_service_ << indent() << "my $args = new " << argsname << "();" << endl << indent()
+             << "$args->read($input);" << endl;
+
+  f_service_ << indent() << "$input->readMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "my $result = new " << resultname << "();" << endl;
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "eval {" << endl;
+    indent_up();
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "$result->{success} = ";
+  }
+  f_service_ << "$self->{handler}->" << tfunction->get_name() << "(";
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_service_ << ", ";
+    }
+    f_service_ << "$args->" << (*f_iter)->get_name();
+  }
+  f_service_ << ");" << endl;
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    indent_down();
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << indent() << "}; if( UNIVERSAL::isa($@,'"
+                 << perl_namespace((*x_iter)->get_type()->get_program())
+                 << (*x_iter)->get_type()->get_name() << "') ){ " << endl;
+
+      indent_up();
+      f_service_ << indent() << "$result->{" << (*x_iter)->get_name() << "} = $@;" << endl;
+      f_service_ << indent() << "$@ = undef;" << endl;
+      indent_down();
+      f_service_ << indent();
+    }
+    f_service_ << "}" << endl;
+
+    // catch-all for unexpected exceptions (THRIFT-3191)
+    f_service_ << indent() << "if ($@) {" << endl;
+    indent_up();
+    f_service_ << indent() << "$@ =~ s/^\\s+|\\s+$//g;" << endl
+               << indent() << "my $err = new TApplicationException(\"Unexpected Exception: \" . $@, TApplicationException::INTERNAL_ERROR);" << endl
+               << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', TMessageType::EXCEPTION, $seqid);" << endl
+               << indent() << "$err->write($output);" << endl
+               << indent() << "$output->writeMessageEnd();" << endl
+               << indent() << "$output->getTransport()->flush();" << endl
+               << indent() << "$@ = undef;" << endl
+               << indent() << "return;" << endl;
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "return;" << endl;
+    indent_down();
+    f_service_ << "}" << endl;
+    return;
+  }
+
+  // Serialize the reply
+  f_service_ << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', TMessageType::REPLY, $seqid);" << endl
+             << indent() << "$result->write($output);" << endl
+             << indent() << "$output->writeMessageEnd();" << endl
+             << indent() << "$output->getTransport()->flush();" << endl;
+
+  // Close function
+  indent_down();
+  f_service_ << "}" << endl << endl;
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_perl_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  f_service_ << "# HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    string name = ts->get_name();
+    ts->set_name(service_name_ + "_" + name);
+    generate_perl_struct_definition(f_service_, ts, false);
+    generate_perl_function_helpers(*f_iter);
+    ts->set_name(name);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_perl_generator::generate_perl_function_helpers(t_function* tfunction) {
+  t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_perl_struct_definition(f_service_, &result, false);
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_perl_generator::generate_service_interface(t_service* tservice) {
+  string extends_if = "";
+  t_service* extends_s = tservice->get_extends();
+  if (extends_s != NULL) {
+    extends_if = "use base qw(" + perl_namespace(extends_s->get_program()) + extends_s->get_name()
+                 + "If);";
+  }
+
+  f_service_ << "package " << perl_namespace(program_) << service_name_ << "If;" << endl << endl
+             << "use strict;" << endl << extends_if << endl << endl;
+
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << "sub " << function_signature(*f_iter) << endl << "  die 'implement interface';\n}"
+               << endl << endl;
+  }
+  indent_down();
+}
+
+/**
+ * Generates a REST interface
+ */
+void t_perl_generator::generate_service_rest(t_service* tservice) {
+  string extends = "";
+  string extends_if = "";
+  t_service* extends_s = tservice->get_extends();
+  if (extends_s != NULL) {
+    extends = extends_s->get_name();
+    extends_if = "use base qw(" + perl_namespace(extends_s->get_program()) + extends_s->get_name()
+                 + "Rest);";
+  }
+  f_service_ << "package " << perl_namespace(program_) << service_name_ << "Rest;" << endl << endl
+             << "use strict;" << endl << extends_if << endl << endl;
+
+  if (extends.empty()) {
+    f_service_ << "sub new {" << endl;
+
+    indent_up();
+
+    f_service_ << indent() << "my ($classname, $impl) = @_;" << endl << indent()
+               << "my $self     ={ impl => $impl };" << endl << endl << indent()
+               << "return bless($self,$classname);" << endl;
+
+    indent_down();
+
+    f_service_ << "}" << endl << endl;
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << "sub " << (*f_iter)->get_name() << "{" << endl;
+
+    indent_up();
+
+    f_service_ << indent() << "my ($self, $request) = @_;" << endl << endl;
+
+    const vector<t_field*>& args = (*f_iter)->get_arglist()->get_members();
+    vector<t_field*>::const_iterator a_iter;
+    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+      t_type* atype = get_true_type((*a_iter)->get_type());
+      string req = "$request->{'" + (*a_iter)->get_name() + "'}";
+      f_service_ << indent() << "my $" << (*a_iter)->get_name() << " = (" << req << ") ? " << req
+                 << " : undef;" << endl;
+      if (atype->is_string() && ((t_base_type*)atype)->is_string_list()) {
+        f_service_ << indent() << "my @" << (*a_iter)->get_name() << " = split(/,/, $"
+                   << (*a_iter)->get_name() << ");" << endl << indent() << "$"
+                   << (*a_iter)->get_name() << " = \\@" << (*a_iter)->get_name() << endl;
+      }
+    }
+    f_service_ << indent() << "return $self->{impl}->" << (*f_iter)->get_name() << "("
+               << argument_list((*f_iter)->get_arglist()) << ");" << endl;
+    indent_down();
+    indent(f_service_) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_perl_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  t_service* extends_s = tservice->get_extends();
+  if (extends_s != NULL) {
+    extends = perl_namespace(extends_s->get_program()) + extends_s->get_name();
+    extends_client = "use base qw(" + extends + "Client);";
+  }
+
+  f_service_ << "package " << perl_namespace(program_) << service_name_ << "Client;" << endl << endl
+             << extends_client << endl << "use base qw(" << perl_namespace(program_)
+             << service_name_ << "If);" << endl;
+
+  // Constructor function
+  f_service_ << "sub new {" << endl;
+
+  indent_up();
+
+  f_service_ << indent() << "my ($classname, $input, $output) = @_;" << endl << indent()
+             << "my $self      = {};" << endl;
+
+  if (!extends.empty()) {
+    f_service_ << indent() << "$self = $classname->SUPER::new($input, $output);" << endl;
+  } else {
+    f_service_ << indent() << "$self->{input}  = $input;" << endl << indent()
+               << "$self->{output} = defined $output ? $output : $input;" << endl << indent()
+               << "$self->{seqid}  = 0;" << endl;
+  }
+
+  f_service_ << indent() << "return bless($self,$classname);" << endl;
+
+  indent_down();
+
+  f_service_ << "}" << endl << endl;
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    f_service_ << "sub " << function_signature(*f_iter) << endl;
+
+    indent_up();
+
+    indent(f_service_) << indent() << "$self->send_" << funname << "(";
+
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "$" << (*fld_iter)->get_name();
+    }
+    f_service_ << ");" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "$self->recv_" << funname << "();" << endl;
+    }
+
+    indent_down();
+
+    f_service_ << "}" << endl << endl;
+
+    f_service_ << "sub send_" << function_signature(*f_iter) << endl;
+
+    indent_up();
+
+    std::string argsname = perl_namespace(tservice->get_program()) + service_name_ + "_"
+                           + (*f_iter)->get_name() + "_args";
+
+    // Serialize the request header
+    f_service_ << indent() << "$self->{output}->writeMessageBegin('" << (*f_iter)->get_name()
+               << "', " << ((*f_iter)->is_oneway() ? "TMessageType::ONEWAY" : "TMessageType::CALL")
+               << ", $self->{seqid});" << endl;
+
+    f_service_ << indent() << "my $args = new " << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "$args->{" << (*fld_iter)->get_name() << "} = $"
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    // Write to the stream
+    f_service_ << indent() << "$args->write($self->{output});" << endl << indent()
+               << "$self->{output}->writeMessageEnd();" << endl << indent()
+               << "$self->{output}->getTransport()->flush();" << endl;
+
+    indent_down();
+
+    f_service_ << "}" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_"
+                               + (*f_iter)->get_name() + "_result";
+      t_struct noargs(program_);
+
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs);
+      // Open function
+      f_service_ << endl << "sub " << function_signature(&recv_function) << endl;
+
+      indent_up();
+
+      f_service_ << indent() << "my $rseqid = 0;" << endl << indent() << "my $fname;" << endl
+                 << indent() << "my $mtype = 0;" << endl << endl;
+
+      f_service_ << indent() << "$self->{input}->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);"
+                 << endl << indent() << "if ($mtype == TMessageType::EXCEPTION) {" << endl
+                 << indent() << "  my $x = new TApplicationException();" << endl << indent()
+                 << "  $x->read($self->{input});" << endl << indent()
+                 << "  $self->{input}->readMessageEnd();" << endl << indent() << "  die $x;" << endl
+                 << indent() << "}" << endl;
+
+      f_service_ << indent() << "my $result = new " << resultname << "();" << endl << indent()
+                 << "$result->read($self->{input});" << endl;
+
+      f_service_ << indent() << "$self->{input}->readMessageEnd();" << endl << endl;
+
+      // Careful, only return result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (defined $result->{success} ) {" << endl << indent()
+                   << "  return $result->{success};" << endl << indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "if (defined $result->{" << (*x_iter)->get_name() << "}) {"
+                   << endl << indent() << "  die $result->{" << (*x_iter)->get_name() << "};"
+                   << endl << indent() << "}" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return;" << endl;
+      } else {
+        f_service_ << indent() << "die \"" << (*f_iter)->get_name() << " failed: unknown result\";"
+                   << endl;
+      }
+
+      // Close function
+      indent_down();
+      f_service_ << "}" << endl;
+    }
+  }
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_perl_generator::generate_deserialize_field(ofstream& out,
+                                                  t_field* tfield,
+                                                  string prefix,
+                                                  bool inclass) {
+  (void)inclass;
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = tfield->get_name();
+
+  // Hack for when prefix is defined (always a hash ref)
+  if (!prefix.empty()) {
+    name = prefix + "{" + tfield->get_name() + "}";
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << "$xfer += $input->";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << "readString(\\$" << name << ");";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool(\\$" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte(\\$" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16(\\$" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32(\\$" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64(\\$" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble(\\$" << name << ");";
+        break;
+      default:
+        throw "compiler error: no PERL name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32(\\$" << name << ");";
+    }
+    out << endl;
+
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a variable. This makes two key assumptions,
+ * first that there is a const char* variable named data that points to the
+ * buffer for deserialization, and that there is a variable protocol which
+ * is a reference to a TProtocol serialization object.
+ */
+void t_perl_generator::generate_deserialize_struct(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   string prefix) {
+  out << indent() << "$" << prefix << " = new " << perl_namespace(tstruct->get_program())
+      << tstruct->get_name() << "();" << endl << indent() << "$xfer += $" << prefix
+      << "->read($input);" << endl;
+}
+
+void t_perl_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_i8, ktype);
+  t_field fvtype(g_type_i8, vtype);
+  t_field fetype(g_type_i8, etype);
+
+  out << indent() << "my $" << size << " = 0;" << endl;
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << ktype << " = 0;"
+        << endl << indent() << "my $" << vtype << " = 0;" << endl;
+
+    out << indent() << "$xfer += $input->readMapBegin("
+        << "\\$" << ktype << ", \\$" << vtype << ", \\$" << size << ");" << endl;
+
+  } else if (ttype->is_set()) {
+
+    out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << etype << " = 0;"
+        << endl << indent() << "$xfer += $input->readSetBegin("
+        << "\\$" << etype << ", \\$" << size << ");" << endl;
+
+  } else if (ttype->is_list()) {
+
+    out << indent() << "$" << prefix << " = [];" << endl << indent() << "my $" << etype << " = 0;"
+        << endl << indent() << "$xfer += $input->readListBegin("
+        << "\\$" << etype << ", \\$" << size << ");" << endl;
+  }
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for (my $" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")"
+              << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "$xfer += $input->readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "$xfer += $input->readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "$xfer += $input->readListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_perl_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+  string key = tmp("key");
+  string val = tmp("val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey, true, true) << endl;
+  indent(out) << declare_field(&fval, true, true) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << "$" << prefix << "->{$" << key << "} = $" << val << ";" << endl;
+}
+
+void t_perl_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+  string elem = tmp("elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << "my $" << elem << " = undef;" << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << "$" << prefix << "->{$" << elem << "} = 1;" << endl;
+}
+
+void t_perl_generator::generate_deserialize_list_element(ofstream& out,
+                                                         t_list* tlist,
+                                                         string prefix) {
+  string elem = tmp("elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << "my $" << elem << " = undef;" << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << "push(@{$" << prefix << "},$" << elem << ");" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_perl_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + "{" + tfield->get_name() + "}");
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + "{" + tfield->get_name() + "}");
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = tfield->get_name();
+
+    // Hack for when prefix is defined (always a hash ref)
+    if (!prefix.empty())
+      name = prefix + "{" + tfield->get_name() + "}";
+
+    indent(out) << "$xfer += $output->";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << "writeString($" << name << ");";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool($" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte($" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16($" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32($" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64($" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble($" << name << ");";
+        break;
+      default:
+        throw "compiler error: no PERL name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32($" << name << ");";
+    }
+    out << endl;
+
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_perl_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << "$xfer += $" << prefix << "->write($output);" << endl;
+}
+
+/**
+ * Writes out a container
+ */
+void t_perl_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "$xfer += $output->writeMapBegin("
+                << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
+                << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
+                << "scalar(keys %{$" << prefix << "}));" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "$xfer += $output->writeSetBegin("
+                << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", "
+                << "scalar(@{$" << prefix << "}));" << endl;
+
+  } else if (ttype->is_list()) {
+
+    indent(out) << "$xfer += $output->writeListBegin("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", "
+                << "scalar(@{$" << prefix << "}));" << endl;
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    string kiter = tmp("kiter");
+    string viter = tmp("viter");
+    indent(out) << "while( my ($" << kiter << ",$" << viter << ") = each %{$" << prefix << "}) "
+                << endl;
+
+    scope_up(out);
+    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+    scope_down(out);
+
+  } else if (ttype->is_set()) {
+    string iter = tmp("iter");
+    indent(out) << "foreach my $" << iter << " (@{$" << prefix << "})" << endl;
+    scope_up(out);
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    scope_down(out);
+
+  } else if (ttype->is_list()) {
+    string iter = tmp("iter");
+    indent(out) << "foreach my $" << iter << " (@{$" << prefix << "}) " << endl;
+    scope_up(out);
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    scope_down(out);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "$xfer += $output->writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "$xfer += $output->writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "$xfer += $output->writeListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ *
+ */
+void t_perl_generator::generate_serialize_map_element(ofstream& out,
+                                                      t_map* tmap,
+                                                      string kiter,
+                                                      string viter) {
+  t_field kfield(tmap->get_key_type(), kiter);
+  generate_serialize_field(out, &kfield);
+
+  t_field vfield(tmap->get_val_type(), viter);
+  generate_serialize_field(out, &vfield);
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_perl_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield);
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_perl_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield);
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ */
+string t_perl_generator::declare_field(t_field* tfield, bool init, bool obj) {
+  string result = "my $" + tfield->get_name();
+  if (init) {
+    t_type* type = get_true_type(tfield->get_type());
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        break;
+      case t_base_type::TYPE_STRING:
+        result += " = ''";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = 0";
+        break;
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+        result += " = 0";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = 0.0";
+        break;
+      default:
+        throw "compiler error: no PERL initializer for base type "
+            + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      result += " = 0";
+    } else if (type->is_container()) {
+      result += " = []";
+    } else if (type->is_struct() || type->is_xception()) {
+      if (obj) {
+        result += " = new " + perl_namespace(type->get_program()) + type->get_name() + "()";
+      } else {
+        result += " = undef";
+      }
+    }
+  }
+  return result + ";";
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_perl_generator::function_signature(t_function* tfunction, string prefix) {
+
+  string str;
+
+  str = prefix + tfunction->get_name() + "{\n";
+  str += "  my $self = shift;\n";
+
+  // Need to create perl function arg inputs
+  const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    str += "  my $" + (*f_iter)->get_name() + " = shift;\n";
+  }
+
+  return str;
+}
+
+/**
+ * Renders a field list
+ */
+string t_perl_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += "$" + (*f_iter)->get_name();
+  }
+  return result;
+}
+
+/**
+ * Converts the parse type to a C++ enum string for the given type.
+ */
+string t_perl_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TType::STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType::BOOL";
+    case t_base_type::TYPE_I8:
+      return "TType::BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType::I16";
+    case t_base_type::TYPE_I32:
+      return "TType::I32";
+    case t_base_type::TYPE_I64:
+      return "TType::I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType::DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "TType::I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType::STRUCT";
+  } else if (type->is_map()) {
+    return "TType::MAP";
+  } else if (type->is_set()) {
+    return "TType::SET";
+  } else if (type->is_list()) {
+    return "TType::LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+THRIFT_REGISTER_GENERATOR(perl, "Perl", "")


[05/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically

Posted by ns...@apache.org.
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc
new file mode 100644
index 0000000..594219a
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc
@@ -0,0 +1,1762 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/version.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::ios;
+using std::map;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * OCaml code generator.
+ *
+ */
+class t_ocaml_generator : public t_oop_generator {
+public:
+  t_ocaml_generator(t_program* program,
+                    const std::map<std::string, std::string>& parsed_options,
+                    const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option ocaml:" + iter->first;
+    }
+
+    out_dir_base_ = "gen-ocaml";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  /**
+   * Program-level generation functions
+   */
+  void generate_program();
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_const(t_const* tconst);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  std::string render_const_value(t_type* type, t_const_value* value);
+  bool struct_member_persistent(t_field* tmember);
+  bool struct_member_omitable(t_field* tmember);
+  bool struct_member_default_cheaply_comparable(t_field* tmember);
+  std::string struct_member_copy_of(t_type* type, string what);
+
+  /**
+   * Struct generation code
+   */
+
+  void generate_ocaml_struct(t_struct* tstruct, bool is_exception);
+  void generate_ocaml_struct_definition(std::ofstream& out,
+                                        t_struct* tstruct,
+                                        bool is_xception = false);
+  void generate_ocaml_struct_member(std::ofstream& out, string tname, t_field* tmember);
+  void generate_ocaml_struct_sig(std::ofstream& out, t_struct* tstruct, bool is_exception);
+  void generate_ocaml_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_ocaml_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_ocaml_function_helpers(t_function* tfunction);
+  void generate_ocaml_method_copy(std::ofstream& out, const vector<t_field*>& members);
+  void generate_ocaml_member_copy(std::ofstream& out, t_field* member);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_interface(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix);
+
+  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct);
+
+  void generate_deserialize_container(std::ofstream& out, t_type* ttype);
+
+  void generate_deserialize_set_element(std::ofstream& out, t_set* tset);
+
+  void generate_deserialize_list_element(std::ofstream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+  void generate_deserialize_type(std::ofstream& out, t_type* type);
+
+  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string name = "");
+
+  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ofstream& out,
+                                      t_map* tmap,
+                                      std::string kiter,
+                                      std::string viter);
+
+  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string ocaml_autogen_comment();
+  std::string ocaml_imports();
+  std::string type_name(t_type* ttype);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string function_type(t_function* tfunc, bool method = false, bool options = false);
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string render_ocaml_type(t_type* type);
+
+private:
+  /**
+   * File streams
+   */
+
+  std::ofstream f_types_;
+  std::ofstream f_consts_;
+  std::ofstream f_service_;
+
+  std::ofstream f_types_i_;
+  std::ofstream f_service_i_;
+};
+
+/*
+ * This is necessary because we want typedefs to appear later,
+ * after all the types have been declared.
+ */
+void t_ocaml_generator::generate_program() {
+  // Initialize the generator
+  init_generator();
+
+  // Generate enums
+  vector<t_enum*> enums = program_->get_enums();
+  vector<t_enum*>::iterator en_iter;
+  for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
+    generate_enum(*en_iter);
+  }
+
+  // Generate structs
+  vector<t_struct*> structs = program_->get_structs();
+  vector<t_struct*>::iterator st_iter;
+  for (st_iter = structs.begin(); st_iter != structs.end(); ++st_iter) {
+    generate_struct(*st_iter);
+  }
+
+  // Generate xceptions
+  vector<t_struct*> xceptions = program_->get_xceptions();
+  vector<t_struct*>::iterator x_iter;
+  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+    generate_xception(*x_iter);
+  }
+
+  // Generate typedefs
+  vector<t_typedef*> typedefs = program_->get_typedefs();
+  vector<t_typedef*>::iterator td_iter;
+  for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
+    generate_typedef(*td_iter);
+  }
+
+  // Generate services
+  vector<t_service*> services = program_->get_services();
+  vector<t_service*>::iterator sv_iter;
+  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
+    service_name_ = get_service_name(*sv_iter);
+    generate_service(*sv_iter);
+  }
+
+  // Generate constants
+  vector<t_const*> consts = program_->get_consts();
+  generate_consts(consts);
+
+  // Close the generator
+  close_generator();
+}
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_ocaml_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  // Make output file
+  string f_types_name = get_out_dir() + program_name_ + "_types.ml";
+  f_types_.open(f_types_name.c_str());
+  string f_types_i_name = get_out_dir() + program_name_ + "_types.mli";
+  f_types_i_.open(f_types_i_name.c_str());
+
+  string f_consts_name = get_out_dir() + program_name_ + "_consts.ml";
+  f_consts_.open(f_consts_name.c_str());
+
+  // Print header
+  f_types_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
+  f_types_i_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
+  f_consts_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl << "open "
+            << capitalize(program_name_) << "_types" << endl;
+}
+
+/**
+ * Autogen'd comment
+ */
+string t_ocaml_generator::ocaml_autogen_comment() {
+  return std::string("(*\n") + " Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "\n"
+         + " DO NOT EDIT UNLESS YOU ARE SURE YOU KNOW WHAT YOU ARE DOING\n" + "*)\n";
+}
+
+/**
+ * Prints standard thrift imports
+ */
+string t_ocaml_generator::ocaml_imports() {
+  return "open Thrift";
+}
+
+/**
+ * Closes the type files
+ */
+void t_ocaml_generator::close_generator() {
+  // Close types file
+  f_types_.close();
+}
+
+/**
+ * Generates a typedef. Ez.
+ *
+ * @param ttypedef The type definition
+ */
+void t_ocaml_generator::generate_typedef(t_typedef* ttypedef) {
+  f_types_ << indent() << "type " << decapitalize(ttypedef->get_symbolic()) << " = "
+           << render_ocaml_type(ttypedef->get_type()) << endl << endl;
+  f_types_i_ << indent() << "type " << decapitalize(ttypedef->get_symbolic()) << " = "
+             << render_ocaml_type(ttypedef->get_type()) << endl << endl;
+}
+
+/**
+ * Generates code for an enumerated type.
+ * the values.
+ *
+ * @param tenum The enumeration
+ */
+void t_ocaml_generator::generate_enum(t_enum* tenum) {
+  indent(f_types_) << "module " << capitalize(tenum->get_name()) << " = " << endl << "struct"
+                   << endl;
+  indent(f_types_i_) << "module " << capitalize(tenum->get_name()) << " : " << endl << "sig"
+                     << endl;
+  indent_up();
+  indent(f_types_) << "type t = " << endl;
+  indent(f_types_i_) << "type t = " << endl;
+  indent_up();
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    string name = capitalize((*c_iter)->get_name());
+    indent(f_types_) << "| " << name << endl;
+    indent(f_types_i_) << "| " << name << endl;
+  }
+  indent_down();
+
+  indent(f_types_) << "let to_i = function" << endl;
+  indent(f_types_i_) << "val to_i : t -> Int32.t" << endl;
+  indent_up();
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    string name = capitalize((*c_iter)->get_name());
+    indent(f_types_) << "| " << name << " -> " << value << "l" << endl;
+  }
+  indent_down();
+
+  indent(f_types_) << "let of_i = function" << endl;
+  indent(f_types_i_) << "val of_i : Int32.t -> t" << endl;
+  indent_up();
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    string name = capitalize((*c_iter)->get_name());
+    indent(f_types_) << "| " << value << "l -> " << name << endl;
+  }
+  indent(f_types_) << "| _ -> raise Thrift_error" << endl;
+  indent_down();
+  indent_down();
+  indent(f_types_) << "end" << endl;
+  indent(f_types_i_) << "end" << endl;
+}
+
+/**
+ * Generate a constant value
+ */
+void t_ocaml_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = decapitalize(tconst->get_name());
+  t_const_value* value = tconst->get_value();
+
+  indent(f_consts_) << "let " << name << " = " << render_const_value(type, value) << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_ocaml_generator::render_const_value(t_type* type, t_const_value* value) {
+  type = get_true_type(type);
+  std::ostringstream out;
+  // OCaml requires all floating point numbers contain a decimal point
+  out.setf(ios::showpoint);
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      out << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      out << value->get_integer() << "l";
+      break;
+    case t_base_type::TYPE_I64:
+      out << value->get_integer() << "L";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer() << ".0";
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    t_enum* tenum = (t_enum*)type;
+    vector<t_enum_value*> constants = tenum->get_constants();
+    vector<t_enum_value*>::iterator c_iter;
+    for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+      int val = (*c_iter)->get_value();
+      if (val == value->get_integer()) {
+        indent(out) << capitalize(tenum->get_name()) << "." << capitalize((*c_iter)->get_name());
+        break;
+      }
+    }
+  } else if (type->is_struct() || type->is_xception()) {
+    string cname = type_name(type);
+    string ct = tmp("_c");
+    out << endl;
+    indent_up();
+    indent(out) << "(let " << ct << " = new " << cname << " in" << endl;
+    indent_up();
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string fname = v_iter->first->get_string();
+      out << indent();
+      out << ct << "#set_" << fname << " ";
+      out << render_const_value(field_type, v_iter->second);
+      out << ";" << endl;
+    }
+    indent(out) << ct << ")";
+    indent_down();
+    indent_down();
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    string hm = tmp("_hm");
+    out << endl;
+    indent_up();
+    indent(out) << "(let " << hm << " = Hashtbl.create " << val.size() << " in" << endl;
+    indent_up();
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(ktype, v_iter->first);
+      string val = render_const_value(vtype, v_iter->second);
+      indent(out) << "Hashtbl.add " << hm << " " << key << " " << val << ";" << endl;
+    }
+    indent(out) << hm << ")";
+    indent_down();
+    indent_down();
+  } else if (type->is_list()) {
+    t_type* etype;
+    etype = ((t_list*)type)->get_elem_type();
+    out << "[" << endl;
+    indent_up();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent();
+      out << render_const_value(etype, *v_iter);
+      out << ";" << endl;
+    }
+    indent_down();
+    indent(out) << "]";
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    string hm = tmp("_hm");
+    indent(out) << "(let " << hm << " = Hashtbl.create " << val.size() << " in" << endl;
+    indent_up();
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(etype, *v_iter);
+      indent(out) << "Hashtbl.add " << hm << " " << val << " true;" << endl;
+    }
+    indent(out) << hm << ")" << endl;
+    indent_down();
+    out << endl;
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+  return out.str();
+}
+
+/**
+ * Generates a "struct"
+ */
+void t_ocaml_generator::generate_struct(t_struct* tstruct) {
+  generate_ocaml_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct, but also has an exception declaration.
+ *
+ * @param txception The struct definition
+ */
+void t_ocaml_generator::generate_xception(t_struct* txception) {
+  generate_ocaml_struct(txception, true);
+}
+
+/**
+ * Generates an OCaml struct
+ */
+void t_ocaml_generator::generate_ocaml_struct(t_struct* tstruct, bool is_exception) {
+  generate_ocaml_struct_definition(f_types_, tstruct, is_exception);
+  generate_ocaml_struct_sig(f_types_i_, tstruct, is_exception);
+}
+
+void t_ocaml_generator::generate_ocaml_method_copy(ofstream& out, const vector<t_field*>& members) {
+  vector<t_field*>::const_iterator m_iter;
+
+  /* Create a copy of the current object */
+  indent(out) << "method copy =" << endl;
+  indent_up();
+  indent_up();
+  indent(out) << "let _new = Oo.copy self in" << endl;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
+    generate_ocaml_member_copy(out, *m_iter);
+
+  indent_down();
+  indent(out) << "_new" << endl;
+  indent_down();
+}
+
+string t_ocaml_generator::struct_member_copy_of(t_type* type, string what) {
+  if (type->is_struct() || type->is_xception()) {
+    return what + string("#copy");
+  }
+  if (type->is_map()) {
+    string copy_of_k = struct_member_copy_of(((t_map*)type)->get_key_type(), "k");
+    string copy_of_v = struct_member_copy_of(((t_map*)type)->get_val_type(), "v");
+
+    if (copy_of_k == "k" && copy_of_v == "v") {
+      return string("(Hashtbl.copy ") + what + string(")");
+    } else {
+      return string(
+                 "((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v "
+                 "-> Hashtbl.add nh ") + copy_of_k + string(" ") + copy_of_v + string(") oh; nh) ")
+             + what + ")";
+    }
+  }
+  if (type->is_set()) {
+    string copy_of = struct_member_copy_of(((t_set*)type)->get_elem_type(), "k");
+
+    if (copy_of == "k") {
+      return string("(Hashtbl.copy ") + what + string(")");
+    } else {
+      return string(
+                 "((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v "
+                 "-> Hashtbl.add nh ") + copy_of + string(" true") + string(") oh; nh) ") + what
+             + ")";
+    }
+  }
+  if (type->is_list()) {
+    string copy_of = struct_member_copy_of(((t_list*)type)->get_elem_type(), "x");
+    if (copy_of != "x") {
+      return string("(List.map (fun x -> ") + copy_of + string(") ") + what + string(")");
+    } else {
+      return what;
+    }
+  }
+  return what;
+}
+
+void t_ocaml_generator::generate_ocaml_member_copy(ofstream& out, t_field* tmember) {
+  string mname = decapitalize(tmember->get_name());
+  t_type* type = get_true_type(tmember->get_type());
+
+  string grab_field = string("self#grab_") + mname;
+  string copy_of = struct_member_copy_of(type, grab_field);
+  if (copy_of != grab_field) {
+    indent(out);
+    if (!struct_member_persistent(tmember)) {
+      out << "if _" << mname << " <> None then" << endl;
+      indent(out) << "  ";
+    }
+    out << "_new#set_" << mname << " " << copy_of << ";" << endl;
+  }
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_ocaml_generator::generate_ocaml_struct_definition(ofstream& out,
+                                                         t_struct* tstruct,
+                                                         bool is_exception) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  string tname = type_name(tstruct);
+  indent(out) << "class " << tname << " =" << endl;
+  indent(out) << "object (self)" << endl;
+
+  indent_up();
+
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      generate_ocaml_struct_member(out, tname, (*m_iter));
+      out << endl;
+    }
+  }
+  generate_ocaml_method_copy(out, members);
+  generate_ocaml_struct_writer(out, tstruct);
+  indent_down();
+  indent(out) << "end" << endl;
+
+  if (is_exception) {
+    indent(out) << "exception " << capitalize(tname) << " of " << tname << endl;
+  }
+
+  generate_ocaml_struct_reader(out, tstruct);
+}
+
+/**
+ * Generates a structure member for a thrift data type.
+ *
+ * @param tname Name of the parent structure for the member
+ * @param tmember Member definition
+ */
+void t_ocaml_generator::generate_ocaml_struct_member(ofstream& out,
+                                                     string tname,
+                                                     t_field* tmember) {
+  string x = tmp("_x");
+  string mname = decapitalize(tmember->get_name());
+
+  indent(out) << "val mutable _" << mname << " : " << render_ocaml_type(tmember->get_type());
+  t_const_value* val = tmember->get_value();
+  if (val) {
+    if (struct_member_persistent(tmember))
+      out << " = " << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
+    else
+      out << " option = Some " << render_const_value(tmember->get_type(), tmember->get_value())
+          << endl;
+  } else {
+    // assert(!struct_member_persistent(tmember))
+    out << " option = None" << endl;
+  }
+
+  if (struct_member_persistent(tmember)) {
+    indent(out) << "method get_" << mname << " = Some _" << mname << endl;
+    indent(out) << "method grab_" << mname << " = _" << mname << endl;
+    indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- " << x << endl;
+  } else {
+    indent(out) << "method get_" << mname << " = _" << mname << endl;
+    indent(out) << "method grab_" << mname << " = match _" << mname
+                << " with None->raise (Field_empty \"" << tname << "." << mname << "\") | Some "
+                << x << " -> " << x << endl;
+    indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- Some " << x
+                << endl;
+    indent(out) << "method unset_" << mname << " = _" << mname << " <- None" << endl;
+  }
+
+  indent(out) << "method reset_" << mname << " = _" << mname << " <- ";
+  if (val) {
+    if (struct_member_persistent(tmember))
+      out << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
+    else
+      out << "Some " << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
+  } else {
+    out << "None" << endl;
+  }
+}
+
+/**
+ * Check whether a member of the structure can not have undefined value
+ *
+ * @param tmember Member definition
+ */
+bool t_ocaml_generator::struct_member_persistent(t_field* tmember) {
+  t_const_value* val = tmember->get_value();
+  return (val ? true : false);
+}
+
+/**
+ * Check whether a member of the structure can be skipped during encoding
+ *
+ * @param tmember Member definition
+ */
+bool t_ocaml_generator::struct_member_omitable(t_field* tmember) {
+  return (tmember->get_req() != t_field::T_REQUIRED);
+}
+
+/**
+ * Figure out whether a member of the structure has
+ * a cheaply comparable default value.
+ *
+ * @param tmember Member definition
+ */
+bool t_ocaml_generator::struct_member_default_cheaply_comparable(t_field* tmember) {
+  t_type* type = get_true_type(tmember->get_type());
+  t_const_value* val = tmember->get_value();
+  if (!val) {
+    return false;
+  } else if (type->is_base_type()) {
+    // Base types are generally cheaply compared for structural equivalence.
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_DOUBLE:
+      if (val->get_double() == 0.0)
+        return true;
+      else
+        return false;
+    default:
+      return true;
+    }
+  } else if (type->is_list()) {
+    // Empty lists are cheaply compared for structural equivalence.
+    // Is empty list?
+    if (val->get_list().size() == 0)
+      return true;
+    else
+      return false;
+  } else {
+    return false;
+  }
+}
+
+/**
+ * Generates a struct definition for a thrift data type.
+ *
+ * @param tstruct The struct definition
+ */
+void t_ocaml_generator::generate_ocaml_struct_sig(ofstream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_exception) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  string tname = type_name(tstruct);
+  indent(out) << "class " << tname << " :" << endl;
+  indent(out) << "object ('a)" << endl;
+
+  indent_up();
+
+  string x = tmp("_x");
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      string mname = decapitalize((*m_iter)->get_name());
+      string type = render_ocaml_type((*m_iter)->get_type());
+      indent(out) << "method get_" << mname << " : " << type << " option" << endl;
+      indent(out) << "method grab_" << mname << " : " << type << endl;
+      indent(out) << "method set_" << mname << " : " << type << " -> unit" << endl;
+      if (!struct_member_persistent(*m_iter))
+        indent(out) << "method unset_" << mname << " : unit" << endl;
+      indent(out) << "method reset_" << mname << " : unit" << endl;
+    }
+  }
+  indent(out) << "method copy : 'a" << endl;
+  indent(out) << "method write : Protocol.t -> unit" << endl;
+  indent_down();
+  indent(out) << "end" << endl;
+
+  if (is_exception) {
+    indent(out) << "exception " << capitalize(tname) << " of " << tname << endl;
+  }
+
+  indent(out) << "val read_" << tname << " : Protocol.t -> " << tname << endl;
+}
+
+/**
+ * Generates the read method for a struct
+ */
+void t_ocaml_generator::generate_ocaml_struct_reader(ofstream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  string sname = type_name(tstruct);
+  string str = tmp("_str");
+  string t = tmp("_t");
+  string id = tmp("_id");
+  indent(out) << "let rec read_" << sname << " (iprot : Protocol.t) =" << endl;
+  indent_up();
+  indent(out) << "let " << str << " = new " << sname << " in" << endl;
+  indent_up();
+  indent(out) << "ignore(iprot#readStructBegin);" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "(try while true do" << endl;
+  indent_up();
+  indent_up();
+
+  // Read beginning field marker
+  indent(out) << "let (_," << t << "," << id << ") = iprot#readFieldBegin in" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if " << t << " = Protocol.T_STOP then" << endl;
+  indent_up();
+  indent(out) << "raise Break" << endl;
+  indent_down();
+  indent(out) << "else ();" << endl;
+
+  indent(out) << "(match " << id << " with " << endl;
+  indent_up();
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "| " << (*f_iter)->get_key() << " -> (";
+    out << "if " << t << " = " << type_to_enum((*f_iter)->get_type()) << " then" << endl;
+    indent_up();
+    indent_up();
+    generate_deserialize_field(out, *f_iter, str);
+    indent_down();
+    out << indent() << "else" << endl << indent() << "  iprot#skip " << t << ")" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "| _ -> "
+      << "iprot#skip " << t << ");" << endl;
+  indent_down();
+  // Read field end marker
+  indent(out) << "iprot#readFieldEnd;" << endl;
+  indent_down();
+  indent(out) << "done; ()" << endl;
+  indent_down();
+  indent(out) << "with Break -> ());" << endl;
+
+  indent(out) << "iprot#readStructEnd;" << endl;
+
+  indent(out) << str << endl << endl;
+  indent_down();
+  indent_down();
+}
+
+void t_ocaml_generator::generate_ocaml_struct_writer(ofstream& out, t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+  string str = tmp("_str");
+  string f = tmp("_f");
+
+  indent(out) << "method write (oprot : Protocol.t) =" << endl;
+  indent_up();
+  indent(out) << "oprot#writeStructBegin \"" << name << "\";" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* tmember = (*f_iter);
+    string mname = "_" + decapitalize(tmember->get_name());
+    string _v;
+
+    if (struct_member_persistent(tmember)) {
+
+      if (struct_member_omitable(tmember) && struct_member_default_cheaply_comparable(tmember)) {
+        _v = "_v";
+        // Avoid redundant encoding of members having default values.
+        indent(out) << "(match " << mname << " with "
+                    << render_const_value(tmember->get_type(), tmember->get_value()) << " -> () | "
+                    << _v << " -> " << endl;
+      } else {
+        _v = mname;
+        indent(out) << "(" << endl;
+      }
+
+    } else {
+
+      indent(out) << "(match " << mname << " with ";
+
+      if (struct_member_omitable(tmember)) {
+        out << "None -> ()";
+
+        if (struct_member_default_cheaply_comparable(tmember)) {
+          // Avoid redundant encoding of members having default values.
+          out << " | Some " << render_const_value(tmember->get_type(), tmember->get_value())
+              << " -> ()";
+        }
+        out << " | Some _v -> " << endl;
+      } else {
+        out << endl;
+        indent(out) << "| None -> raise (Field_empty \"" << type_name(tstruct) << "." << mname
+                    << "\")" << endl;
+        indent(out) << "| Some _v -> " << endl;
+      }
+
+      _v = "_v";
+    }
+    indent_up();
+    // Write field header
+    indent(out) << "oprot#writeFieldBegin(\"" << tmember->get_name() << "\","
+                << type_to_enum(tmember->get_type()) << "," << tmember->get_key() << ");" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, tmember, _v);
+
+    // Write field closer
+    indent(out) << "oprot#writeFieldEnd" << endl;
+
+    indent_down();
+    indent(out) << ");" << endl;
+  }
+
+  // Write the struct map
+  out << indent() << "oprot#writeFieldStop;" << endl << indent() << "oprot#writeStructEnd" << endl;
+
+  indent_down();
+}
+
+/**
+ * Generates a thrift service.
+ *
+ * @param tservice The service definition
+ */
+void t_ocaml_generator::generate_service(t_service* tservice) {
+  string f_service_name = get_out_dir() + capitalize(service_name_) + ".ml";
+  f_service_.open(f_service_name.c_str());
+  string f_service_i_name = get_out_dir() + capitalize(service_name_) + ".mli";
+  f_service_i_.open(f_service_i_name.c_str());
+
+  f_service_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
+  f_service_i_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl;
+
+  /* if (tservice->get_extends() != NULL) {
+    f_service_ <<
+      "open " << capitalize(tservice->get_extends()->get_name()) << endl;
+    f_service_i_ <<
+      "open " << capitalize(tservice->get_extends()->get_name()) << endl;
+  }
+  */
+  f_service_ << "open " << capitalize(program_name_) << "_types" << endl << endl;
+
+  f_service_i_ << "open " << capitalize(program_name_) << "_types" << endl << endl;
+
+  // Generate the three main parts of the service
+  generate_service_helpers(tservice);
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+
+  // Close service file
+  f_service_.close();
+  f_service_i_.close();
+}
+
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_ocaml_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  indent(f_service_) << "(* HELPER FUNCTIONS AND STRUCTURES *)" << endl << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_ocaml_struct_definition(f_service_, ts, false);
+    generate_ocaml_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_ocaml_generator::generate_ocaml_function_helpers(t_function* tfunction) {
+  t_struct result(program_, decapitalize(tfunction->get_name()) + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+  generate_ocaml_struct_definition(f_service_, &result, false);
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_ocaml_generator::generate_service_interface(t_service* tservice) {
+  f_service_ << indent() << "class virtual iface =" << endl << "object (self)" << endl;
+  f_service_i_ << indent() << "class virtual iface :" << endl << "object" << endl;
+
+  indent_up();
+
+  if (tservice->get_extends() != NULL) {
+    string extends = type_name(tservice->get_extends());
+    indent(f_service_) << "inherit " << extends << ".iface" << endl;
+    indent(f_service_i_) << "inherit " << extends << ".iface" << endl;
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string ft = function_type(*f_iter, true, true);
+    f_service_ << indent() << "method virtual " << decapitalize((*f_iter)->get_name()) << " : "
+               << ft << endl;
+    f_service_i_ << indent() << "method virtual " << decapitalize((*f_iter)->get_name()) << " : "
+                 << ft << endl;
+  }
+  indent_down();
+  indent(f_service_) << "end" << endl << endl;
+  indent(f_service_i_) << "end" << endl << endl;
+}
+
+/**
+ * Generates a service client definition. Note that in OCaml, the client doesn't implement iface.
+ *This is because
+ * The client does not (and should not have to) deal with arguments being None.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_ocaml_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  indent(f_service_) << "class client (iprot : Protocol.t) (oprot : Protocol.t) =" << endl
+                     << "object (self)" << endl;
+  indent(f_service_i_) << "class client : Protocol.t -> Protocol.t -> " << endl << "object" << endl;
+  indent_up();
+
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    indent(f_service_) << "inherit " << extends << ".client iprot oprot as super" << endl;
+    indent(f_service_i_) << "inherit " << extends << ".client" << endl;
+  }
+  indent(f_service_) << "val mutable seqid = 0" << endl;
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    indent(f_service_) << "method " << function_signature(*f_iter) << " = " << endl;
+    indent(f_service_i_) << "method " << decapitalize((*f_iter)->get_name()) << " : "
+                         << function_type(*f_iter, true, false) << endl;
+    indent_up();
+    indent(f_service_) << "self#send_" << funname;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << " " << decapitalize((*fld_iter)->get_name());
+    }
+    f_service_ << ";" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      f_service_ << "self#recv_" << funname << endl;
+    }
+    indent_down();
+
+    indent(f_service_) << "method private send_" << function_signature(*f_iter) << " = " << endl;
+    indent_up();
+
+    std::string argsname = decapitalize((*f_iter)->get_name() + "_args");
+
+    // Serialize the request header
+    f_service_ << indent() << "oprot#writeMessageBegin (\"" << (*f_iter)->get_name() << "\", "
+               << ((*f_iter)->is_oneway() ? "Protocol.ONEWAY" : "Protocol.CALL") << ", seqid);"
+               << endl;
+
+    f_service_ << indent() << "let args = new " << argsname << " in" << endl;
+    indent_up();
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args#set_" << (*fld_iter)->get_name() << " "
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    // Write to the stream
+    f_service_ << indent() << "args#write oprot;" << endl << indent() << "oprot#writeMessageEnd;"
+               << endl << indent() << "oprot#getTransport#flush" << endl;
+
+    indent_down();
+    indent_down();
+
+    if (!(*f_iter)->is_oneway()) {
+      std::string resultname = decapitalize((*f_iter)->get_name() + "_result");
+      t_struct noargs(program_);
+
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs);
+      // Open function
+      f_service_ << indent() << "method private " << function_signature(&recv_function) << " ="
+                 << endl;
+      indent_up();
+
+      // TODO(mcslee): Validate message reply here, seq ids etc.
+
+      f_service_ << indent() << "let (fname, mtype, rseqid) = iprot#readMessageBegin in" << endl;
+      indent_up();
+      f_service_ << indent() << "(if mtype = Protocol.EXCEPTION then" << endl << indent()
+                 << "  let x = Application_Exn.read iprot in" << endl;
+      indent_up();
+      f_service_ << indent() << "  (iprot#readMessageEnd;" << indent()
+                 << "   raise (Application_Exn.E x))" << endl;
+      indent_down();
+      f_service_ << indent() << "else ());" << endl;
+      string res = "_";
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+
+      if (!(*f_iter)->get_returntype()->is_void() || xceptions.size() > 0) {
+        res = "result";
+      }
+      f_service_ << indent() << "let " << res << " = read_" << resultname << " iprot in" << endl;
+      indent_up();
+      f_service_ << indent() << "iprot#readMessageEnd;" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "match result#get_success with Some v -> v | None -> (" << endl;
+        indent_up();
+      }
+
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "(match result#get_" << (*x_iter)->get_name()
+                   << " with None -> () | Some _v ->" << endl;
+        indent(f_service_) << "  raise (" << capitalize(type_name((*x_iter)->get_type()))
+                           << " _v));" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "()" << endl;
+      } else {
+        f_service_
+            << indent()
+            << "raise (Application_Exn.E (Application_Exn.create Application_Exn.MISSING_RESULT \""
+            << (*f_iter)->get_name() << " failed: unknown result\")))" << endl;
+        indent_down();
+      }
+
+      // Close function
+      indent_down();
+      indent_down();
+      indent_down();
+    }
+  }
+
+  indent_down();
+  indent(f_service_) << "end" << endl << endl;
+  indent(f_service_i_) << "end" << endl << endl;
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_ocaml_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // Generate the header portion
+  indent(f_service_) << "class processor (handler : iface) =" << endl << indent() << "object (self)"
+                     << endl;
+  indent(f_service_i_) << "class processor : iface ->" << endl << indent() << "object" << endl;
+  indent_up();
+
+  f_service_ << indent() << "inherit Processor.t" << endl << endl;
+  f_service_i_ << indent() << "inherit Processor.t" << endl << endl;
+  string extends = "";
+
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    indent(f_service_) << "inherit " + extends + ".processor (handler :> " + extends + ".iface)"
+                       << endl;
+    indent(f_service_i_) << "inherit " + extends + ".processor" << endl;
+  }
+
+  if (extends.empty()) {
+    indent(f_service_) << "val processMap = Hashtbl.create " << functions.size() << endl;
+  }
+  indent(f_service_i_)
+      << "val processMap : (string, int * Protocol.t * Protocol.t -> unit) Hashtbl.t" << endl;
+
+  // Generate the server implementation
+  indent(f_service_) << "method process iprot oprot =" << endl;
+  indent(f_service_i_) << "method process : Protocol.t -> Protocol.t -> bool" << endl;
+  indent_up();
+
+  f_service_ << indent() << "let (name, typ, seqid)  = iprot#readMessageBegin in" << endl;
+  indent_up();
+  // TODO(mcslee): validate message
+
+  // HOT: dictionary function lookup
+  f_service_ << indent() << "if Hashtbl.mem processMap name then" << endl << indent()
+             << "  (Hashtbl.find processMap name) (seqid, iprot, oprot)" << endl << indent()
+             << "else (" << endl << indent() << "  iprot#skip(Protocol.T_STRUCT);" << endl
+             << indent() << "  iprot#readMessageEnd;" << endl << indent()
+             << "  let x = Application_Exn.create Application_Exn.UNKNOWN_METHOD (\"Unknown "
+                "function \"^name) in" << endl << indent()
+             << "    oprot#writeMessageBegin(name, Protocol.EXCEPTION, seqid);" << endl << indent()
+             << "    x#write oprot;" << endl << indent() << "    oprot#writeMessageEnd;" << endl
+             << indent() << "    oprot#getTransport#flush" << endl << indent() << ");" << endl;
+
+  // Read end of args field, the T_STOP, and the struct close
+  f_service_ << indent() << "true" << endl;
+  indent_down();
+  indent_down();
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent(f_service_) << "initializer" << endl;
+  indent_up();
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "Hashtbl.add processMap \"" << (*f_iter)->get_name()
+               << "\" self#process_" << (*f_iter)->get_name() << ";" << endl;
+  }
+  indent_down();
+
+  indent_down();
+  indent(f_service_) << "end" << endl << endl;
+  indent(f_service_i_) << "end" << endl << endl;
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_ocaml_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open function
+  indent(f_service_) << "method private process_" << tfunction->get_name()
+                     << " (seqid, iprot, oprot) =" << endl;
+  indent_up();
+
+  string argsname = decapitalize(tfunction->get_name()) + "_args";
+  string resultname = decapitalize(tfunction->get_name()) + "_result";
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  string args = "args";
+  if (fields.size() == 0) {
+    args = "_";
+  }
+
+  f_service_ << indent() << "let " << args << " = read_" << argsname << " iprot in" << endl;
+  indent_up();
+  f_service_ << indent() << "iprot#readMessageEnd;" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "let result = new " << resultname << " in" << endl;
+    indent_up();
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "(try" << endl;
+    indent_up();
+  }
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result#set_success ";
+  }
+  f_service_ << "(handler#" << tfunction->get_name();
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    f_service_ << " args#get_" << (*f_iter)->get_name();
+  }
+  f_service_ << ");" << endl;
+
+  if (xceptions.size() > 0) {
+    indent_down();
+    indent(f_service_) << "with" << endl;
+    indent_up();
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << indent() << "| " << capitalize(type_name((*x_iter)->get_type())) << " "
+                 << (*x_iter)->get_name() << " -> " << endl;
+      indent_up();
+      indent_up();
+      if (!tfunction->is_oneway()) {
+        f_service_ << indent() << "result#set_" << (*x_iter)->get_name() << " "
+                   << (*x_iter)->get_name() << endl;
+      } else {
+        indent(f_service_) << "()";
+      }
+      indent_down();
+      indent_down();
+    }
+    indent_down();
+    f_service_ << indent() << ");" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "()" << endl;
+    indent_down();
+    indent_down();
+    return;
+  }
+
+  f_service_ << indent() << "oprot#writeMessageBegin (\"" << tfunction->get_name()
+             << "\", Protocol.REPLY, seqid);" << endl << indent() << "result#write oprot;" << endl
+             << indent() << "oprot#writeMessageEnd;" << endl << indent()
+             << "oprot#getTransport#flush" << endl;
+
+  // Close function
+  indent_down();
+  indent_down();
+  indent_down();
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_ocaml_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+  t_type* type = tfield->get_type();
+
+  string name = decapitalize(tfield->get_name());
+  indent(out) << prefix << "#set_" << name << " ";
+  generate_deserialize_type(out, type);
+  out << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_ocaml_generator::generate_deserialize_type(ofstream& out, t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE";
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type);
+  } else if (type->is_base_type()) {
+    out << "iprot#";
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "compiler error: cannot serialize void field in a struct";
+      break;
+    case t_base_type::TYPE_STRING:
+      out << "readString";
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << "readBool";
+      break;
+    case t_base_type::TYPE_I8:
+      out << "readByte";
+      break;
+    case t_base_type::TYPE_I16:
+      out << "readI16";
+      break;
+    case t_base_type::TYPE_I32:
+      out << "readI32";
+      break;
+    case t_base_type::TYPE_I64:
+      out << "readI64";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      out << "readDouble";
+      break;
+    default:
+      throw "compiler error: no ocaml name for base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    string ename = capitalize(type->get_name());
+    out << "(" << ename << ".of_i iprot#readI32)";
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE TYPE '%s'\n", type->get_name().c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, calling read()
+ */
+void t_ocaml_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct) {
+  string prefix = "";
+  t_program* program = tstruct->get_program();
+  if (program != NULL && program != program_) {
+    prefix = capitalize(program->get_name()) + "_types.";
+  }
+  string name = decapitalize(tstruct->get_name());
+  out << "(" << prefix << "read_" << name << " iprot)";
+}
+
+/**
+ * Serialize a container by writing out the header followed by
+ * data and then a footer.
+ */
+void t_ocaml_generator::generate_deserialize_container(ofstream& out, t_type* ttype) {
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+  string con = tmp("_con");
+
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_i8, ktype);
+  t_field fvtype(g_type_i8, vtype);
+  t_field fetype(g_type_i8, etype);
+
+  out << endl;
+  indent_up();
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "(let (" << ktype << "," << vtype << "," << size << ") = iprot#readMapBegin in"
+                << endl;
+    indent(out) << "let " << con << " = Hashtbl.create " << size << " in" << endl;
+    indent_up();
+    indent(out) << "for i = 1 to " << size << " do" << endl;
+    indent_up();
+    indent(out) << "let _k = ";
+    generate_deserialize_type(out, ((t_map*)ttype)->get_key_type());
+    out << " in" << endl;
+    indent(out) << "let _v = ";
+    generate_deserialize_type(out, ((t_map*)ttype)->get_val_type());
+    out << " in" << endl;
+    indent_up();
+    indent(out) << "Hashtbl.add " << con << " _k _v" << endl;
+    indent_down();
+    indent_down();
+    indent(out) << "done; iprot#readMapEnd; " << con << ")";
+    indent_down();
+  } else if (ttype->is_set()) {
+    indent(out) << "(let (" << etype << "," << size << ") = iprot#readSetBegin in" << endl;
+    indent(out) << "let " << con << " = Hashtbl.create " << size << " in" << endl;
+    indent_up();
+    indent(out) << "for i = 1 to " << size << " do" << endl;
+    indent_up();
+    indent(out) << "Hashtbl.add " << con << " ";
+    generate_deserialize_type(out, ((t_set*)ttype)->get_elem_type());
+    out << " true" << endl;
+    indent_down();
+    indent(out) << "done; iprot#readSetEnd; " << con << ")";
+    indent_down();
+  } else if (ttype->is_list()) {
+    indent(out) << "(let (" << etype << "," << size << ") = iprot#readListBegin in" << endl;
+    indent_up();
+    indent(out) << "let " << con << " = (Array.to_list (Array.init " << size << " (fun _ -> ";
+    generate_deserialize_type(out, ((t_list*)ttype)->get_elem_type());
+    out << "))) in" << endl;
+    indent_up();
+    indent(out) << "iprot#readListEnd; " << con << ")";
+    indent_down();
+    indent_down();
+  }
+  indent_down();
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_ocaml_generator::generate_serialize_field(ofstream& out, t_field* tfield, string name) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + tfield->get_name();
+  }
+
+  if (name.length() == 0) {
+    name = decapitalize(tfield->get_name());
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    indent(out) << "oprot#";
+
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        out << "writeString(" << name << ")";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ")";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ")";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ")";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ")";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ")";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ")";
+        break;
+      default:
+        throw "compiler error: no ocaml name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      string ename = capitalize(type->get_name());
+      out << "writeI32(" << ename << ".to_i " << name << ")";
+    }
+
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type->get_name().c_str());
+  }
+  out << ";" << endl;
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_ocaml_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  indent(out) << prefix << "#write(oprot)";
+}
+
+void t_ocaml_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+  if (ttype->is_map()) {
+    indent(out) << "oprot#writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ",";
+    out << type_to_enum(((t_map*)ttype)->get_val_type()) << ",";
+    out << "Hashtbl.length " << prefix << ");" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot#writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ",";
+    out << "Hashtbl.length " << prefix << ");" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot#writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type())
+                << ",";
+    out << "List.length " << prefix << ");" << endl;
+  }
+
+  if (ttype->is_map()) {
+    string kiter = tmp("_kiter");
+    string viter = tmp("_viter");
+    indent(out) << "Hashtbl.iter (fun " << kiter << " -> fun " << viter << " -> " << endl;
+    indent_up();
+    generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+    indent_down();
+    indent(out) << ") " << prefix << ";" << endl;
+  } else if (ttype->is_set()) {
+    string iter = tmp("_iter");
+    indent(out) << "Hashtbl.iter (fun " << iter << " -> fun _ -> ";
+    indent_up();
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+    indent_down();
+    indent(out) << ") " << prefix << ";" << endl;
+  } else if (ttype->is_list()) {
+    string iter = tmp("_iter");
+    indent(out) << "List.iter (fun " << iter << " -> ";
+    indent_up();
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+    indent_down();
+    indent(out) << ") " << prefix << ";" << endl;
+  }
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot#writeMapEnd";
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot#writeSetEnd";
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot#writeListEnd";
+  }
+}
+
+/**
+ * Serializes the members of a map.
+ *
+ */
+void t_ocaml_generator::generate_serialize_map_element(ofstream& out,
+                                                       t_map* tmap,
+                                                       string kiter,
+                                                       string viter) {
+  t_field kfield(tmap->get_key_type(), kiter);
+  generate_serialize_field(out, &kfield);
+
+  t_field vfield(tmap->get_val_type(), viter);
+  generate_serialize_field(out, &vfield);
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_ocaml_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield);
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_ocaml_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield);
+}
+
+/**
+ * Renders a function signature of the form 'name args'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_ocaml_generator::function_signature(t_function* tfunction, string prefix) {
+  return prefix + decapitalize(tfunction->get_name()) + " "
+         + argument_list(tfunction->get_arglist());
+}
+
+string t_ocaml_generator::function_type(t_function* tfunc, bool method, bool options) {
+  string result = "";
+
+  const vector<t_field*>& fields = tfunc->get_arglist()->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result += render_ocaml_type((*f_iter)->get_type());
+    if (options)
+      result += " option";
+    result += " -> ";
+  }
+  if (fields.empty() && !method) {
+    result += "unit -> ";
+  }
+  result += render_ocaml_type(tfunc->get_returntype());
+  return result;
+}
+
+/**
+ * Renders a field list
+ */
+string t_ocaml_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += " ";
+    }
+    result += (*f_iter)->get_name();
+  }
+  return result;
+}
+
+string t_ocaml_generator::type_name(t_type* ttype) {
+  string prefix = "";
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    if (!ttype->is_service()) {
+      prefix = capitalize(program->get_name()) + "_types.";
+    }
+  }
+
+  string name = ttype->get_name();
+  if (ttype->is_service()) {
+    name = capitalize(name);
+  } else {
+    name = decapitalize(name);
+  }
+  return prefix + name;
+}
+
+/**
+ * Converts the parse type to a Protocol.t_type enum
+ */
+string t_ocaml_generator::type_to_enum(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      return "Protocol.T_VOID";
+    case t_base_type::TYPE_STRING:
+      return "Protocol.T_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "Protocol.T_BOOL";
+    case t_base_type::TYPE_I8:
+      return "Protocol.T_BYTE";
+    case t_base_type::TYPE_I16:
+      return "Protocol.T_I16";
+    case t_base_type::TYPE_I32:
+      return "Protocol.T_I32";
+    case t_base_type::TYPE_I64:
+      return "Protocol.T_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "Protocol.T_DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "Protocol.T_I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "Protocol.T_STRUCT";
+  } else if (type->is_map()) {
+    return "Protocol.T_MAP";
+  } else if (type->is_set()) {
+    return "Protocol.T_SET";
+  } else if (type->is_list()) {
+    return "Protocol.T_LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Converts the parse type to an ocaml type
+ */
+string t_ocaml_generator::render_ocaml_type(t_type* type) {
+  type = get_true_type(type);
+
+  if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      return "unit";
+    case t_base_type::TYPE_STRING:
+      return "string";
+    case t_base_type::TYPE_BOOL:
+      return "bool";
+    case t_base_type::TYPE_I8:
+      return "int";
+    case t_base_type::TYPE_I16:
+      return "int";
+    case t_base_type::TYPE_I32:
+      return "Int32.t";
+    case t_base_type::TYPE_I64:
+      return "Int64.t";
+    case t_base_type::TYPE_DOUBLE:
+      return "float";
+    }
+  } else if (type->is_enum()) {
+    return capitalize(((t_enum*)type)->get_name()) + ".t";
+  } else if (type->is_struct() || type->is_xception()) {
+    return type_name((t_struct*)type);
+  } else if (type->is_map()) {
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    return "(" + render_ocaml_type(ktype) + "," + render_ocaml_type(vtype) + ") Hashtbl.t";
+  } else if (type->is_set()) {
+    t_type* etype = ((t_set*)type)->get_elem_type();
+    return "(" + render_ocaml_type(etype) + ",bool) Hashtbl.t";
+  } else if (type->is_list()) {
+    t_type* etype = ((t_list*)type)->get_elem_type();
+    return render_ocaml_type(etype) + " list";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+THRIFT_REGISTER_GENERATOR(ocaml, "OCaml", "")

http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_oop_generator.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_oop_generator.h b/compiler/cpp/src/thrift/generate/t_oop_generator.h
new file mode 100644
index 0000000..8fb580d
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_oop_generator.h
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef T_OOP_GENERATOR_H
+#define T_OOP_GENERATOR_H
+
+#include <string>
+#include <iostream>
+
+#include "thrift/common.h"
+#include "thrift/generate/t_generator.h"
+
+#include <algorithm>
+
+/**
+ * Class with utility methods shared across common object oriented languages.
+ * Specifically, most of this stuff is for C++/Java.
+ *
+ */
+class t_oop_generator : public t_generator {
+public:
+  t_oop_generator(t_program* program) : t_generator(program) {}
+
+  /**
+   * Scoping, using curly braces!
+   */
+
+  void scope_up(std::ostream& out) {
+    indent(out) << "{" << std::endl;
+    indent_up();
+  }
+
+  void scope_down(std::ostream& out) {
+    indent_down();
+    indent(out) << "}" << std::endl;
+  }
+
+  std::string upcase_string(std::string original) {
+    std::transform(original.begin(), original.end(), original.begin(), (int (*)(int))toupper);
+    return original;
+  }
+
+  virtual std::string get_enum_class_name(t_type* type) {
+    std::string package = "";
+    t_program* program = type->get_program();
+    if (program != NULL && program != program_) {
+      package = program->get_namespace("java") + ".";
+    }
+    return package + type->get_name();
+  }
+
+  virtual void generate_java_docstring_comment(std::ofstream& out, std::string contents) {
+    generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
+  }
+
+  virtual void generate_java_doc(std::ofstream& out, t_field* field) {
+    if (field->get_type()->is_enum()) {
+      std::string combined_message = field->get_doc() + "\n@see "
+                                     + get_enum_class_name(field->get_type());
+      generate_java_docstring_comment(out, combined_message);
+    } else {
+      generate_java_doc(out, (t_doc*)field);
+    }
+  }
+
+  /**
+   * Emits a JavaDoc comment if the provided object has a doc in Thrift
+   */
+  virtual void generate_java_doc(std::ofstream& out, t_doc* tdoc) {
+    if (tdoc->has_doc()) {
+      generate_java_docstring_comment(out, tdoc->get_doc());
+    }
+  }
+
+  /**
+   * Emits a JavaDoc comment if the provided function object has a doc in Thrift
+   */
+  virtual void generate_java_doc(std::ofstream& out, t_function* tfunction) {
+    if (tfunction->has_doc()) {
+      std::stringstream ss;
+      ss << tfunction->get_doc();
+      const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+      std::vector<t_field*>::const_iterator p_iter;
+      for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
+        t_field* p = *p_iter;
+        ss << "\n@param " << p->get_name();
+        if (p->has_doc()) {
+          ss << " " << p->get_doc();
+        }
+      }
+      generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n");
+    }
+  }
+};
+
+#endif