THRIFT-27 : use default values when generating erlang records
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1086752 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 0f9a822..fec56bc 100644
--- a/compiler/cpp/src/generate/t_erl_generator.cc
+++ b/compiler/cpp/src/generate/t_erl_generator.cc
@@ -68,7 +68,11 @@
void generate_struct (t_struct* tstruct);
void generate_xception (t_struct* txception);
void generate_service (t_service* tservice);
+ void generate_member_type(std::ostream & out, t_type* type);
+ void generate_member_value(std::ostream & out, t_type* type, t_const_value* value);
+ std::string render_member_type(t_type* type);
+ std::string render_default_value(t_type* type);
std::string render_const_value(t_type* type, t_const_value* value);
/**
@@ -77,6 +81,7 @@
void generate_erl_struct(t_struct* tstruct, bool is_exception);
void generate_erl_struct_definition(std::ostream& out, std::ostream& hrl_out, t_struct* tstruct, bool is_xception=false, bool is_result=false);
+ void generate_erl_struct_member(std::ostream& out, t_field * tmember);
void generate_erl_struct_info(std::ostream& out, t_struct* tstruct);
void generate_erl_function_helpers(t_function* tfunction);
@@ -95,7 +100,6 @@
std::string erl_autogen_comment();
std::string erl_imports();
std::string render_includes();
- std::string declare_field(t_field* tfield);
std::string type_name(t_type* ttype);
std::string function_signature(t_function* tfunction, std::string prefix="");
@@ -116,6 +120,8 @@
return in;
}
+ static std::string comment(string in);
+
private:
/**
@@ -247,6 +253,21 @@
}
/**
+ * Comment out text
+ */
+
+string t_erl_generator::comment(string in)
+{
+ size_t pos = 0;
+ in.insert(pos, "%% ");
+ while ( (pos = in.find_first_of('\n', pos)) != string::npos )
+ {
+ in.insert(++pos, "%% ");
+ }
+ return in;
+}
+
+/**
* Prints standard thrift imports
*/
string t_erl_generator::erl_imports() {
@@ -349,7 +370,7 @@
indent(out) << value->get_integer();
} else if (type->is_struct() || type->is_xception()) {
- out << "#" << type->get_name() << "{";
+ out << "#" << uncapitalize(type->get_name()) << "{";
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
const map<t_const_value*, t_const_value*>& val = value->get_map();
@@ -382,41 +403,37 @@
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
- const map<t_const_value*, t_const_value*>& val = value->get_map();
- map<t_const_value*, t_const_value*>::const_iterator v_iter;
- bool first = true;
- out << "dict:from_list([";
- for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
- if (first) {
- first=false;
- } else {
- out << ",";
+ if ( value->get_map().empty() ) {
+ out << "dict:new()";
+ } else {
+ out << "dict:from_list([";
+ map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
+ for (i = value->get_map().begin(); i != end;) {
+ out << "("
+ << render_const_value(ktype, i->first) << ","
+ << render_const_value(vtype, i->second) << ")";
+ if ( ++i != end ) {
+ out << ",";
+ }
}
- out << "("
- << render_const_value(ktype, v_iter->first) << ","
- << render_const_value(vtype, v_iter->second) << ")";
+ out << "])";
}
- out << "])";
-
} else if (type->is_set()) {
- t_type* etype;
- etype = ((t_set*)type)->get_elem_type();
-
- bool first = true;
- const vector<t_const_value*>& val = value->get_list();
- vector<t_const_value*>::const_iterator v_iter;
- out << "sets:from_list([";
- for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
- if (first) {
- first=false;
- } else {
- out << ",";
+ t_type* etype = ((t_set*)type)->get_elem_type();
+ if ( value->get_list().empty() ) {
+ out << "sets:new()";
+ } else {
+ out << "sets:from_list([";
+ vector<t_const_value*>::const_iterator i, end = value->get_list().end();
+ for( i = value->get_list().begin(); i != end; ) {
+ out << "(" << render_const_value(etype, *i) << ",true)";
+ if ( ++i != end ) {
+ out << ",";
+ }
}
- out << "(" << render_const_value(etype, *v_iter) << ",true)";
+ out << "])";
}
- out << "])";
-
} else if (type->is_list()) {
t_type* etype;
etype = ((t_list*)type)->get_elem_type();
@@ -440,6 +457,53 @@
return out.str();
}
+string t_erl_generator::render_default_value(t_type* type) {
+ if (type->is_struct() || type->is_xception()) {
+ return "#" + uncapitalize(type->get_name()) + "{}";
+ } else if (type->is_map()) {
+ return "dict:new()";
+ } else if (type->is_set()) {
+ return "sets:new()";
+ } else if (type->is_list()) {
+ return "[]";
+ } else {
+ return "";
+ }
+}
+
+
+string t_erl_generator::render_member_type(t_type* type) {
+ type = get_true_type(type);
+ if (type->is_base_type()) {
+ t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+ switch (tbase) {
+ case t_base_type::TYPE_STRING:
+ return "string()";
+ case t_base_type::TYPE_BOOL:
+ return "boolean()";
+ case t_base_type::TYPE_BYTE:
+ case t_base_type::TYPE_I16:
+ case t_base_type::TYPE_I32:
+ case t_base_type::TYPE_I64:
+ return "integer()";
+ case t_base_type::TYPE_DOUBLE:
+ return "float()";
+ default:
+ throw "compiler error: unsupported base type " + t_base_type::t_base_name(tbase);
+ }
+ } else if (type->is_enum()) {
+ return "integer()";
+ } else if (type->is_struct() || type->is_xception()) {
+ } else if (type->is_map()) {
+ } else if (type->is_set()) {
+ } else if (type->is_list()) {
+ return "list()";
+ } else {
+ throw "compiler error: unsupported type " + type->get_name();
+ }
+ return "";
+}
+
/**
* Generates a struct
*/
@@ -477,47 +541,57 @@
bool is_result)
{
(void) is_result;
+ (void) is_exception;
+
+ indent(out) << "%% struct " << type_name(tstruct) << endl << endl;
+
+ std::stringstream buf;
+ buf << indent() << "-record(" << type_name(tstruct) << ", {";
+ string field_indent(buf.str().size(), ' ');
+
const vector<t_field*>& members = tstruct->get_members();
- vector<t_field*>::const_iterator m_iter;
-
- indent(out) << "%% struct " << type_name(tstruct) << endl;
-
- if (is_exception) {
- }
-
- out << endl;
-
- if (members.size() > 0) {
- 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) {
- if (first) {
- first = false;
- } else {
- out << ", ";
- hrl_out << ", ";
- }
- std::string name = uncapitalize((*m_iter)->get_name());
- out << name;
- hrl_out << name;
+ for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end();) {
+ generate_erl_struct_member(buf, *m_iter);
+ if ( ++m_iter != members.end() ) {
+ buf << ", " << endl << field_indent;
}
- out << "})." << endl;
- hrl_out << "})." << endl;
- } else { // no members; explicit comment
- indent(out) << "% -record(" << type_name(tstruct) << ", {})." << endl;
- indent(hrl_out) << "-record(" << type_name(tstruct) << ", {})." << endl;
}
+ buf << "}).";
- out << endl;
- hrl_out << endl;
-
+ hrl_out << buf.str() << endl << endl;
+ out << comment(buf.str()) << endl << endl;
generate_erl_struct_info(out, tstruct);
}
/**
+ * Generates the record field definition
+ */
+
+void t_erl_generator::generate_erl_struct_member(ostream & out, t_field * tmember)
+{
+ out << uncapitalize(tmember->get_name());
+ generate_member_value(out, tmember->get_type(), tmember->get_value());
+ generate_member_type(out, tmember->get_type());
+}
+
+void t_erl_generator::generate_member_type(ostream & out, t_type* type) {
+ string member_type = render_member_type(type);
+ if ( !member_type.empty() ) {
+ out << " :: " << member_type;
+ }
+}
+
+void t_erl_generator::generate_member_value(ostream & out, t_type* type, t_const_value* value) {
+ string member_value = value ? render_const_value(type, value)
+ : render_default_value(type);
+ if ( !member_value.empty() ) {
+ out << " = " << member_value;
+ }
+}
+
+
+/**
* Generates the read method for a struct
*/
void t_erl_generator::generate_erl_struct_info(ostream& out,
@@ -700,23 +774,6 @@
indent_down();
}
-
-/**
- * Declares a field, which may include initialization as necessary.
- *
- * @param ttype The type
- */
-string t_erl_generator::declare_field(t_field* tfield) { // TODO
- string result = "@" + tfield->get_name();
- t_type* type = get_true_type(tfield->get_type());
- if (tfield->get_value() != NULL) {
- result += " = " + render_const_value(type, tfield->get_value());
- } else {
- result += " = nil";
- }
- return result;
-}
-
/**
* Renders a function signature of the form 'type name(args)'
*