From: Bryan Duxbury Date: Thu, 2 Sep 2010 00:07:20 +0000 (+0000) Subject: THRIFT-860. ocaml: copy method and reset method X-Git-Tag: 0.5.0~81 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=0f4078dbf5ed39beeacd509f1fab8fcb17d4c44a;p=common%2Fthrift.git 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 4f0a020d..e1875f4e 100644 --- a/compiler/cpp/src/generate/t_ocaml_generator.cc +++ b/compiler/cpp/src/generate/t_ocaml_generator.cc @@ -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& 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& members) { + vector::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 _"<raise (Field_empty \""< " << 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;