From 7ff3245bfae7c99ac12550ddc252f80ad32dd366 Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Thu, 1 Feb 2007 05:26:18 +0000 Subject: [PATCH] Default values and nullification for thrift code Summary: All things are null now, unless you specify a default value! Reviewed By: marc git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664963 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_cpp_generator.cc | 47 +++++-- compiler/cpp/src/generate/t_java_generator.cc | 61 ++++++--- compiler/cpp/src/generate/t_java_generator.h | 4 +- compiler/cpp/src/generate/t_php_generator.cc | 84 +++++++----- compiler/cpp/src/generate/t_php_generator.h | 2 +- compiler/cpp/src/generate/t_py_generator.cc | 127 +++++++----------- compiler/cpp/src/generate/t_py_generator.h | 4 +- compiler/cpp/src/generate/t_rb_generator.cc | 121 +++++++---------- compiler/cpp/src/generate/t_rb_generator.h | 4 +- compiler/cpp/src/main.cc | 7 + compiler/cpp/src/main.h | 6 + compiler/cpp/src/parse/t_field.h | 11 ++ compiler/cpp/src/thrifty.yy | 48 ++++--- 13 files changed, 283 insertions(+), 243 deletions(-) diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 05b43313..e22830ee 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -373,29 +373,53 @@ void t_cpp_generator::generate_struct_definition(ofstream& out, vector::const_iterator m_iter; const vector& members = tstruct->get_members(); - // Default constructor - bool init_ctor = false; if (!pointers) { + // Default constructor + indent(out) << + tstruct->get_name() << "()"; + + bool init_ctor = false; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); while (t->is_typedef()) { t = ((t_typedef*)t)->get_type(); } - if (t->is_base_type() && - ((t_base_type*)t)->get_base() != t_base_type::TYPE_STRING) { + if (t->is_base_type() || t->is_enum()) { + string dval; + if (t->is_enum()) { + dval += "(" + t->get_name() + ")"; + } + dval += t->is_string() ? "\"\"" : "0"; + t_const_value* cv = (*m_iter)->get_value(); + if (cv != NULL) { + dval = render_const_value(out, (*m_iter)->get_name(), t, cv); + } if (!init_ctor) { init_ctor = true; - indent(out) << - tstruct->get_name() << "() : "; - out << (*m_iter)->get_name() << "(0)"; + out << " : "; + out << (*m_iter)->get_name() << "(" << dval << ")"; } else { - out << ", " << (*m_iter)->get_name() << "(0)"; + out << ", " << (*m_iter)->get_name() << "(" << dval << ")"; } } } - } - if (init_ctor) { - out << " {} " << endl; + out << " {" << endl; + indent_up(); + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + if (!t->is_base_type()) { + t_const_value* cv = (*m_iter)->get_value(); + if (cv != NULL) { + print_const_value(out, (*m_iter)->get_name(), t, cv); + } + } + } + indent_down(); + indent(out) << "} " << endl; } out << @@ -1696,6 +1720,7 @@ void t_cpp_generator::generate_deserialize_container(ofstream& out, string etype = tmp("_etype"); indent(out) << + prefix << ".clear();" << endl << "uint32_t " << size << ";" << endl; // Declare variables, read header diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc index ffe8b2af..e3a31669 100644 --- a/compiler/cpp/src/generate/t_java_generator.cc +++ b/compiler/cpp/src/generate/t_java_generator.cc @@ -146,23 +146,25 @@ void t_java_generator::generate_consts(std::vector consts) { * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ -void t_java_generator::print_const_value(ofstream& out, string name, t_type* type, t_const_value* value, bool in_static) { +void t_java_generator::print_const_value(std::ofstream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) { + + indent(out); + if (!defval) { + out << + (in_static ? "" : "public static final ") << + type_name(type) << " "; + } if (type->is_base_type()) { string v2 = render_const_value(out, name, type, value); - indent(out) << "public static final " << type_name(type) << " " << name << " = " << v2 << ";" << endl << - endl; + out << name << " = " << v2 << ";" << endl << endl; } else if (type->is_enum()) { - indent(out) << "public static final int " << name << " = " << value->get_integer() << ";" << endl << - endl; + out << name << " = " << value->get_integer() << ";" << endl << endl; } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; - indent(out) << - (in_static ? "" : "public static final ") << - type_name(type) << " " << name << - " = new " << type_name(type) << "();" << endl; + out << name << " = new " << type_name(type) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); @@ -187,9 +189,7 @@ void t_java_generator::print_const_value(ofstream& out, string name, t_type* typ } out << endl; } else if (type->is_map()) { - indent(out) << - (in_static ? "" : "public static final ") << - type_name(type, true, true) << " " << name << " = new " << type_name(type, true, true) << "();" << endl; + out << name << " = new " << type_name(type, true, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); @@ -209,9 +209,7 @@ void t_java_generator::print_const_value(ofstream& out, string name, t_type* typ } out << endl; } else if (type->is_list() || type->is_set()) { - indent(out) << - (in_static ? "" : "public static final ") << - type_name(type) << " " << name << " = new " << type_name(type) << "();" << endl; + out << name << " = new " << type_name(type) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); @@ -348,7 +346,7 @@ void t_java_generator::generate_java_struct_definition(ofstream &out, vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << - "public " << declare_field(*m_iter, true) << endl; + "public " << declare_field(*m_iter, false) << endl; } // Inner Isset class @@ -368,6 +366,22 @@ void t_java_generator::generate_java_struct_definition(ofstream &out, endl; } + // Default constructor + indent(out) << + "public " << tstruct->get_name() << "() {" << endl; + indent_up(); + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + if (!t->is_base_type() && (*m_iter)->get_value() != NULL) { + print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); + } + } + indent_down(); + indent(out) << "}" << endl << endl; + generate_java_struct_reader(out, tstruct); if (is_result) { generate_java_struct_result_writer(out, tstruct); @@ -1202,6 +1216,8 @@ void t_java_generator::generate_deserialize_container(ofstream& out, obj = tmp("_list"); } + indent(out) << prefix << " = new " << type_name(ttype, false, true) << "(); // from me" << endl; + // Declare variables, read header if (ttype->is_map()) { out << @@ -1214,7 +1230,6 @@ void t_java_generator::generate_deserialize_container(ofstream& out, indent() << "TList " << obj << " = iprot.readListBegin();" << endl; } - // For loop iterates over elements string i = tmp("_i"); indent(out) << @@ -1259,9 +1274,9 @@ void t_java_generator::generate_deserialize_map_element(ofstream& out, t_field fval(tmap->get_val_type(), val); indent(out) << - declare_field(&fkey, true) << endl; + declare_field(&fkey) << endl; indent(out) << - declare_field(&fval, true) << endl; + declare_field(&fval) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); @@ -1597,13 +1612,15 @@ string t_java_generator::declare_field(t_field* tfield, bool init) { while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } - if (ttype->is_base_type()) { + if (ttype->is_base_type() && tfield->get_value() != NULL) { + ofstream dummy; + result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value()); + } else if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: - // result += " = \"\""; result += " = null"; break; case t_base_type::TYPE_BOOL: @@ -1625,7 +1642,7 @@ string t_java_generator::declare_field(t_field* tfield, bool init) { } else if (ttype->is_container()) { result += " = new " + type_name(ttype, false, true) + "()"; } else { - result += " = null"; + result += " = new " + type_name(ttype, false, true) + "()";; } } return result + ";"; diff --git a/compiler/cpp/src/generate/t_java_generator.h b/compiler/cpp/src/generate/t_java_generator.h index 35748e55..3c7680e2 100644 --- a/compiler/cpp/src/generate/t_java_generator.h +++ b/compiler/cpp/src/generate/t_java_generator.h @@ -40,7 +40,7 @@ class t_java_generator : public t_oop_generator { void generate_xception(t_struct* txception); void generate_service (t_service* tservice); - void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value, bool in_static); + void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval=false); std::string render_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value); /** @@ -138,7 +138,7 @@ class t_java_generator : public t_oop_generator { ttype->is_container() || ttype->is_struct() || ttype->is_xception() || - (ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING)); + ttype->is_string(); } diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc index 5418733a..903aac08 100644 --- a/compiler/cpp/src/generate/t_php_generator.cc +++ b/compiler/cpp/src/generate/t_php_generator.cc @@ -123,7 +123,7 @@ void t_php_generator::generate_const(t_const* tconst) { t_const_value* value = tconst->get_value(); f_consts_ << "$GLOBALS['" << program_name_ << "_CONSTANTS']['" << name << "'] = "; - print_const_value(type, value); + f_consts_ << render_const_value(type, value); f_consts_ << ";" << endl << endl; } @@ -132,36 +132,40 @@ void t_php_generator::generate_const(t_const* tconst) { * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ -void t_php_generator::print_const_value(t_type* type, t_const_value* value) { +string t_php_generator::render_const_value(t_type* type, t_const_value* value) { + std::ostringstream out; + while (type->is_typedef()) { + type = ((t_typedef*)type)->get_type(); + } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: - f_consts_ << "'" << value->get_string() << "'"; + out << "'" << value->get_string() << "'"; break; case t_base_type::TYPE_BOOL: - f_consts_ << (value->get_integer() > 0 ? "true" : "false"); + out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_BYTE: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: - f_consts_ << value->get_integer(); + out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - f_consts_ << value->get_integer(); + out << value->get_integer(); } else { - f_consts_ << value->get_double(); + out << value->get_double(); } break; default: throw "compiler error: no const of base type " + tbase; } } else if (type->is_enum()) { - indent(f_consts_) << value->get_integer(); + indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { - f_consts_ << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl; + out << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; @@ -177,30 +181,30 @@ void t_php_generator::print_const_value(t_type* type, t_const_value* value) { if (field_type == NULL) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } - f_consts_ << indent(); - print_const_value(g_type_string, v_iter->first); - f_consts_ << " => "; - print_const_value(field_type, v_iter->second); - f_consts_ << endl; + out << indent(); + out << render_const_value(g_type_string, v_iter->first); + out << " => "; + out << render_const_value(field_type, v_iter->second); + out << endl; } indent_down(); - indent(f_consts_) << "))"; + indent(out) << "))"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - f_consts_ << "array(" << endl; + out << "array(" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - f_consts_ << indent(); - print_const_value(ktype, v_iter->first); - f_consts_ << " => "; - print_const_value(vtype, v_iter->second); - f_consts_ << "," << endl; + out << indent(); + out << render_const_value(ktype, v_iter->first); + out << " => "; + out << render_const_value(vtype, v_iter->second); + out << "," << endl; } indent_down(); - indent(f_consts_) << ")"; + indent(out) << ")"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { @@ -208,21 +212,22 @@ void t_php_generator::print_const_value(t_type* type, t_const_value* value) { } else { etype = ((t_set*)type)->get_elem_type(); } - f_consts_ << "array(" << endl; + out << "array(" << endl; indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - f_consts_ << indent(); - print_const_value(etype, *v_iter); + out << indent(); + out << render_const_value(etype, *v_iter); if (type->is_set()) { - f_consts_ << " => true"; + out << " => true"; } - f_consts_ << "," << endl; + out << "," << endl; } indent_down(); - indent(f_consts_) << ")"; + indent(out) << ")"; } + return out.str(); } /** @@ -273,8 +278,16 @@ void t_php_generator::generate_php_struct_definition(ofstream& out, indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + string dval = "null"; + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) { + dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value()); + } indent(out) << - "public $" << (*m_iter)->get_name() << " = null;" << endl; + "public $" << (*m_iter)->get_name() << " = " << dval << ";" << endl; } out << endl; @@ -284,6 +297,17 @@ void t_php_generator::generate_php_struct_definition(ofstream& out, out << indent() << "public function __construct($vals=null) {" << endl; indent_up(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) { + indent(out) << "$this->" << (*m_iter)->get_name() << " = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl; + } + } + out << indent() << "if (is_array($vals)) {" << endl; indent_up(); @@ -821,7 +845,7 @@ void t_php_generator::generate_service_rest(t_service* tservice) { "class " << service_name_ << "Rest" << extends_if << " {" << endl; indent_up(); f_service_ << - indent() << "var $impl_;" << endl << + indent() << "private $impl_;" << endl << endl << indent() << "public function __construct($impl) {" << endl << indent() << " $this->impl_ = $impl;" << endl << diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h index ddea1a2f..8b9e9713 100644 --- a/compiler/cpp/src/generate/t_php_generator.h +++ b/compiler/cpp/src/generate/t_php_generator.h @@ -43,7 +43,7 @@ class t_php_generator : public t_oop_generator { void generate_xception (t_struct* txception); void generate_service (t_service* tservice); - void print_const_value (t_type* type, t_const_value* value); + std::string render_const_value(t_type* type, t_const_value* value); /** * Structs! diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc index daf56bf5..5190de37 100644 --- a/compiler/cpp/src/generate/t_py_generator.cc +++ b/compiler/cpp/src/generate/t_py_generator.cc @@ -123,8 +123,7 @@ void t_py_generator::generate_const(t_const* tconst) { string name = tconst->get_name(); t_const_value* value = tconst->get_value(); - indent(f_consts_) << name << " = "; - print_const_value(type, value); + indent(f_consts_) << name << " = " << render_const_value(type, value); f_consts_ << endl << endl; } @@ -133,36 +132,38 @@ void t_py_generator::generate_const(t_const* tconst) { * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ -void t_py_generator::print_const_value(t_type* type, t_const_value* value) { +string t_py_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) { case t_base_type::TYPE_STRING: - f_consts_ << "'" << value->get_string() << "'"; + out << "'" << value->get_string() << "'"; break; case t_base_type::TYPE_BOOL: - f_consts_ << (value->get_integer() > 0 ? "True" : "False"); + out << (value->get_integer() > 0 ? "True" : "False"); break; case t_base_type::TYPE_BYTE: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: - f_consts_ << value->get_integer(); + out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - f_consts_ << value->get_integer(); + out << value->get_integer(); } else { - f_consts_ << value->get_double(); + out << value->get_double(); } break; default: throw "compiler error: no const of base type " + tbase; } } else if (type->is_enum()) { - indent(f_consts_) << value->get_integer(); + indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { - f_consts_ << type->get_name() << "({" << endl; + out << type->get_name() << "({" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; @@ -178,30 +179,30 @@ void t_py_generator::print_const_value(t_type* type, t_const_value* value) { if (field_type == NULL) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } - f_consts_ << indent(); - print_const_value(g_type_string, v_iter->first); - f_consts_ << " : "; - print_const_value(field_type, v_iter->second); - f_consts_ << "," << endl; + out << indent(); + out << render_const_value(g_type_string, v_iter->first); + out << " : "; + out << render_const_value(field_type, v_iter->second); + out << "," << endl; } indent_down(); - indent(f_consts_) << "})"; + indent(out) << "})"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - f_consts_ << "{" << endl; + out << "{" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - f_consts_ << indent(); - print_const_value(ktype, v_iter->first); - f_consts_ << " : "; - print_const_value(vtype, v_iter->second); - f_consts_ << "," << endl; + out << indent(); + out << render_const_value(ktype, v_iter->first); + out << " : "; + out << render_const_value(vtype, v_iter->second); + out << "," << endl; } indent_down(); - indent(f_consts_) << "}"; + indent(out) << "}"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { @@ -210,23 +211,25 @@ void t_py_generator::print_const_value(t_type* type, t_const_value* value) { etype = ((t_set*)type)->get_elem_type(); } if (type->is_set()) { - f_consts_ << "set("; + out << "set("; } - f_consts_ << "[" << endl; + out << "[" << endl; indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - f_consts_ << indent(); - print_const_value(etype, *v_iter); - f_consts_ << "," << endl; + out << indent(); + out << render_const_value(etype, *v_iter); + out << "," << endl; } indent_down(); - indent(f_consts_) << "]"; + indent(out) << "]"; if (type->is_set()) { - f_consts_ << ")"; + out << ")"; } } + + return out.str(); } /** @@ -288,14 +291,9 @@ void t_py_generator::generate_py_struct_definition(ofstream& out, "pass" <get_name() << " = None" << endl; - } else { - // This fills in default values, as opposed to nulls - indent(out) << - declare_field(*m_iter, true) << endl; - } + // This fills in default values, as opposed to nulls + indent(out) << + declare_field(*m_iter) << endl; } indent(out) << @@ -1393,51 +1391,16 @@ void t_py_generator::generate_serialize_list_element(ofstream &out, * * @param ttype The type */ -string t_py_generator::declare_field(t_field* tfield, bool init, bool obj) { +string t_py_generator::declare_field(t_field* tfield) { string result = "self." + tfield->get_name(); - if (init) { - t_type* type = tfield->get_type(); - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - break; - case t_base_type::TYPE_STRING: - result += " = ''"; - break; - case t_base_type::TYPE_BOOL: - result += " = False"; - break; - case t_base_type::TYPE_BYTE: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - result += " = 0"; - break; - case t_base_type::TYPE_DOUBLE: - result += " = 0.0"; - break; - default: - throw "compiler error: no PHP initializer for base type " + tbase; - } - } else if (type->is_enum()) { - result += " = 0"; - } else if (type->is_container()) { - if (type->is_map()) { - result += " = {}"; - } else { - result += " = []"; - } - } else if (type->is_struct() || type->is_xception()) { - if (obj) { - result += " = " + type_name((t_struct*)type) + "()"; - } else { - result += " = None"; - } - } + t_type* type = tfield->get_type(); + while (type->is_typedef()) { + type = ((t_typedef*)type)->get_type(); + } + if (tfield->get_value() != NULL) { + result += " = " + render_const_value(type, tfield->get_value()); + } else { + result += " = None"; } return result; } diff --git a/compiler/cpp/src/generate/t_py_generator.h b/compiler/cpp/src/generate/t_py_generator.h index c0afe60b..e849e6bf 100644 --- a/compiler/cpp/src/generate/t_py_generator.h +++ b/compiler/cpp/src/generate/t_py_generator.h @@ -38,7 +38,7 @@ class t_py_generator : public t_oop_generator { void generate_xception (t_struct* txception); void generate_service (t_service* tservice); - void print_const_value (t_type* type, t_const_value* value); + std::string render_const_value(t_type* type, t_const_value* value); /** * Struct generation code @@ -122,7 +122,7 @@ class t_py_generator : public t_oop_generator { std::string py_autogen_comment(); std::string py_imports(); std::string render_includes(); - std::string declare_field(t_field* tfield, bool init=false, bool obj=false); + std::string declare_field(t_field* tfield); std::string type_name(t_type* ttype); std::string function_signature(t_function* tfunction, std::string prefix=""); std::string argument_list(t_struct* tstruct); diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc index e33a5ec1..4636e43e 100644 --- a/compiler/cpp/src/generate/t_rb_generator.cc +++ b/compiler/cpp/src/generate/t_rb_generator.cc @@ -132,8 +132,7 @@ void t_rb_generator::generate_const(t_const* tconst) { name[0] = toupper(name[0]); - indent(f_consts_) << name << " = "; - print_const_value(type, value); + indent(f_consts_) << name << " = " << render_const_value(type, value); f_consts_ << endl << endl; } @@ -142,36 +141,37 @@ void t_rb_generator::generate_const(t_const* tconst) { * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ -void t_rb_generator::print_const_value(t_type* type, t_const_value* value) { +string t_rb_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) { case t_base_type::TYPE_STRING: - f_consts_ << "'" << value->get_string() << "'"; + out << "'" << value->get_string() << "'"; break; case t_base_type::TYPE_BOOL: - f_consts_ << (value->get_integer() > 0 ? "true" : "false"); + out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_BYTE: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: - f_consts_ << value->get_integer(); + out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - f_consts_ << value->get_integer(); + out << value->get_integer(); } else { - f_consts_ << value->get_double(); + out << value->get_double(); } break; default: throw "compiler error: no const of base type " + tbase; } } else if (type->is_enum()) { - indent(f_consts_) << value->get_integer(); + indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { - f_consts_ << type->get_name() << "({" << endl; + out << type->get_name() << "({" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; @@ -187,30 +187,30 @@ void t_rb_generator::print_const_value(t_type* type, t_const_value* value) { if (field_type == NULL) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } - f_consts_ << indent(); - print_const_value(g_type_string, v_iter->first); - f_consts_ << " => "; - print_const_value(field_type, v_iter->second); - f_consts_ << "," << endl; + out << indent(); + out << render_const_value(g_type_string, v_iter->first); + out << " => "; + out << render_const_value(field_type, v_iter->second); + out << "," << endl; } indent_down(); - indent(f_consts_) << "})"; + indent(out) << "})"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - f_consts_ << "{" << endl; + out << "{" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - f_consts_ << indent(); - print_const_value(ktype, v_iter->first); - f_consts_ << " =>x "; - print_const_value(vtype, v_iter->second); - f_consts_ << "," << endl; + out << indent(); + out << render_const_value(ktype, v_iter->first); + out << " => "; + out << render_const_value(vtype, v_iter->second); + out << "," << endl; } indent_down(); - indent(f_consts_) << "}"; + indent(out) << "}"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { @@ -219,28 +219,29 @@ void t_rb_generator::print_const_value(t_type* type, t_const_value* value) { etype = ((t_set*)type)->get_elem_type(); } if (type->is_set()) { - f_consts_ << "{"; + out << "{"; } else { - f_consts_ << "[" << endl; + out << "[" << endl; } indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - f_consts_ << indent(); - print_const_value(etype, *v_iter); + out << indent(); + out << render_const_value(etype, *v_iter); if (type->is_set()) { - f_consts_ << " => true"; + out << " => true"; } - f_consts_ << "," << endl; + out << "," << endl; } indent_down(); if (type->is_set()) { - indent(f_consts_) << "}"; + indent(out) << "}"; } else { - indent(f_consts_) << "]"; + indent(out) << "]"; } } + return out.str(); } /** @@ -323,6 +324,11 @@ void t_rb_generator::generate_rb_struct_definition(ofstream& out, 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(); @@ -1435,51 +1441,16 @@ void t_rb_generator::generate_serialize_list_element(ofstream &out, * * @param ttype The type */ -string t_rb_generator::declare_field(t_field* tfield, bool init, bool obj) { +string t_rb_generator::declare_field(t_field* tfield) { string result = "@" + tfield->get_name(); - if (init) { - t_type* type = tfield->get_type(); - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - break; - case t_base_type::TYPE_STRING: - result += " = ''"; - break; - case t_base_type::TYPE_BOOL: - result += " = false"; - break; - case t_base_type::TYPE_BYTE: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - result += " = 0"; - break; - case t_base_type::TYPE_DOUBLE: - result += " = 0.0"; - break; - default: - throw "compiler error: no PHP initializer for base type " + tbase; - } - } else if (type->is_enum()) { - result += " = 0"; - } else if (type->is_container()) { - if (type->is_map() || type->is_set()) { - result += " = {}"; - } else { - result += " = []"; - } - } else if (type->is_struct() || type->is_xception()) { - if (obj) { - result += " = " + type_name((t_struct*)type) + "()"; - } else { - result += " = nil"; - } - } + t_type* type = tfield->get_type(); + while (type->is_typedef()) { + type = ((t_typedef*)type)->get_type(); + } + if (tfield->get_value() != NULL) { + result += " = " + render_const_value(type, tfield->get_value()); + } else { + result += " = nil"; } return result; } diff --git a/compiler/cpp/src/generate/t_rb_generator.h b/compiler/cpp/src/generate/t_rb_generator.h index 9299f3ee..bb74db67 100644 --- a/compiler/cpp/src/generate/t_rb_generator.h +++ b/compiler/cpp/src/generate/t_rb_generator.h @@ -38,7 +38,7 @@ class t_rb_generator : public t_oop_generator { void generate_xception (t_struct* txception); void generate_service (t_service* tservice); - void print_const_value (t_type* type, t_const_value* value); + std::string render_const_value(t_type* type, t_const_value* value); /** * Struct generation code @@ -122,7 +122,7 @@ class t_rb_generator : public t_oop_generator { std::string rb_autogen_comment(); std::string rb_imports(); std::string render_includes(); - std::string declare_field(t_field* tfield, bool init=false, bool obj=false); + std::string declare_field(t_field* tfield); std::string type_name(t_type* ttype); std::string function_signature(t_function* tfunction, std::string prefix=""); std::string argument_list(t_struct* tstruct); diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index 24dca83d..a582436a 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -414,6 +414,13 @@ void validate_const_type(t_const* c) { validate_const_rec(c->get_name(), c->get_type(), c->get_value()); } +/** + * Check the type of a default value assigned to a field. + */ +void validate_field_value(t_field* field, t_const_value* cv) { + validate_const_rec(field->get_name(), field->get_type(), cv); +} + /** * Parses a program */ diff --git a/compiler/cpp/src/main.h b/compiler/cpp/src/main.h index a7c1d3d3..470ac7ff 100644 --- a/compiler/cpp/src/main.h +++ b/compiler/cpp/src/main.h @@ -3,6 +3,7 @@ #include #include "parse/t_const.h" +#include "parse/t_field.h" /** * Defined in the flex library @@ -37,6 +38,11 @@ void failure(const char* fmt, ...); */ void validate_const_type(t_const* c); +/** + * Check constant types + */ +void validate_field_value(t_field* field, t_const_value* cv); + /** * Converts a string filename into a thrift program name */ diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h index 35414efe..058b9fbd 100644 --- a/compiler/cpp/src/parse/t_field.h +++ b/compiler/cpp/src/parse/t_field.h @@ -15,12 +15,14 @@ class t_field { type_(type), name_(name), key_(0), + value_(NULL), xsd_optional_(false) {} t_field(t_type* type, std::string name, int32_t key) : type_(type), name_(name), key_(key), + value_(NULL), xsd_optional_(false) {} ~t_field() {} @@ -45,10 +47,19 @@ class t_field { return xsd_optional_; } + void set_value(t_const_value* value) { + value_ = value; + } + + t_const_value* get_value() { + return value_; + } + private: t_type* type_; std::string name_; int32_t key_; + t_const_value* value_; bool xsd_optional_; diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy index a90d64b3..a6492fe9 100644 --- a/compiler/cpp/src/thrifty.yy +++ b/compiler/cpp/src/thrifty.yy @@ -123,7 +123,9 @@ int y_field_val = -1; %type DefinitionType %type Field +%type FieldIdentifier %type FieldType +%type FieldValue %type FieldList %type Enum @@ -575,32 +577,46 @@ FieldList: } Field: - tok_int_constant ':' FieldType tok_identifier XsdOptional CommaOrSemicolonOptional + FieldIdentifier FieldType tok_identifier FieldValue XsdOptional CommaOrSemicolonOptional { pdebug("tok_int_constant : Field -> FieldType tok_identifier"); + if ($1 < 0) { + pwarning(2, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $3); + } + $$ = new t_field($2, $3, $1); + if ($4 != NULL) { + validate_field_value($$, $4); + $$->set_value($4); + } + $$->set_xsd_optional($5); + } + +FieldIdentifier: + tok_int_constant ':' + { if ($1 <= 0) { - pwarning(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $1, $4); + pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n", $1); $1 = y_field_val--; } - $$ = new t_field($3, $4, $1); - $$->set_xsd_optional($5); + $$ = $1; } -| FieldType tok_identifier XsdOptional CommaOrSemicolonOptional +| { - pdebug("Field -> FieldType tok_identifier"); - pwarning(2, "No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", $2); - $$ = new t_field($1, $2, y_field_val--); - $$->set_xsd_optional($3); + $$ = y_field_val--; } -| FieldType tok_identifier '=' tok_int_constant CommaOrSemicolonOptional + +FieldValue: + '=' ConstValue { - pwarning(1, "Trailing = id notation is deprecated. Use 'Id: Type Name' notation instead"); - pdebug("Field -> FieldType tok_identifier = tok_int_constant"); - if ($4 <= 0) { - pwarning(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $4, $2); - $4 = y_field_val--; + if (g_parse_mode == PROGRAM) { + $$ = $2; + } else { + $$ = NULL; } - $$ = new t_field($1, $2, $4); + } +| + { + $$ = NULL; } DefinitionType: -- 2.17.1