THRIFT-860. ocaml: copy method and reset method

The attached patch provides the class copying and reset-to-default values methods.

Patch: Lev Walkin

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@991774 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Bryan Duxbury 2010-09-02 00:07:20 +00:00
parent 38104c8234
commit 0f4078dbf5

View File

@ -68,6 +68,7 @@ class t_ocaml_generator : public t_oop_generator {
bool struct_member_persistent(t_field *tmember);
bool struct_member_omitable(t_field *tmember);
bool struct_member_default_cheaply_comparable(t_field *tmember);
std::string struct_member_copy_of(t_type *type, string what);
/**
* Struct generation code
@ -80,6 +81,8 @@ class t_ocaml_generator : public t_oop_generator {
void generate_ocaml_struct_reader(std::ofstream& out, t_struct* tstruct);
void generate_ocaml_struct_writer(std::ofstream& out, t_struct* tstruct);
void generate_ocaml_function_helpers(t_function* tfunction);
void generate_ocaml_method_copy(std::ofstream& out, const vector<t_field *>& members);
void generate_ocaml_member_copy(std::ofstream& out, t_field *member);
/**
* Service-level generation functions
@ -527,6 +530,78 @@ void t_ocaml_generator::generate_ocaml_struct(t_struct* tstruct,
generate_ocaml_struct_sig(f_types_i_,tstruct,is_exception);
}
void t_ocaml_generator::generate_ocaml_method_copy(ofstream& out,
const vector<t_field *>& members) {
vector<t_field*>::const_iterator m_iter;
/* Create a copy of the current object */
indent(out) << "method copy =" << endl;
indent_up(); indent_up();
indent(out) << "let _new = Oo.copy self in" << endl;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
generate_ocaml_member_copy(out, *m_iter);
indent_down();
indent(out) << "_new" << endl;
indent_down();
}
string t_ocaml_generator::struct_member_copy_of(t_type *type, string what) {
if (type->is_struct() || type->is_xception()) {
return what + string ("#copy");
} if (type->is_map()) {
string copy_of_k = struct_member_copy_of(((t_map *)type)->get_key_type(), "k");
string copy_of_v = struct_member_copy_of(((t_map *)type)->get_val_type(), "v");
if(copy_of_k == "k" && copy_of_v == "v") {
return string ("(Hashtbl.copy ") + what + string(")");
} else {
return string ("((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v -> Hashtbl.add nh ")
+ copy_of_k + string(" ") + copy_of_v
+ string(") oh; nh) ")
+ what + ")";
}
} if (type->is_set()) {
string copy_of = struct_member_copy_of(((t_set *)type)->get_elem_type(), "k");
if(copy_of == "k") {
return string ("(Hashtbl.copy ") + what + string(")");
} else {
return string ("((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v -> Hashtbl.add nh ")
+ copy_of + string(" true")
+ string(") oh; nh) ")
+ what + ")";
}
} if (type->is_list()) {
string copy_of = struct_member_copy_of(((t_list *)type)->get_elem_type(), "x");
if(copy_of != "x") {
return string("(List.map (fun x -> ")
+ copy_of + string (") ")
+ what + string(")");
} else {
return what;
}
}
return what;
}
void t_ocaml_generator::generate_ocaml_member_copy(ofstream& out,
t_field *tmember) {
string mname = decapitalize(tmember->get_name());
t_type* type = get_true_type(tmember->get_type());
string grab_field = string("self#grab_") + mname;
string copy_of = struct_member_copy_of(type, grab_field);
if(copy_of != grab_field) {
indent(out);
if(!struct_member_persistent(tmember)) {
out << "if _" << mname << " <> None then" << endl;
indent(out) << " ";
}
out << "_new#set_" << mname << " " << copy_of << ";" << endl;
}
}
/**
* Generates a struct definition for a thrift data type.
*
@ -546,8 +621,10 @@ void t_ocaml_generator::generate_ocaml_struct_definition(ofstream& out,
if (members.size() > 0) {
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
generate_ocaml_struct_member(out, tname, (*m_iter));
out << endl;
}
}
generate_ocaml_method_copy(out, members);
generate_ocaml_struct_writer(out, tstruct);
indent_down();
indent(out) << "end" << endl;
@ -591,7 +668,20 @@ void t_ocaml_generator::generate_ocaml_struct_member(ofstream& out,
indent(out) << "method get_" << mname << " = _" << mname << endl;
indent(out) << "method grab_" << mname << " = match _"<<mname<<" with None->raise (Field_empty \""<<tname<<"."<<mname<<"\") | Some " << x <<" -> " << x << endl;
indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- Some " << x << endl;
indent(out) << "method unset_" << mname << " = _" << mname << " <- None" << endl;
}
indent(out) << "method reset_" << mname << " = _" << mname << " <- ";
if(val) {
if(struct_member_persistent(tmember))
out << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
else
out << "Some " << render_const_value(tmember->get_type(), tmember->get_value()) << endl;
} else {
out << "None" << endl;
}
}
/**
@ -671,8 +761,12 @@ void t_ocaml_generator::generate_ocaml_struct_sig(ofstream& out,
indent(out) << "method get_" << mname << " : " << type << " option" << endl;
indent(out) << "method grab_" << mname << " : " << type << endl;
indent(out) << "method set_" << mname << " : " << type << " -> unit" << endl;
if(!struct_member_persistent(*m_iter))
indent(out) << "method unset_" << mname << " : unit" << endl;
indent(out) << "method reset_" << mname << " : unit" << endl;
}
}
indent(out) << "method copy : " << tname << endl;
indent(out) << "method write : Protocol.t -> unit" << endl;
indent_down();
indent(out) << "end" << endl;