[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 &&