From ae1f10f8f296f0e19229994e2ef58569754c66f6 Mon Sep 17 00:00:00 2001 From: Christopher Piro Date: Tue, 24 Jul 2007 04:30:15 +0000 Subject: [PATCH] [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 --- compiler/cpp/src/generate/t_erl_generator.cc | 414 +++++++------------ compiler/cpp/src/generate/t_erl_generator.h | 37 +- lib/erl/lib/thrift/server.sh | 6 + 3 files changed, 188 insertions(+), 269 deletions(-) diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc index 4407cf51..f069b769 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 #include #include @@ -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 @@ void t_erl_generator::init_generator() { // 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 @@ string t_erl_generator::render_includes() { const vector& 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::render_includes() { */ 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 @@ void t_erl_generator::close_generator() { } /** - * 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 @@ void t_erl_generator::generate_typedef(t_typedef* ttypedef) {} * @param tenum The enumeration */ void t_erl_generator::generate_enum(t_enum* tenum) { - //f_types_ << "module " << tenum->get_name() << endl; - //indent_up(); - vector constants = tenum->get_constants(); vector::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 @@ void t_erl_generator::generate_enum(t_enum* tenum) { ++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_enum(t_enum* tenum) { */ 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 @@ void t_erl_generator::generate_const(t_const* tconst) { */ 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 @@ string t_erl_generator::render_const_value(t_type* type, t_const_value* value) { } /** - * 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 @@ void t_erl_generator::generate_xception(t_struct* txception) { } /** - * Generates a ruby struct + * Generates a struct */ void t_erl_generator::generate_erl_struct(t_struct* tstruct, bool is_exception) { @@ -305,9 +305,7 @@ void t_erl_generator::generate_erl_struct(t_struct* tstruct, } /** - * 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 @@ void t_erl_generator::generate_erl_struct_definition(ostream& out, ostream& hrl_out, t_struct* tstruct, bool is_exception, - bool is_result) { + bool is_result) +{ const vector& members = tstruct->get_members(); vector::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; 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 @@ void t_erl_generator::generate_erl_struct_definition(ostream& out, 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 @@ void t_erl_generator::generate_erl_struct_reader(ostream& out, const vector& fields = tstruct->get_members(); vector::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 @@ void t_erl_generator::generate_erl_struct_reader(ostream& out, 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 @@ void t_erl_generator::generate_erl_struct_reader(ostream& out, 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; - indent_up(); - indent(out) << "Ftype == ?tType_STOP ->" << endl << - indent() << " Str;" << endl; - - // indent() << "true ->" << endl; - - // if (fields.size() > 0) { - // indent(out) << - // "end" << endl; - // } - - // 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"); + // Check for field STOP marker and break + indent(out) << "if" << endl; + indent_up(); + indent(out) << "Ftype == ?tType_STOP ->" << endl << + indent() << " Str;" << endl; - 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(); - } + // 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; - // 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()" <get_name() + << "=Val});" << 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& fields = tstruct->get_members(); vector::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 @@ void t_erl_generator::generate_erl_struct_writer(ostream& out, // TODO * @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 @@ void t_erl_generator::generate_service(t_service* tservice) { } 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 @@ void t_erl_generator::generate_service(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::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 @@ void t_erl_generator::generate_service_interface(t_service* tservice) { indent() << "% " << function_signature(*f_iter) << endl; } // indent_down(); - indent(f_service_) << endl << endl; + indent(f_service_) << endl; } /** @@ -699,15 +628,15 @@ void t_erl_generator::generate_service_client(t_service* tservice) { export_string("new", 1); f_service_ << - indent() << "new(Iprot, Oprot) -> % generate_service_client" << endl << - indent() << " #"<" << endl << + indent() << " #"<" << endl << - indent() << " #"< functions = tservice->get_functions(); @@ -722,7 +651,7 @@ void t_erl_generator::generate_service_client(t_service* tservice) { // 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 @@ void t_erl_generator::generate_service_client(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_client(t_service* tservice) { // 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 @@ void t_erl_generator::generate_service_client(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_client(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_server(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_server(t_service* tservice) { indent_up(); + // TODO: inheritance runtime code (prolly) goes here: + // f_service_ << // indent() << "include Iface" << endl << // indent() << "include TProcessor" << endl << @@ -911,10 +840,8 @@ void t_erl_generator::generate_service_server(t_service* tservice) { } 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 @@ void t_erl_generator::generate_service_server(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_server(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_server(t_service* tservice) { 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 @@ void t_erl_generator::generate_service_server(t_service* tservice) { * @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 @@ void t_erl_generator::generate_process_function(t_service* tservice, 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 @@ void t_erl_generator::generate_process_function(t_service* tservice, 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; + indent(f_service_) << "{error, E} when is_record(E, " << uncapitalize((*x_iter)->get_type()->get_name()) << ") ->" << endl; + indent_up(); - //"" << (*x_iter)->get_type()->get_name() << "} -> " << "% TODO investigate this" << endl; + indent(f_service_) << "#" << resultname << "{" << (*x_iter)->get_name() << " = E};" << 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_up(); - indent(f_service_) << "true -> throw(cpiro_if_nomatch) % TODO(cpiro): spirit foul" << 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 @@ void t_erl_generator::generate_process_function(t_service* tservice, indent(f_service_) << "Result." << endl << endl; - // Close function indent_down(); - // indent(f_service_); } /** @@ -1137,7 +1039,6 @@ void t_erl_generator::generate_deserialize_field(ostream &out, 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 @@ void t_erl_generator::generate_deserialize_field(ostream &out, } 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 @@ void t_erl_generator::generate_deserialize_field(ostream &out, /** * 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 @@ void t_erl_generator::generate_deserialize_set_element(ostream &out, // TODO /** * 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 @@ void t_erl_generator::generate_serialize_field(ostream &out, } 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_field(ostream &out, 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 @@ void t_erl_generator::generate_serialize_container(ostream &out, "?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 @@ void t_erl_generator::generate_serialize_container(ostream &out, 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 @@ void t_erl_generator::generate_serialize_container(ostream &out, * 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 @@ void t_erl_generator::generate_serialize_map_element(ostream &out, // TODO /** * 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 @@ void t_erl_generator::generate_serialize_set_element(ostream &out, // TODO /** * 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::declare_field(t_field* tfield) { // TODO */ 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 @@ void t_erl_generator::export_types_function(t_function* tfunction, + ((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 @@ void t_erl_generator::export_function(t_function* tfunction, /** * 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& fields = tstruct->get_members(); @@ -1574,7 +1473,7 @@ string t_erl_generator::argument_list(t_struct* tstruct) { // TODO? 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 @@ string t_erl_generator::argument_list(t_struct* tstruct) { // TODO? 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 @@ string t_erl_generator::type_to_enum(t_type* type) { 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 d54514ed..cf2c87bc 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,26 +144,37 @@ class t_erl_generator : public t_oop_generator { private: + /** + * 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_; - // f_types_ - // f_consts_ - // f_service_ - /** * File streams */ - 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); - 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 c02c0e4e..4247c984 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 && -- 2.17.1