[thrift] misc. Erlang codegen improvements, cleanups

Summary:
 * const/enum namespacing
 * better formatting, less debugging comments in both source and gen-erl/

Notes:
 * in preparation for iproctor's whiz-bang map/list/set support


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665169 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc
index 4407cf5..f069b76 100644
--- a/compiler/cpp/src/generate/t_erl_generator.cc
+++ b/compiler/cpp/src/generate/t_erl_generator.cc
@@ -4,6 +4,8 @@
 // See accompanying file LICENSE or visit the Thrift site at:
 // http://developers.facebook.com/thrift/
 
+// still missing: inheritance, containers
+
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -12,9 +14,6 @@
 
 using namespace std;
 
-void hrl_header(std::ostream& out, std::string name);
-void hrl_footer(std::ostream& out, std::string name); 
-
 /**
  * UI for file generation by opening up the necessary file output
  * streams.
@@ -25,44 +24,50 @@
   // Make output directory
   mkdir(T_ERL_DIR, S_IREAD | S_IWRITE | S_IEXEC);
 
-  export_types_lines_first_ = export_lines_first_ = true;
+  // setup export lines
+  export_lines_first_ = true;
+  export_types_lines_first_ = true;
 
-  // Make output file
+  // types files
   string f_types_name = string(T_ERL_DIR)+"/"+program_name_+"_types.erl";
   string f_types_hrl_name = string(T_ERL_DIR)+"/"+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_, program_name_ + "_types");
 
-  string f_consts_name = string(T_ERL_DIR)+"/"+program_name_+"_constants.hrl";
-  f_consts_.open(f_consts_name.c_str());
-
-  // Print header
   f_types_file_ <<
     erl_autogen_comment() << endl <<
-    "-module(" << uncapitalize(program_name_) << "_types)." << endl <<
+    "-module(" << program_name_ << "_types)." << endl <<
     erl_imports() << endl;
 
   f_types_file_ <<
-    "-include(\"" << uncapitalize(program_name_) << "_types.hrl\")." << endl << 
+    "-include(\"" << program_name_ << "_types.hrl\")." << endl << 
     endl;
 
   f_types_hrl_file_ << render_includes() << endl;
-  
+
+  // consts file
+  string f_consts_name = string(T_ERL_DIR)+"/"+program_name_+"_constants.hrl";
+  f_consts_.open(f_consts_name.c_str());
+
   f_consts_ <<
     erl_autogen_comment() << endl <<
     erl_imports() << endl <<
-    "-include(\"" << program_name_ << "_types.hrl\"). % init_generator" << endl <<
+    "-include(\"" << program_name_ << "_types.hrl\")." << endl <<
     endl;
 }
 
-void hrl_header(ostream& out, string name) {
+/**
+ * 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 hrl_footer(ostream& out, string name) {
+void t_erl_generator::hrl_footer(ostream& out, string name) {
   out << "-endif." << endl;
 }
 
@@ -73,7 +78,7 @@
   const vector<t_program*>& includes = program_->get_includes();
   string result = "";
   for (size_t i = 0; i < includes.size(); ++i) {
-    result += "-include(\"" + includes[i]->get_name() + "_types.hrl\"). % render_includes\n";
+    result += "-include(\"" + includes[i]->get_name() + "_types.hrl\").\n";
   }
   if (includes.size() > 0) {
     result += "\n";
@@ -86,11 +91,11 @@
  */
 string t_erl_generator::erl_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" +
-    "%\n";
+    std::string("%%\n") +
+    "%% Autogenerated by Thrift\n" +
+    "%%\n" +
+    "%% DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
+    "%%\n";
 }
 
 /**
@@ -119,11 +124,12 @@
 }
 
 /**
- * Generates a typedef. This is not done in Ruby, types are all implicit.
+ * Generates a typedef. no op
  *
  * @param ttypedef The type definition
  */
-void t_erl_generator::generate_typedef(t_typedef* ttypedef) {}
+void t_erl_generator::generate_typedef(t_typedef* ttypedef) {
+}
 
 /**
  * Generates code for an enumerated type. Done using a class to scope
@@ -132,12 +138,11 @@
  * @param tenum The enumeration
  */
 void t_erl_generator::generate_enum(t_enum* tenum) {
-  //f_types_ << "module " << tenum->get_name() << endl;
-  //indent_up();
-  
   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) {
     if ((*c_iter)->has_value()) {
       value = (*c_iter)->get_value();
@@ -145,16 +150,12 @@
       ++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());
     
     f_types_hrl_file_ <<
-      indent() << "-define(" << name << ", " << value << ")."<< endl;
+      indent() << "-define(" << program_name_ << "_" << name << ", " << value << ")."<< endl;
   }
 
-  //  indent_down();
   f_types_hrl_file_ << endl;
 }
 
@@ -163,12 +164,10 @@
  */
 void t_erl_generator::generate_const(t_const* tconst) {
   t_type* type = tconst->get_type();
-  string name = tconst->get_name();
+  string name = capitalize(tconst->get_name());
   t_const_value* value = tconst->get_value();
   
-  name[0] = toupper(name[0]);
-
-  f_consts_ << "-define(" << name << ", " << render_const_value(type, value) << ")." << endl << endl;
+  f_consts_ << "-define(" << program_name_ << "_" << name << ", " << render_const_value(type, value) << ")." << endl << endl;
 }
 
 /**
@@ -178,6 +177,7 @@
  */
 string t_erl_generator::render_const_value(t_type* type, t_const_value* value) {
   std::ostringstream out;
+
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
     switch (tbase) {
@@ -280,7 +280,7 @@
 }
 
 /**
- * Generates a ruby struct
+ * Generates a struct
  */
 void t_erl_generator::generate_struct(t_struct* tstruct) {
   generate_erl_struct(tstruct, false);
@@ -297,7 +297,7 @@
 }
 
 /**
- * Generates a ruby struct
+ * Generates a struct
  */
 void t_erl_generator::generate_erl_struct(t_struct* tstruct,
                                         bool is_exception) {
@@ -305,9 +305,7 @@
 }
 
 /**
- * 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...)
+ * Generates a struct definition for a thrift data type.
  *
  * @param tstruct The struct definition
  */
@@ -315,24 +313,21 @@
 						     ostream& hrl_out,
                                                    t_struct* tstruct,
                                                    bool is_exception,
-                                                   bool is_result) {
+                                                   bool is_result) 
+{
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter; 
 
-  //  indent_up(); // indent removeme
-
   indent(out) << "%% struct " << type_name(tstruct) << endl;
 
-  if (is_exception) { // TODO
-    out << "% RUBY( < StandardError) % TODO";
+  if (is_exception) { 
   }
-  out << endl;
-  //  indent_up();
 
-///   out << endl;
+  out << endl;
+
   if (members.size() > 0) {
-    indent(out)     << "% -record(" << uncapitalize(type_name(tstruct)) << ", {";
-    indent(hrl_out) <<   "-record(" << uncapitalize(type_name(tstruct)) << ", {";
+    indent(out)     << "% -record(" << type_name(tstruct) << ", {";
+    indent(hrl_out) <<   "-record(" << type_name(tstruct) << ", {";
 
     bool first = true;
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
@@ -348,50 +343,15 @@
     out     << "})." << endl;
     hrl_out << "})." << endl;
   } else { // no members; explicit comment
-    indent(out)     << "% -record(" << uncapitalize(type_name(tstruct)) << ", {}). % empty struct" << endl;
-    indent(hrl_out) <<   "-record(" << uncapitalize(type_name(tstruct)) << ", {}). % empty struct" << endl;
+    indent(out)     << "% -record(" << type_name(tstruct) << ", {})." << endl;
+    indent(hrl_out) <<   "-record(" << type_name(tstruct) << ", {})." << endl;
   }
   
-    // no constructors : use #myStruct{} and #myStruct{field=Val}
-    
-///     out <<
-///       indent() << "" << uncapitalize(type_name(tstruct)) << "(d=nil)" << endl;
-///   indent_up();
-/// 
-///   if (members.size() > 0) {
-///     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-///       if ((*m_iter)->get_value() != NULL) {
-///         indent(out) << declare_field(*m_iter) << endl;
-///       }
-///     }
-///     indent(out) <<
-///       "if (d != nil)" << endl;
-///     indent_up();
-///     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-///       out <<
-///         indent() << "if (d.has_key?('" << (*m_iter)->get_name() << "'))" << endl <<
-///         indent() << "  @" << (*m_iter)->get_name() << " = d['" << (*m_iter)->get_name() << "']" << endl <<
-///         indent() << "end" << endl;
-///     }
-///     indent_down();
-///     indent(out) << "end" << endl;
-///   }
-///   
-///   indent_down();
-///   indent(out) << "end" << endl;
-///  
-///   out << endl;
-/// 
-
   out << endl;
   hrl_out << endl;
 
-
   generate_erl_struct_reader(out, tstruct);
   generate_erl_struct_writer(out, tstruct);
-
-  //indent_down();
-  //  indent(out) << "end" << endl << endl;
 }
 
 /**
@@ -402,9 +362,9 @@
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
-  string name = uncapitalize(type_name(tstruct)) + "_read";
+  string name = type_name(tstruct) + "_read";
 
-  if(out == f_types_) { // TODO(cpiro): omfg please ftlog do this right
+  if(out == f_types_) { // OH HAI MR. HORRIBLE
     export_types_string(name, 1);
   } else {
     export_string(name, 1);
@@ -415,13 +375,10 @@
     
   out <<
     indent() << "?R0(Iprot, readStructBegin)," << endl <<   
-    indent() << "Str = " << uncapitalize(type_name(tstruct)) << "_read_loop(Iprot, ";
+    indent() << "Str = " << type_name(tstruct) << "_read_loop(Iprot, ";
 
-  //  if (fields.size() > 0) { // cpiro: sensible default for non-empty structs
-    out << "#" << uncapitalize(type_name(tstruct)) << "{}";
-    //  } else {
-    //    out << "empty_struct";
-    //  }
+  // empty struct
+  out << "#" << type_name(tstruct) << "{}";
 
   out << ")," << endl <<
     indent() << "?R0(Iprot, readStructEnd)," << endl <<
@@ -430,101 +387,72 @@
   indent_down();
 
   indent(out) <<
-    "" << uncapitalize(type_name(tstruct)) << "_read_loop(Iprot, Str) ->" << endl;
+    "" << type_name(tstruct) << "_read_loop(Iprot, Str) ->" << endl;
   indent_up();
 
-    // Read beginning field marker
+  // Read beginning field marker
   out <<
     indent() << "{ _Fname, Ftype, Fid } = ?R0(Iprot, readFieldBegin)," << endl <<
     indent() << "Fid, % suppress unused warnings" << endl;
 
-    // Check for field STOP marker and break
-    indent(out) << "if" << endl;
+  // Check for field STOP marker and break
+  indent(out) << "if" << endl;
+  indent_up();
+  indent(out) << "Ftype == ?tType_STOP ->" << endl <<
+    indent() << "  Str;" << endl;
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out << indent() << "(Fid == " << (*f_iter)->get_key() << ") and (Ftype == " 
+	<< type_to_enum((*f_iter)->get_type()) << ") ->" << endl;
+    
     indent_up();
-    indent(out) << "Ftype == ?tType_STOP ->" << endl <<
-      indent() << "  Str;" << endl;
-
-    //      indent() << "true ->" << endl;
-
-    //    if (fields.size() > 0) {
-    //      indent(out) <<
-    //        "end" << endl;
-    //    }
+    generate_deserialize_field(out, *f_iter, "Val");
+    
+    out << indent() << "?R0(Iprot, readFieldEnd)," << endl
+	<< indent() << type_name(tstruct) << "_read_loop(Iprot, "
+	<< "Str#" << type_name(tstruct)
+	<< "{" << (*f_iter)->get_name()
+	<< "=Val});" << 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() << "elsif ";
-      //      }
-      out << indent() << "(Fid == " << (*f_iter)->get_key() << ") and (Ftype == " 
-	  << type_to_enum((*f_iter)->get_type()) << ") ->" << endl;
-
-      indent_up();
-      generate_deserialize_field(out, *f_iter, "Val");
-
-      out << indent() << "?R0(Iprot, readFieldEnd)," << endl
-	  << indent() << uncapitalize(type_name(tstruct)) << "_read_loop(Iprot, "
-	  << "Str#" << uncapitalize(type_name(tstruct))
-	  << "{" << (*f_iter)->get_name()
-	  << "=Val});" << endl;
-      indent_down();
-    }
-    
-    // In the default case we skip the field
-    out <<
-      indent() << "true -> " << endl <<
-      indent() << "  ?R1(Iprot, skip, Ftype)," << endl <<
-      indent() << "  ?R0(Iprot, readFieldEnd)," << endl <<
-      indent() << "  " << uncapitalize(type_name(tstruct)) << "_read_loop(Iprot, Str)" << endl;
-    indent_down();
-    indent(out) << "end." << endl; 
-      
-    // Read field end marker
-    //    indent(out) <<
-    //"iprot.readFieldEnd()" <<endl;
-    
-    //    indent_down();
-    //    indent(out) << "end" << endl;
-
-    //    indent(out) <<
-    //"iprot.readStructEnd()" << endl;
-
-    indent_down();
-    //    indent(out) << "end" << endl;
+  // In the default case we skip the field
+  out <<
+    indent() << "true -> " << endl <<
+    indent() << "  ?R1(Iprot, skip, Ftype)," << endl <<
+    indent() << "  ?R0(Iprot, readFieldEnd)," << endl <<
+    indent() << "  " << type_name(tstruct) << "_read_loop(Iprot, Str)" << endl;
+  indent_down();
+  
+  indent(out) << "end." << endl; 
+  
+  indent_down();
   out << endl;
 }
 
-void t_erl_generator::generate_erl_struct_writer(ostream& out, // TODO
+void t_erl_generator::generate_erl_struct_writer(ostream& out,
                                                t_struct* tstruct) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
-  string fname = uncapitalize(type_name(tstruct)) + "_write";
+  string fname = type_name(tstruct) + "_write";
 
-  if(out == f_types_) { // TODO(cpiro): omfg please ftlog do this right
+  if(out == f_types_) { // OH HAI MR. HORRIBLE
     export_types_string(fname, 2);
   } else {
     export_string(fname, 2);
   }
   
-  indent(out) << fname << "(Str, Oprot) -> %xy" << endl;
+  indent(out) << fname << "(Str, Oprot) ->" << endl;
   indent_up();
   
   out <<
     indent() << "Str, % suppress unused warnings" << endl <<
     indent() << "?R1(Oprot, writeStructBegin, \"" << name << "\")," << endl;
 
-
-  string prefix = string("Str#") + uncapitalize(type_name(tstruct)) + ".";
+  string prefix = string("Str#") + type_name(tstruct) + ".";
 
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     // Write field header
@@ -566,12 +494,12 @@
  * @param tservice The service definition
  */
 void t_erl_generator::generate_service(t_service* tservice) {
-  string f_service_hrl_name = string(T_ERL_DIR)+"/"+uncapitalize(service_name_)+".hrl";
-  string f_service_name = string(T_ERL_DIR)+"/"+uncapitalize(service_name_)+".erl";
+  string f_service_hrl_name = string(T_ERL_DIR)+"/"+service_name_+".hrl";
+  string f_service_name = string(T_ERL_DIR)+"/"+service_name_+".erl";
   f_service_file_.open(f_service_name.c_str());
   f_service_hrl_.open(f_service_hrl_name.c_str());
 
-  hrl_header(f_service_hrl_, uncapitalize(service_name_));
+  hrl_header(f_service_hrl_, service_name_);
 
   if (tservice->get_extends() != NULL) {
     f_service_hrl_ << "-include(\"" << 
@@ -579,7 +507,7 @@
   }
 
   f_service_hrl_ <<
-    "-include(\"" << uncapitalize(program_name_) << "_types.hrl\")." << endl << 
+    "-include(\"" << program_name_ << "_types.hrl\")." << endl << 
     endl;
 
   // Generate the three main parts of the service (well, two for now in PHP)
@@ -593,7 +521,7 @@
 
   f_service_file_ <<
     erl_autogen_comment() << endl <<
-    "-module(" << uncapitalize(service_name_) << ")." << endl << endl <<
+    "-module(" << service_name_ << ")." << endl << endl <<
     erl_imports() << endl;
 
   f_service_file_ << "-include(\"" << uncapitalize(tservice->get_name()) << ".hrl\")." << endl << endl;
@@ -618,11 +546,12 @@
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter;
 
-  indent(f_service_) <<
-    "% HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+  //  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_erl_struct_definition(f_service_, f_service_hrl_, ts, false);
     generate_erl_function_helpers(*f_iter);
   }
@@ -671,7 +600,7 @@
       indent() << "% " << function_signature(*f_iter) << endl;
   }
   //  indent_down();
-  indent(f_service_) << endl << endl;
+  indent(f_service_) << endl;
 }
 
 /**
@@ -699,15 +628,15 @@
   export_string("new", 1);
 
   f_service_ <<
-    indent() << "new(Iprot, Oprot) -> % generate_service_client" << endl <<
-    indent() << "  #"<<uncapitalize(service_name_)<<"{iprot=Iprot, oprot=Oprot, seqid=0}." << endl <<
+    indent() << "new(Iprot, Oprot) ->" << endl <<
+    indent() << "  #"<<service_name_<<"{iprot=Iprot, oprot=Oprot, seqid=0}." << endl <<
     indent() << "new(Iprot) ->" << endl <<
-    indent() << "  #"<<uncapitalize(service_name_)<<"{iprot=Iprot, oprot=Iprot, seqid=0}." << endl << endl;
+    indent() << "  #"<<service_name_<<"{iprot=Iprot, oprot=Iprot, seqid=0}." << endl << endl;
 
   //  indent(f_service_) << "end" << endl << endl;
 
   f_service_hrl_ <<
-    indent() << "-record("<< uncapitalize(service_name_) <<", {iprot, oprot, seqid})." << endl << endl;
+    indent() << "-record("<< service_name_ <<", {iprot, oprot, seqid})." << endl << endl;
 
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
@@ -722,7 +651,7 @@
 
     // Open function
     indent(f_service_) <<
-      function_signature(*f_iter) << " -> % generate_service_client (call)" << endl;
+      function_signature(*f_iter) << " ->" << endl;
 
     indent_up();
 
@@ -756,7 +685,7 @@
     export_function(*f_iter, "send_");
 
     indent(f_service_) <<
-      "send_" << function_signature(*f_iter) << " -> % generate_service_client (send)" << endl;
+      "send_" << function_signature(*f_iter) << " ->" << endl;
     indent_up();
 
       std::string argsname = capitalize((*f_iter)->get_name() + "_args");
@@ -800,11 +729,10 @@
       // Open function
       f_service_ <<
         endl <<
-        indent() << function_signature(&recv_function) << " -> % generate_service_client (recv)" << endl;
+        indent() << function_signature(&recv_function) << " ->" << endl;
       indent_up();
 
       // TODO(mcslee): Validate message reply here, seq ids etc.
-      // TODO(cpiro): actually raise an Erlang exception?
 
       f_service_ <<
 	indent() << "Iprot = oop:get(This, iprot)," << endl <<
@@ -812,7 +740,7 @@
 	indent() << "if" << endl <<
 	indent() << "  Mtype == ?tMessageType_EXCEPTION ->" << endl <<
 	indent() << "    X = tApplicationException:new()," << endl <<
-	indent() << "    tApplicationException:read(X, Iprot), %% cpiro rly treat exceptions different?" << endl <<
+	indent() << "    tApplicationException:read(X, Iprot)," << endl <<
 	indent() << "    ?R0(Iprot, readMessageEnd), " << endl <<
 	indent() << "    {error, X};" << endl <<
 	indent() << "  true ->" << endl <<
@@ -820,12 +748,11 @@
 	indent() << "    ?R0(Iprot, readMessageEnd)," << endl <<
 	indent() << "    if % time to figure out retval" << endl;
 
-	//	indent() << "	 {ok, Success} % result.success casing? Success even for void?" << endl <<
-	//	indent() << "end" << endl;
-
       // WATCH cpiro
       // Careful, only return _result if not a void function
 
+      // TODO(cpiro): exit or {ok, _} and {error, _} ??
+
       std::string result = "Result#"+resultname+".";
       if (!(*f_iter)->get_returntype()->is_void()) {
 	f_service_ <<
@@ -879,7 +806,7 @@
   string extends_processor = "";
   if (tservice->get_extends() != NULL) {
     extends = type_name(tservice->get_extends());
-    extends_processor = " RUBY(< " + extends + "::Processor) "; // TODO(cpiro)
+    extends_processor = " INHERIT(" + extends + "::Processor) % TODO"; 
   }
 
   // Generate the header portion
@@ -888,6 +815,8 @@
 
   indent_up();
 
+  // TODO: inheritance runtime code (prolly) goes here:
+
   //  f_service_ <<
   //    indent() << "include Iface" << endl <<
   //    indent() << "include TProcessor" << endl <<
@@ -911,10 +840,8 @@
   } 
   indent_down();
   indent(f_service_) << "end" << endl << endl;
-*/
-  indent(f_service_) <<
-    "% initialize wuz here" << endl << endl;
- 
+  */
+
   export_string("process", 3);
 
   // Generate the server implementation
@@ -931,14 +858,14 @@
   f_service_ <<
     // try to dispatch to one of our process_*
     indent() << "case Name of" << endl;
-
-    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-      f_service_ <<
-	indent() << "  \"" << (*f_iter)->get_name() << "\" -> process_" << (*f_iter)->get_name() << "(HandlerModule, Seqid, Iprot, Oprot);" << endl;
-    } 
-
-    indent(f_service_) << "  %% TODO(cpiro): pass to super" << endl;
-    indent(f_service_) << "  _ -> % unknown function" << endl <<
+  
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ <<
+      indent() << "  \"" << (*f_iter)->get_name() << "\" -> process_" << (*f_iter)->get_name() << "(HandlerModule, Seqid, Iprot, Oprot);" << endl;
+  } 
+  
+  indent(f_service_) << "  %% TODO(cpiro): pass to super" << endl;
+  indent(f_service_) << "  _UnknownFunction ->" << endl <<
     indent() << "    ?R1(Iprot, skip, ?tType_STRUCT)," << endl <<
     indent() << "    ?R0(Iprot, readMessageEnd)," << endl <<
     indent() << "    X = tApplicationException:new(?tApplicationException_UNKNOWN_METHOD, \"Unknown function \" ++ Name)," << endl <<
@@ -949,7 +876,7 @@
     indent() << "    ?R0(Trans, effectful_flush)," << endl <<
     indent() << "    {error, X} % what's the retval in this case?" << endl <<
     indent() << "end." << endl;
-      //    indent() << "ok. % this one?" << endl << endl;
+
   /*
     indent() << "if (@processMap.has_key?(name))" << endl <<
     indent() << "  @processMap[name].call(seqid, iprot, oprot)" << endl <<
@@ -965,12 +892,7 @@
     indent() << "end" << endl;
   */
 
-  // Read end of args field, the T_STOP, and the struct close
-  //  f_service_ <<
-  //    indent() << "return true" << endl;
-
   indent_down();
-  //  indent(f_service_) << "end" << endl << endl;
 
   // Generate the process subfunctions
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
@@ -987,7 +909,7 @@
  * @param tfunction The function to write a dispatcher for
  */
 void t_erl_generator::generate_process_function(t_service* tservice,
-						t_function* tfunction) { // TODO(cpiro)
+						t_function* tfunction) {
 
   string name = "process_" + tfunction->get_name();
   
@@ -1019,9 +941,8 @@
   if (!tfunction->is_async()) {
   }
 
-
   // Try block for a function with exceptions
-  //  if (xceptions.size() > 0) { // TODO(cpiro)
+  //  if (xceptions.size() > 0) {
   //    f_service_ <<
   //      indent() << "try" << endl;
   //    indent_up();
@@ -1061,39 +982,22 @@
   indent_down();
 
   if (!tfunction->is_async() && xceptions.size() > 0) {
-    indent(f_service_) << "{error, E} ->" << endl;
-    indent_up();
-    indent(f_service_) << "if" << endl;
-
     for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      f_service_ << "";
-	//        indent() << "{error, ?" << (*x_iter)->get_type()->get_name() << "} -> " << "% TODO investigate this" << endl;
-
-	//"" << (*x_iter)->get_type()->get_name() << "} -> " << "% TODO investigate this" << endl;
-
-      if (!tfunction->is_async()) {
-        indent_up();
-        f_service_ <<
-          indent() << "is_record(E, " << uncapitalize((*x_iter)->get_type()->get_name()) << ") -> #" <<
-	  resultname << "{" << (*x_iter)->get_name() << " = E};" << endl;
-	// RUBY(Result.oops = 
-        indent_down();
-      }
+      indent(f_service_) << "{error, E} when is_record(E, " << uncapitalize((*x_iter)->get_type()->get_name()) << ") ->" << endl;
       indent_up();
-      indent(f_service_) << "true -> throw(cpiro_if_nomatch) % TODO(cpiro): spirit foul" << endl;
+
+      indent(f_service_) << "#" << resultname << "{" << (*x_iter)->get_name() << " = E};" << endl;
+
       indent_down();
     }
-    indent(f_service_) << "end;" << endl;
-    indent_down();
   }
-  indent(f_service_) << "dummy -> throw(cpiro_case_nomatch) % TODO(cpiro): gross" << endl;
+
+  indent(f_service_) << "dummy -> dummy % TODO: only for the semicolon's sake" << endl;
   indent_down();
   indent(f_service_) << "end," << endl;
 
-  //indent_down();
-
   if (tfunction->is_async()) { 
-    indent(f_service_) << "% async" << endl;
+    indent(f_service_) << "% async, write nothing" << endl;
   } else {
     f_service_ <<
       indent() << "?R3(Oprot, writeMessageBegin, \"" << tfunction->get_name() << "\", ?tMessageType_REPLY, Seqid)," << endl <<
@@ -1105,9 +1009,7 @@
   
   indent(f_service_) << "Result." << endl << endl;
 
-  // Close function
   indent_down();
-  //  indent(f_service_);
 }
 
 /**
@@ -1137,7 +1039,6 @@
     generate_deserialize_container(out, type, name);
   } else if (type->is_base_type() || type->is_enum()) {
     indent(out) <<
-      //      name << " = iprot.";
       name << " = ?R0(Iprot, ";
     
     if (type->is_base_type()) {
@@ -1174,7 +1075,7 @@
     } else if (type->is_enum()) {
       out << "readI32";
     }
-    out << "), % generate_deserialize_field" << endl;
+    out << ")," << endl;
 
   } else {
     printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
@@ -1185,13 +1086,11 @@
 /**
  * Generates an unserializer for a struct, calling read()
  */
- void t_erl_generator::generate_deserialize_struct(ostream &out, // TODO
+ void t_erl_generator::generate_deserialize_struct(ostream &out,
                                                   t_struct* tstruct,
                                                   string prefix) {
   out <<
-    //    indent() << prefix << " = " << type_name(tstruct) << ":new()" << endl <<
-    //    indent() << prefix << ".read(iprot)" << endl;
-    indent() << prefix << " = " << (tstruct->get_program())->get_name() << "_types:" << uncapitalize(type_name(tstruct)) << "_read(Iprot), % generate_deserialize_struct" << endl;
+    indent() << prefix << " = " << (tstruct->get_program())->get_name() << "_types:" << type_name(tstruct) << "_read(Iprot)," << endl;
 }
 
 /**
@@ -1291,7 +1190,7 @@
 /**
  * Write a list element
  */
-void t_erl_generator::generate_deserialize_list_element(ostream &out,
+void t_erl_generator::generate_deserialize_list_element(ostream &out, // TODO
                                                         t_list* tlist,
                                                         string prefix) {
   string elem = tmp("_elem");
@@ -1373,7 +1272,7 @@
     } else if (type->is_enum()) {
       out << "writeI32, " << name << "),";
     }
-    out << " % generate_serialize_field" << endl;
+    out << "" << endl;
   } else {
     printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
            prefix.c_str(),
@@ -1391,12 +1290,10 @@
 void t_erl_generator::generate_serialize_struct(ostream &out,
                                                t_struct* tstruct,
                                                string prefix) {
-  indent(out) << tstruct->get_program()->get_name() << "_types:" <<  uncapitalize(tstruct->get_name()) << "_write(" << prefix << ", Oprot), % generate_serialize_struct" << endl;
-  //  indent(out) <<
-  //    "?R1(" << prefix << ", write, Oprot), % generate_serialize_struct" << endl;
+  indent(out) << tstruct->get_program()->get_name() << "_types:" <<  uncapitalize(tstruct->get_name()) << "_write(" << prefix << ", Oprot)," << endl;
 }
 
-void t_erl_generator::generate_serialize_container(ostream &out,
+void t_erl_generator::generate_serialize_container(ostream &out, // TODO
                                                   t_type* ttype,
                                                   string prefix) {
   if (ttype->is_map()) {
@@ -1404,20 +1301,20 @@
       "?R3(Oprot, writeMapBegin, " <<
       type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
       type_to_enum(((t_map*)ttype)->get_val_type()) << ", length(" <<
-      prefix << ")), % generate_serialize_container" << endl;
+      prefix << "))," << endl;
   } else if (ttype->is_set()) {
     indent(out) <<
       "?R2(Oprot, writeSetBegin, " <<
       type_to_enum(((t_set*)ttype)->get_elem_type()) << ", length(" <<
-      prefix << ")), % generate_serialize_container" << endl;
+      prefix << "))," << endl;
   } else if (ttype->is_list()) {
     indent(out) <<
       "?R2(Oprot, writeListBegin, " <<
       type_to_enum(((t_list*)ttype)->get_elem_type()) << ", length(" <<
-      prefix << ")), % generate_serialize_container" << endl;
+      prefix << "))," << endl;
   }
 
-  if (ttype->is_map()) { // TODO
+  if (ttype->is_map()) {
     string kiter = tmp("kiter");
     string viter = tmp("viter");
     indent(out) << 
@@ -1447,13 +1344,13 @@
     
   if (ttype->is_map()) {
     indent(out) <<
-      "?R0(Oprot, writeMapEnd), % generate_serialize_container" << endl;
+      "?R0(Oprot, writeMapEnd)," << endl;
   } else if (ttype->is_set()) {
     indent(out) <<
-      "?R0(Oprot, writeSetEnd), % generate_serialize_container" << endl;
+      "?R0(Oprot, writeSetEnd)," << endl;
   } else if (ttype->is_list()) {
     indent(out) <<
-      "?R0(Oprot, writeListEnd), % generate_serialize_container" << endl;
+      "?R0(Oprot, writeListEnd)," << endl;
   }
 }
 
@@ -1461,7 +1358,7 @@
  * Serializes the members of a map.
  *
  */
-void t_erl_generator::generate_serialize_map_element(ostream &out, // TODO
+void t_erl_generator::generate_serialize_map_element(ostream &out,
                                                      t_map* tmap,
                                                      string kiter,
                                                      string viter) {
@@ -1475,7 +1372,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_erl_generator::generate_serialize_set_element(ostream &out, // TODO
+void t_erl_generator::generate_serialize_set_element(ostream &out,
                                                      t_set* tset,
                                                      string iter) {
   t_field efield(tset->get_elem_type(), iter);
@@ -1485,7 +1382,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_erl_generator::generate_serialize_list_element(ostream &out, // TODO
+void t_erl_generator::generate_serialize_list_element(ostream &out,
                                                       t_list* tlist,
                                                       string iter) {
   t_field efield(tlist->get_elem_type(), iter);
@@ -1519,13 +1416,14 @@
  */
 string t_erl_generator::function_signature(t_function* tfunction,
                                            string prefix) {
-  // TODO(mcslee): Nitpicky, no ',' if argument_list is empty
-  // WATCH cpiro: do we really hardcode This into them all?
   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;
@@ -1543,6 +1441,7 @@
 	 + ((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;
@@ -1565,7 +1464,7 @@
 /**
  * Renders a field list
  */
-string t_erl_generator::argument_list(t_struct* tstruct) { // TODO?
+string t_erl_generator::argument_list(t_struct* tstruct) {
   string result = "";
 
   const vector<t_field*>& fields = tstruct->get_members();
@@ -1574,7 +1473,7 @@
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     if (first) {
       first = false;
-      result += ", ";   // WATCH cpiro: initial comma to compensate for initial This
+      result += ", "; // initial comma to compensate for initial This
     } else {
       result += ", ";
     }
@@ -1583,25 +1482,26 @@
   return result;
 }
 
-string t_erl_generator::type_name(t_type* ttype) { // TODO
+string t_erl_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.";
+      prefix = program->get_name() + "_types."; // TODO
     }
   }
 
   string name = ttype->get_name();
+  
   if (ttype->is_struct() || ttype->is_xception()) {
-    name = capitalize(ttype->get_name());
+    name = uncapitalize(ttype->get_name());
   }
 
   return prefix + name;
 }
 
 /**
- * Converts the parse type to a Ruby tyoe
+ * Converts the parse type to a Erlang "type" (macro for int constants)
  */
 string t_erl_generator::type_to_enum(t_type* type) {
   while (type->is_typedef()) {
@@ -1642,5 +1542,3 @@
 
   throw "INVALID TYPE IN type_to_enum: " + type->get_name();
 }
-
-//  LocalWords:  Iprot
diff --git a/compiler/cpp/src/generate/t_erl_generator.h b/compiler/cpp/src/generate/t_erl_generator.h
index d54514e..cf2c87b 100644
--- a/compiler/cpp/src/generate/t_erl_generator.h
+++ b/compiler/cpp/src/generate/t_erl_generator.h
@@ -18,7 +18,11 @@
 class t_erl_generator : public t_oop_generator {
  public:
   t_erl_generator(t_program* program) :
-    t_oop_generator(program) {}
+    t_oop_generator(program) 
+  {
+    program_name_[0] = tolower(program_name_[0]);
+    service_name_[0] = tolower(service_name_[0]);
+  }
 
   /**
    * Init and close methods
@@ -140,18 +144,8 @@
 
  private:
 
-  bool export_lines_first_;
-  std::ostringstream export_lines_;
-
-  bool export_types_lines_first_;
-  std::ostringstream export_types_lines_;
-
-  // f_types_
-  // f_consts_
-  // f_service_
-
   /**
-   * File streams
+   * add function to export list
    */
 
   void export_function(t_function* tfunction, std::string prefix="");
@@ -160,6 +154,27 @@
   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_types_;
   std::ofstream f_types_file_;
   std::ofstream f_types_hrl_file_;
diff --git a/lib/erl/lib/thrift/server.sh b/lib/erl/lib/thrift/server.sh
index c02c0e4..4247c98 100755
--- a/lib/erl/lib/thrift/server.sh
+++ b/lib/erl/lib/thrift/server.sh
@@ -1,4 +1,10 @@
 #!/bin/sh
+if ! [ -d tutorial/gen-erl ]; then
+    echo generating gen-erl
+    cd tutorial
+    thrift -erl -r tutorial.thrift
+    cd ..
+fi
 echo "Compiling user/ and tutorial/gen-erl/..."
 mkdir ebin-user
 erlc -I include -I tutorial/gen-erl -o ebin-user user/*.erl tutorial/gen-erl/*.erl &&