in thrift/compiler/generate/t_hack_generator.cc [1479:1720]
std::string t_hack_generator::render_const_value_helper(
const t_type* type,
const t_const_value* value,
std::ostream& temp_var_initializations_out,
t_name_generator& namer,
bool immutable_collections) {
std::ostringstream out;
type = type->get_true_type();
if (const auto* tbase_type = dynamic_cast<const t_base_type*>(type)) {
switch (tbase_type->get_base()) {
case t_base_type::TYPE_STRING:
case t_base_type::TYPE_BINARY:
out << render_string(value->get_string());
break;
case t_base_type::TYPE_BOOL:
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:
out << value->get_integer();
break;
case t_base_type::TYPE_DOUBLE:
case t_base_type::TYPE_FLOAT:
if (value->get_type() == t_const_value::CV_INTEGER) {
out << value->get_integer();
} else {
out << value->get_double();
}
if (out.str().find('.') == std::string::npos &&
out.str().find('e') == std::string::npos) {
out << ".0";
}
break;
default:
throw std::runtime_error(
"compiler error: no const of base type " +
t_base_type::t_base_name(tbase_type->get_base()));
}
} else if (const auto* tenum = dynamic_cast<const t_enum*>(type)) {
const t_enum_value* val = tenum->find_value(value->get_integer());
if (val != nullptr) {
out << hack_name(tenum) << "::" << val->name();
} else {
out << hack_name(tenum) << "::coerce(" << value->get_integer() << ")";
}
} else if (const auto* tstruct = dynamic_cast<const t_struct*>(type)) {
auto struct_name = hack_name(type);
if (is_async_struct(tstruct)) {
auto temp_val = namer(("$" + struct_name).c_str());
int preserved_indent_size = get_indent();
set_indent(2);
temp_var_initializations_out << indent() << temp_val << " = "
<< hack_name(type)
<< "::withDefaultValues();\n";
for (const auto& entry : value->get_map()) {
const auto* field =
tstruct->get_field_by_name(entry.first->get_string());
if (field == nullptr) {
throw std::runtime_error(
"type error: " + type->name() + " has no field " +
entry.first->get_string());
}
t_const_value* v = entry.second;
std::stringstream inner;
if (v) {
auto* field_wrapper = find_hack_wrapper(*field);
if (field_wrapper) {
inner << indent() << temp_val << "->get_" << field->name()
<< "()->setValue_DO_NOT_USE_THRIFT_INTERNAL(";
} else {
inner << indent() << temp_val << "->" << field->name() << " = ";
}
inner << render_const_value_helper(
field->get_type(), v, temp_var_initializations_out, namer);
if (field_wrapper) {
inner << ");\n";
} else {
inner << ";\n";
}
}
temp_var_initializations_out << inner.str() << "\n";
}
out << temp_val;
set_indent(preserved_indent_size);
} else {
out << hack_name(type) << "::fromShape(\n";
indent_up();
indent(out) << "shape(\n";
indent_up();
for (const auto& entry : value->get_map()) {
const auto* field =
tstruct->get_field_by_name(entry.first->get_string());
if (field == nullptr) {
throw std::runtime_error(
"type error: " + type->name() + " has no field " +
entry.first->get_string());
}
}
for (const auto& field : tstruct->fields()) {
t_const_value* k = nullptr;
t_const_value* v = nullptr;
for (const auto& entry : value->get_map()) {
if (field.name() == entry.first->get_string()) {
k = entry.first;
v = entry.second;
}
}
if (v != nullptr) {
indent(out) << render_const_value_helper(
&t_base_type::t_string(),
k,
temp_var_initializations_out,
namer)
<< " => "
<< render_const_value_helper(
field.get_type(),
v,
temp_var_initializations_out,
namer)
<< ",\n";
}
}
indent_down();
indent(out) << ")\n";
indent_down();
indent(out) << ")";
}
} else if (const auto* tmap = dynamic_cast<const t_map*>(type)) {
const t_type* ktype = tmap->get_key_type();
const t_type* vtype = tmap->get_val_type();
if (arrays_) {
out << "dict[\n";
} else if (no_use_hack_collections_) {
out << "darray[\n";
} else {
out << (immutable_collections ? "Imm" : "") << "Map {\n";
}
indent_up();
for (const auto& entry : value->get_map()) {
out << indent();
out << render_const_value_helper(
ktype,
entry.first,
temp_var_initializations_out,
namer,
immutable_collections);
out << " => ";
out << render_const_value_helper(
vtype,
entry.second,
temp_var_initializations_out,
namer,
immutable_collections);
out << ",\n";
}
indent_down();
if (arrays_ || no_use_hack_collections_) {
indent(out) << "]";
} else {
indent(out) << "}";
}
} else if (const auto* tlist = dynamic_cast<const t_list*>(type)) {
const t_type* etype = tlist->get_elem_type();
if (arrays_) {
out << "vec[\n";
} else if (no_use_hack_collections_) {
out << "varray[\n";
} else {
out << (immutable_collections ? "Imm" : "") << "Vector {\n";
}
indent_up();
for (const auto* val : value->get_list()) {
out << indent();
out << render_const_value_helper(
etype,
val,
temp_var_initializations_out,
namer,
immutable_collections);
out << ",\n";
}
indent_down();
if (arrays_ || no_use_hack_collections_) {
indent(out) << "]";
} else {
indent(out) << "}";
}
} else if (const auto* tset = dynamic_cast<const t_set*>(type)) {
const t_type* etype = tset->get_elem_type();
indent_up();
const auto& vals = value->get_list();
if (arrays_) {
out << "keyset[\n";
for (const auto* val : vals) {
out << indent();
out << render_const_value_helper(
etype,
val,
temp_var_initializations_out,
namer,
immutable_collections);
out << ",\n";
}
indent_down();
indent(out) << "]";
} else if (arraysets_) {
out << "dict[\n";
for (const auto* val : vals) {
out << indent();
out << render_const_value_helper(
etype,
val,
temp_var_initializations_out,
namer,
immutable_collections);
out << " => true";
out << ",\n";
}
indent_down();
indent(out) << "]";
} else {
out << (immutable_collections ? "Imm" : "") << "Set {\n";
for (const auto* val : vals) {
out << indent();
out << render_const_value_helper(
etype,
val,
temp_var_initializations_out,
namer,
immutable_collections);
out << ",\n";
}
indent_down();
indent(out) << "}";
}
}
return out.str();
}