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
diff --git a/compiler/cpp/src/generate/t_ocaml_generator.cc b/compiler/cpp/src/generate/t_ocaml_generator.cc
index 4f0a020..e1875f4 100644
--- a/compiler/cpp/src/generate/t_ocaml_generator.cc
+++ b/compiler/cpp/src/generate/t_ocaml_generator.cc
@@ -68,6 +68,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;