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
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 05b4331..e22830e 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -373,29 +373,53 @@
vector<t_field*>::const_iterator m_iter;
const vector<t_field*>& 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 @@
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 ffe8b2a..e3a3166 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -146,23 +146,25 @@
* 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<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();
map<t_const_value*, t_const_value*>::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 @@
}
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 @@
}
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 @@
vector<t_field*>::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 @@
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 @@
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 @@
indent() << "TList " << obj << " = iprot.readListBegin();" << endl;
}
-
// For loop iterates over elements
string i = tmp("_i");
indent(out) <<
@@ -1259,9 +1274,9 @@
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 @@
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 @@
} 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 35748e5..3c7680e 100644
--- a/compiler/cpp/src/generate/t_java_generator.h
+++ b/compiler/cpp/src/generate/t_java_generator.h
@@ -40,7 +40,7 @@
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 @@
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 5418733..903aac0 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -123,7 +123,7 @@
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 @@
* 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<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
@@ -177,30 +181,30 @@
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<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::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 @@
} else {
etype = ((t_set*)type)->get_elem_type();
}
- f_consts_ << "array(" << endl;
+ out << "array(" << endl;
indent_up();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::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 @@
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 @@
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 @@
"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 ddea1a2..8b9e971 100644
--- a/compiler/cpp/src/generate/t_php_generator.h
+++ b/compiler/cpp/src/generate/t_php_generator.h
@@ -43,7 +43,7 @@
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 daf56bf..5190de3 100644
--- a/compiler/cpp/src/generate/t_py_generator.cc
+++ b/compiler/cpp/src/generate/t_py_generator.cc
@@ -123,8 +123,7 @@
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 @@
* 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<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
@@ -178,30 +179,30 @@
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<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::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 @@
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<t_const_value*>& val = value->get_list();
vector<t_const_value*>::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 @@
"pass" <<endl;
} else {
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- if (is_result) {
- indent(out) <<
- "self." << (*m_iter)->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 @@
*
* @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 c0afe60..e849e6b 100644
--- a/compiler/cpp/src/generate/t_py_generator.h
+++ b/compiler/cpp/src/generate/t_py_generator.h
@@ -38,7 +38,7 @@
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 @@
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 e33a5ec..4636e43 100644
--- a/compiler/cpp/src/generate/t_rb_generator.cc
+++ b/compiler/cpp/src/generate/t_rb_generator.cc
@@ -132,8 +132,7 @@
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 @@
* 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<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
@@ -187,30 +187,30 @@
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<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::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 @@
etype = ((t_set*)type)->get_elem_type();
}
if (type->is_set()) {
- f_consts_ << "{";
+ out << "{";
} else {
- f_consts_ << "[" << endl;
+ out << "[" << endl;
}
indent_up();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::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 @@
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 @@
*
* @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 9299f3e..bb74db6 100644
--- a/compiler/cpp/src/generate/t_rb_generator.h
+++ b/compiler/cpp/src/generate/t_rb_generator.h
@@ -38,7 +38,7 @@
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 @@
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 24dca83..a582436 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -415,6 +415,13 @@
}
/**
+ * 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
*/
void parse(t_program* program, t_program* parent_program) {
diff --git a/compiler/cpp/src/main.h b/compiler/cpp/src/main.h
index a7c1d3d..470ac7f 100644
--- a/compiler/cpp/src/main.h
+++ b/compiler/cpp/src/main.h
@@ -3,6 +3,7 @@
#include <string>
#include "parse/t_const.h"
+#include "parse/t_field.h"
/**
* Defined in the flex library
@@ -38,6 +39,11 @@
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
*/
std::string program_name(std::string filename);
diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h
index 35414ef..058b9fb 100644
--- a/compiler/cpp/src/parse/t_field.h
+++ b/compiler/cpp/src/parse/t_field.h
@@ -15,12 +15,14 @@
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 @@
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 a90d64b..a6492fe 100644
--- a/compiler/cpp/src/thrifty.yy
+++ b/compiler/cpp/src/thrifty.yy
@@ -123,7 +123,9 @@
%type<ttype> DefinitionType
%type<tfield> Field
+%type<iconst> FieldIdentifier
%type<ttype> FieldType
+%type<tconstv> FieldValue
%type<tstruct> FieldList
%type<tenum> Enum
@@ -575,32 +577,46 @@
}
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(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $1, $4);
- $1 = y_field_val--;
+ 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($3, $4, $1);
+ $$ = new t_field($2, $3, $1);
+ if ($4 != NULL) {
+ validate_field_value($$, $4);
+ $$->set_value($4);
+ }
$$->set_xsd_optional($5);
}
-| FieldType tok_identifier XsdOptional CommaOrSemicolonOptional
+
+FieldIdentifier:
+ tok_int_constant ':'
{
- 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);
- }
-| FieldType tok_identifier '=' tok_int_constant CommaOrSemicolonOptional
- {
- 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 ($1 <= 0) {
+ pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n", $1);
+ $1 = y_field_val--;
}
- $$ = new t_field($1, $2, $4);
+ $$ = $1;
+ }
+|
+ {
+ $$ = y_field_val--;
+ }
+
+FieldValue:
+ '=' ConstValue
+ {
+ if (g_parse_mode == PROGRAM) {
+ $$ = $2;
+ } else {
+ $$ = NULL;
+ }
+ }
+|
+ {
+ $$ = NULL;
}
DefinitionType: