cppGenEnum.ml 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. open Ast
  2. open Type
  3. open Error
  4. open Common
  5. open Globals
  6. open CppStrings
  7. open CppExprUtils
  8. open CppTypeUtils
  9. open CppAst
  10. open CppAstTools
  11. open CppSourceWriter
  12. open CppContext
  13. open CppGen
  14. let generate baseCtx enum_def =
  15. let common_ctx = baseCtx.ctx_common in
  16. let class_path = enum_def.e_path in
  17. let just_class_name = (snd class_path) in
  18. let class_name = just_class_name ^ "_obj" in
  19. let remap_class_name = ("::" ^ (join_class_path_remap class_path "::") ) in
  20. let cpp_file = new_placed_cpp_file common_ctx class_path in
  21. let output_cpp = (cpp_file#write) in
  22. let debug = if (Meta.has Meta.NoDebug enum_def.e_meta) || ( Common.defined common_ctx Define.NoDebug) then 0 else 1 in
  23. let ctx = file_context baseCtx cpp_file debug false in
  24. let strq = strq ctx.ctx_common in
  25. let classId = try Hashtbl.find baseCtx.ctx_type_ids (class_text enum_def.e_path) with Not_found -> Int32.zero in
  26. let classIdTxt = Printf.sprintf "0x%08lx" classId in
  27. if (debug>1) then
  28. print_endline ("Found enum definition:" ^ (join_class_path class_path "::" ));
  29. cpp_file#write_h "#include <hxcpp.h>\n\n";
  30. let super_deps = create_super_dependencies common_ctx in
  31. let referenced,flags = CppReferences.find_referenced_types_flags ctx (TEnumDecl enum_def) "*" super_deps (Hashtbl.create 0) false false false in
  32. List.iter (add_include cpp_file) referenced;
  33. begin_namespace output_cpp class_path;
  34. output_cpp "\n";
  35. PMap.iter (fun _ constructor ->
  36. let name = keyword_remap constructor.ef_name in
  37. match constructor.ef_type with
  38. | TFun (args,_) ->
  39. output_cpp (remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ "(" ^
  40. (print_tfun_arg_list true args) ^")\n");
  41. output_cpp ("{\n\treturn ::hx::CreateEnum< " ^ class_name ^ " >(" ^ (strq name) ^ "," ^
  42. (string_of_int constructor.ef_index) ^ "," ^ (string_of_int (List.length args)) ^ ")" );
  43. ExtList.List.iteri (fun i (arg,_,_) -> output_cpp ("->_hx_init(" ^ (string_of_int i) ^ "," ^ (keyword_remap arg) ^ ")")) args;
  44. output_cpp ";\n}\n\n"
  45. | _ ->
  46. output_cpp ( remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ ";\n\n" )
  47. ) enum_def.e_constrs;
  48. let constructor_arg_count constructor =
  49. (match constructor.ef_type with | TFun(args,_) -> List.length args | _ -> 0 )
  50. in
  51. output_cpp ("bool " ^ class_name ^ "::__GetStatic(const ::String &inName, ::Dynamic &outValue, ::hx::PropertyAccess inCallProp)\n{\n");
  52. PMap.iter (fun _ constructor ->
  53. let name = constructor.ef_name in
  54. let dyn = if constructor_arg_count constructor > 0 then "_dyn()" else "" in
  55. output_cpp ("\tif (inName==" ^ strq name ^ ") { outValue = " ^ class_name ^ "::" ^ keyword_remap name ^ dyn ^ "; return true; }\n" );
  56. ) enum_def.e_constrs;
  57. output_cpp ("\treturn super::__GetStatic(inName, outValue, inCallProp);\n}\n\n");
  58. output_cpp ("HX_DEFINE_CREATE_ENUM(" ^ class_name ^ ")\n\n");
  59. output_cpp ("bool " ^ class_name ^ "::_hx_isInstanceOf(int inClassId) {\n");
  60. output_cpp ("\treturn inClassId == (int)0x00000001 || inClassId == ::hx::EnumBase_obj::_hx_ClassId || inClassId == _hx_ClassId;\n");
  61. output_cpp ("}\n");
  62. output_cpp ("int " ^ class_name ^ "::__FindIndex(::String inName)\n{\n");
  63. PMap.iter (fun _ constructor ->
  64. let name = constructor.ef_name in
  65. let idx = string_of_int constructor.ef_index in
  66. output_cpp ("\tif (inName==" ^ (strq name) ^ ") return " ^ idx ^ ";\n") ) enum_def.e_constrs;
  67. output_cpp ("\treturn super::__FindIndex(inName);\n");
  68. output_cpp ("}\n\n");
  69. (* Dynamic versions of constructors *)
  70. let dump_dynamic_constructor _ constr =
  71. let count = constructor_arg_count constr in
  72. if (count>0) then begin
  73. let nargs = string_of_int count in
  74. output_cpp ("STATIC_HX_DEFINE_DYNAMIC_FUNC" ^ nargs ^ "(" ^ class_name ^ "," ^
  75. (keyword_remap constr.ef_name) ^ ",return)\n\n");
  76. end
  77. in
  78. PMap.iter dump_dynamic_constructor enum_def.e_constrs;
  79. output_cpp ("int " ^ class_name ^ "::__FindArgCount(::String inName)\n{\n");
  80. PMap.iter (fun _ constructor ->
  81. let name = constructor.ef_name in
  82. let count = string_of_int (constructor_arg_count constructor) in
  83. output_cpp ("\tif (inName==" ^ (strq name) ^ ") return " ^ count ^ ";\n") ) enum_def.e_constrs;
  84. output_cpp ("\treturn super::__FindArgCount(inName);\n");
  85. output_cpp ("}\n\n");
  86. (* Dynamic "Get" Field function - string version *)
  87. output_cpp ("::hx::Val " ^ class_name ^ "::__Field(const ::String &inName,::hx::PropertyAccess inCallProp)\n{\n");
  88. let dump_constructor_test _ constr =
  89. output_cpp ("\tif (inName==" ^ (strq constr.ef_name) ^ ") return " ^
  90. (keyword_remap constr.ef_name) );
  91. if ( (constructor_arg_count constr) > 0 ) then output_cpp "_dyn()";
  92. output_cpp (";\n")
  93. in
  94. PMap.iter dump_constructor_test enum_def.e_constrs;
  95. output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n");
  96. output_cpp ("static ::String " ^ class_name ^ "_sStaticFields[] = {\n");
  97. let sorted =
  98. List.sort (fun f1 f2 -> (PMap.find f1 enum_def.e_constrs ).ef_index -
  99. (PMap.find f2 enum_def.e_constrs ).ef_index )
  100. (pmap_keys enum_def.e_constrs) in
  101. List.iter (fun name -> output_cpp ("\t" ^ (strq name) ^ ",\n") ) sorted;
  102. output_cpp "\t::String(null())\n};\n\n";
  103. (* ENUM - Mark static as used by GC - they are const now, so no marking*)
  104. (* ENUM - Visit static as used by GC - none *)
  105. output_cpp ("::hx::Class " ^ class_name ^ "::__mClass;\n\n");
  106. output_cpp ("Dynamic __Create_" ^ class_name ^ "() { return new " ^ class_name ^ "; }\n\n");
  107. output_cpp ("void " ^ class_name ^ "::__register()\n{\n");
  108. let text_name = strq (join_class_path class_path ".") in
  109. output_cpp ("\n::hx::Static(__mClass) = ::hx::_hx_RegisterClass(" ^ text_name ^
  110. ", ::hx::TCanCast< " ^ class_name ^ " >," ^ class_name ^ "_sStaticFields,0,\n");
  111. output_cpp ("\t&__Create_" ^ class_name ^ ", &__Create,\n");
  112. output_cpp ("\t&super::__SGetClass(), &Create" ^ class_name ^ ", 0\n");
  113. output_cpp("#ifdef HXCPP_VISIT_ALLOCS\n , 0\n#endif\n");
  114. output_cpp ("#ifdef HXCPP_SCRIPTABLE\n , 0\n#endif\n");
  115. output_cpp (");\n");
  116. output_cpp ("\t__mClass->mGetStaticField = &" ^ class_name ^"::__GetStatic;\n");
  117. output_cpp "}\n\n";
  118. output_cpp ("void " ^ class_name ^ "::__boot()\n{\n");
  119. (match Texpr.build_metadata common_ctx.basic (TEnumDecl enum_def) with
  120. | Some expr ->
  121. let ctx = file_context ctx cpp_file 1 false in
  122. gen_cpp_init ctx class_name "boot" "__mClass->__meta__ = " expr
  123. | _ -> () );
  124. PMap.iter (fun _ constructor ->
  125. let name = constructor.ef_name in
  126. match constructor.ef_type with
  127. | TFun (_,_) -> ()
  128. | _ ->
  129. output_cpp ( (keyword_remap name) ^ " = ::hx::CreateConstEnum< " ^ class_name ^ " >(" ^ (strq name) ^ "," ^
  130. (string_of_int constructor.ef_index) ^ ");\n" )
  131. ) enum_def.e_constrs;
  132. output_cpp ("}\n\n");
  133. output_cpp "\n";
  134. end_namespace output_cpp class_path;
  135. cpp_file#close;
  136. let h_file = new_header_file common_ctx common_ctx.file class_path in
  137. let super = "::hx::EnumBase_obj" in
  138. let output_h = (h_file#write) in
  139. let def_string = join_class_path class_path "_" in
  140. begin_header_file (h_file#write_h) def_string false;
  141. List.iter2 (fun r f -> gen_forward_decl h_file r f) referenced flags;
  142. output_h ( get_code enum_def.e_meta Meta.HeaderCode );
  143. begin_namespace output_h class_path;
  144. output_h "\n\n";
  145. output_h ("class " ^ class_name ^ " : public " ^ super ^ "\n");
  146. output_h ("{\n\ttypedef " ^ super ^ " super;\n");
  147. output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n");
  148. output_h "\n\tpublic:\n";
  149. output_h ("\t\tenum { _hx_ClassId = " ^ classIdTxt ^ " };\n\n");
  150. output_h ("\t\t" ^ class_name ^ "() {};\n");
  151. output_h ("\t\tHX_DO_ENUM_RTTI;\n");
  152. output_h ("\t\tstatic void __boot();\n");
  153. output_h ("\t\tstatic void __register();\n");
  154. output_h ("\t\tstatic bool __GetStatic(const ::String &inName, Dynamic &outValue, ::hx::PropertyAccess inCallProp);\n");
  155. output_h ("\t\t::String GetEnumName( ) const { return " ^ (strq (join_class_path class_path ".")) ^ "; }\n" );
  156. output_h ("\t\t::String __ToString() const { return " ^ (strq (just_class_name ^ ".") )^ " + _hx_tag; }\n");
  157. output_h ("\t\tbool _hx_isInstanceOf(int inClassId);\n\n");
  158. PMap.iter (fun _ constructor ->
  159. let name = keyword_remap constructor.ef_name in
  160. output_h ( "\t\tstatic " ^ remap_class_name ^ " " ^ name );
  161. match constructor.ef_type with
  162. | TFun (args,_) ->
  163. output_h ( "(" ^ (print_tfun_arg_list true args) ^");\n");
  164. output_h ( "\t\tstatic ::Dynamic " ^ name ^ "_dyn();\n");
  165. | _ ->
  166. output_h ";\n";
  167. output_h ( "\t\tstatic inline " ^ remap_class_name ^ " " ^ name ^
  168. "_dyn() { return " ^name ^ "; }\n" );
  169. ) enum_def.e_constrs;
  170. output_h "};\n\n";
  171. end_namespace output_h class_path;
  172. end_header_file output_h def_string;
  173. h_file#close