Browse Source

[cpp] Gencpp Rework Mk II (#11819)

* Initial class, interface, and enum separation

* fold init stuff

* Move interface header generation into its own module

* reduce some duplication

* managed interface implementation gen in its own module

* cache dependencies in the ctx

* move to gencpp with the other context data func

* remove interface code from class gen modules

* Use option for reference wildcard

* path Map

* Add back objc guard

* calculate IDs up front

* separate id lookup table

* Object IDs module to hide cache

* remap enum constructors

* more interface dead code removal

* tcpp interface type

* name, flags, and debug level in tcpp_class

* remove unused constructor var list return item

* separate out header field generation

* separate managed and native header gen functions

* move header stuff into shared function

* break class impl field gen function down

* add converted fields to tcpp_class

* Initial split for managed and native class impl

* map for haxe and native implementations

* use a list for haxe and native implementations

* use tcpp_class field variables

* field rename and meta / rtti filtering

* create fields and default functions at class transform

* use container flag

* Mark and visit using variables and fix inverted container flag

* static mark and visit use static variables list

* print reflective fields

* don't duplicate boot generation code

* don't duplicate init function generation

* don't duplicate dynamic function allocation generation

* generate properties and __Field function

* fold right member get fields

* static get fields

* shared member and static get fold functions

* static set function uses ordered fields

* member set uses organised fields

* turn abstract functions into normal functions

* cppia gen uses organised functions

* simplify ScriptNamedFunction generation

* bit of simplification of more cppia stuff

* GetFields uses organised fields

* move class retyping into retyper

* remap interface functions

* store interface hash

* store meta and rtti fields in remapped interface

* dead code removal

* tcpp interfaces only store their functions

* remapped enum fields rename for consistency

* calculate interface slots ahead of time

* remap interface arg names

* retype the interfaces stored on retyped classes

* retype tcpp_class supers

* find_class_implementation uses tcpp_class

* folds for class interface code

* other minor cleanup

* use flags in class generation to selectively generate some funcs

* retype class functions

* retype class variables

* dedicated var and dyn function boot functions

* dead code cleanup

* use bindings instead of to_list

* own implementation of of_list

* replace another to_list

* Fix pointer and struct wrapping

* fix debug level not being reset between classes

* add space after static

* remove unused variable

* ensure SourceFile paths are made absolute

* some debugging

* remove debugging prints and store class params

* don't use already mangled name when generating the getter name in reflection

* same for setters

* dont use new gc references function

* better handling of static and virtual attributes

* generate scriptable class using tcpp class function lists

* go back to type cant be null

* Container flag refers to entire inheritance tree

* allow code to easily distinguish between the different container types

* remove accidentally tracked file

* pass a context object around the retyper

* closures tracked in retyper ctx

* injection stored in retyper ctx

* declarations track by retyper ctx

* this handling moved into ctx

* gc stack handled by retyper ctx

* function return type handled by retyper ctx

* move loop goto management into retyper ctx

* consistent retyper ctx variable name

* move remaining counter into the fold

* shared string_map_of_list function

* another pass to catch some missing :: prefixes

* remove unused imports
Aidan Lee 7 months ago
parent
commit
d2af50081a

+ 146 - 1
src/generators/cpp/cppAst.ml

@@ -1,6 +1,45 @@
 open Type
 open Globals
 
+module PathMap = Map.Make(struct type t = path let compare i1 i2 = String.compare (s_type_path i2) (s_type_path i1) end)
+
+module ObjectIds = struct
+  type t = {
+    ids : int32 PathMap.t;
+    cache : unit Int32Map.t;
+  }
+
+  let empty = { ids = PathMap.empty; cache = Int32Map.empty }
+
+  let add path id store =
+    { ids = PathMap.add path id store.ids; cache = Int32Map.add id () store.cache }
+
+  let find_opt path store =
+    PathMap.find_opt path store.ids
+
+  let collision id store =
+    Int32Map.mem id store.cache
+end
+
+module InterfaceSlots = struct
+  type t = {
+    hash : int StringMap.t;
+    next : int;
+  }
+
+  let empty = { hash = StringMap.empty; next = 2 }
+
+  let add name slots =
+    match StringMap.find_opt name slots.hash with
+    | Some slot ->
+      slots
+    | None ->
+      { hash = StringMap.add name slots.next slots.hash; next = slots.next + 1 }
+
+  let find_opt name slots =
+    StringMap.find_opt name slots.hash
+end
+
 type tcpp =
   | TCppDynamic
   | TCppUnchanged
@@ -44,7 +83,7 @@ and tcpp_closure = {
   close_args : (tvar * texpr option) list;
   close_expr : tcppexpr;
   close_id : int;
-  close_undeclared : (string, tvar) Hashtbl.t;
+  close_undeclared : tvar StringMap.t;
   close_this : tcppthis option;
 }
 
@@ -152,3 +191,109 @@ and tcpp_expr_expr =
   | CppCastObjCBlock of tcppexpr * tcpp list * tcpp
   | CppCastProtocol of tcppexpr * tclass
   | CppCastNative of tcppexpr
+
+and tcpp_class_container =
+  | Current (* If the current class holds GC variables *)
+  | Parent (* If one of the current classes parents holds GC variables *)
+
+and tcpp_class_flags =
+  | QuickAlloc
+  | Scriptable
+  | MemberGet
+  | MemberSet
+  | StaticGet
+  | StaticSet
+  | GetFields
+  | Compare
+  | Boot
+
+and tcpp_class_function = {
+  tcf_field : tclass_field;
+  tcf_name : string;
+  tcf_func : tfunc;
+
+  tcf_is_virtual : bool;
+  tcf_is_reflective : bool;
+  tcf_is_external : bool;
+  tcf_is_scriptable : bool;
+  tcf_is_overriding : bool;
+}
+
+and tcpp_class_variable = {
+  tcv_field : tclass_field;
+  tcv_name : string;
+  tcv_type : t;
+  tcv_default : texpr option;
+
+  tcv_is_stackonly : bool;
+  tcv_is_gc_element : bool;
+  tcv_is_reflective : bool;
+}
+
+and tcpp_class = {
+  tcl_class : tclass;
+  tcl_params : tparams;
+  tcl_name : string;
+  tcl_id : int32;
+  tcl_flags : int;
+  tcl_debug_level : int;
+  tcl_super : tcpp_class option;
+  tcl_container : tcpp_class_container option;
+
+  tcl_haxe_interfaces : tcpp_interface list;
+  tcl_native_interfaces : tcpp_interface list;
+
+  tcl_static_variables : tcpp_class_variable list;
+  tcl_static_properties : tcpp_class_variable list;
+  tcl_static_functions : tcpp_class_function list;
+  tcl_static_dynamic_functions : tcpp_class_function list;
+
+  tcl_variables : tcpp_class_variable list;
+  tcl_properties : tcpp_class_variable list;
+  tcl_functions : tcpp_class_function list;
+  tcl_dynamic_functions : tcpp_class_function list;
+
+  tcl_meta : texpr option;
+  tcl_rtti : texpr option;
+  tcl_init : texpr option;
+}
+
+and tcpp_interface_function = {
+  iff_field : tclass_field;
+  iff_name : string;
+  iff_args : (string * bool * t) list;
+  iff_return : t;
+  iff_script_slot : int option;
+}
+
+and tcpp_interface = {
+  if_class : tclass;
+  if_name : string;
+  if_hash : string;
+  if_debug_level : int;
+  if_functions : tcpp_interface_function list;
+  if_variables : tclass_field list;
+  if_extends : tcpp_interface option;
+  if_meta : texpr option;
+  if_rtti : texpr option;
+  if_scriptable : bool;
+}
+
+and tcpp_enum_field = {
+  tef_field : tenum_field;
+  tef_name : string;
+  tef_hash : string;
+}
+
+and tcpp_enum = {
+  te_enum : tenum;
+  te_id : int32;
+  te_constructors : tcpp_enum_field list;
+}
+
+and tcpp_decl =
+  | ManagedClass of tcpp_class
+  | NativeClass of tcpp_class
+  | ManagedInterface of tcpp_interface
+  | NativeInterface of tcpp_interface
+  | Enum of tcpp_enum

+ 50 - 12
src/generators/cpp/cppAstTools.ml

@@ -6,6 +6,8 @@ open CppTypeUtils
 
 let follow = Abstract.follow_with_abstracts
 
+let string_map_of_list bs = List.fold_left (fun m (k, v) -> StringMap.add k v m) StringMap.empty bs
+
 (*
    A class_path is made from a package (array of strings) and a class name.
    Join these together, inclding a separator.  eg, "/" for includes : pack1/pack2/Name or "::"
@@ -588,6 +590,19 @@ and array_element_type haxe_type =
    | _ -> "::Dynamic"
 
 and cpp_function_signature tfun abi =
+   let gen_interface_arg_type_name name opt typ =
+      let type_str = (type_string typ) in
+      (* type_str may have already converted Null<X> to Dynamic because of NotNull tag ... *)
+      (if (opt && (cant_be_null typ) && type_str<>"Dynamic" ) then
+         "::hx::Null< " ^ type_str ^ " > "
+      else
+         type_str ) ^ " " ^ (keyword_remap name)
+   in
+   
+   let gen_tfun_interface_arg_list args =
+      String.concat "," (List.map (fun (name,opt,typ) -> gen_interface_arg_type_name name opt typ) args)
+   in
+
    match follow tfun with
    | TFun(args,ret) -> (type_string ret) ^ " " ^ abi ^ "(" ^ (gen_tfun_interface_arg_list args) ^ ")"
    | _ -> "void *"
@@ -600,18 +615,7 @@ and cpp_function_signature_params params = match params with
    | _ ->
       print_endline ("Params:" ^ (String.concat "," (List.map type_string params) ));
       die "" __LOC__;
-
-and gen_interface_arg_type_name name opt typ =
-   let type_str = (type_string typ) in
-   (* type_str may have already converted Null<X> to Dynamic because of NotNull tag ... *)
-   (if (opt && (cant_be_null typ) && type_str<>"Dynamic" ) then
-      "::hx::Null< " ^ type_str ^ " > "
-   else
-      type_str ) ^ " " ^ (keyword_remap name)
-
-and gen_tfun_interface_arg_list args =
-   String.concat "," (List.map (fun (name,opt,typ) -> gen_interface_arg_type_name name opt typ) args)
-
+   
 and cant_be_null haxe_type =
    is_numeric haxe_type || (type_has_meta_key Meta.NotNull haxe_type )
 
@@ -725,3 +729,37 @@ let enum_getter_type t =
   | TCppScalar "bool"  -> "Bool"
   | TCppScalar x  -> x
   | _  -> "Object"
+
+let int_of_tcpp_class_flag (flag:tcpp_class_flags) =
+   Obj.magic flag
+
+let set_tcpp_class_flag flags c =
+   set_flag flags (int_of_tcpp_class_flag c)
+
+let has_tcpp_class_flag c flag =
+   has_flag c.tcl_flags (int_of_tcpp_class_flag flag)
+
+let all_interface_functions tcpp_interface =
+   let add_interface_functions existing interface =
+      let folder acc cur =
+         if List.exists (fun f -> f.iff_name = cur.iff_name) acc then
+            acc
+         else
+            cur :: acc
+         in
+      List.fold_left folder existing interface.if_functions
+   in
+
+   let rec visit_interface existing interface =
+      let initial =
+         match interface.if_extends with
+         | None ->
+            existing
+         | Some super ->
+            visit_interface existing super
+      in
+
+      add_interface_functions initial interface
+   in
+
+   visit_interface [] tcpp_interface |> List.rev

+ 8 - 8
src/generators/cpp/cppContext.ml

@@ -1,4 +1,6 @@
 open Gctx
+open Globals
+open Type
 open CppAstTools
 
 (* CPP code generation context *)
@@ -17,20 +19,19 @@ type context = {
   mutable ctx_debug_level : int;
   (* cached as required *)
   mutable ctx_file_info : (string, string) PMap.t ref;
-  ctx_type_ids : (string, Int32.t) Hashtbl.t;
   (* Per file *)
   ctx_output : string -> unit;
   ctx_writer : CppSourceWriter.source_writer;
   ctx_file_id : int ref;
   ctx_is_header : bool;
-  ctx_interface_slot : (string, int) Hashtbl.t ref;
-  ctx_interface_slot_count : int ref;
+  ctx_super_deps : path list CppAst.PathMap.t;
+  ctx_constructor_deps : tclass_field CppAst.PathMap.t;
+  ctx_class_member_types : string StringMap.t;
   (* This is for returning from the child nodes of TSwitch && TTry *)
   mutable ctx_real_this_ptr : bool;
-  mutable ctx_class_member_types : (string, string) Hashtbl.t;
 }
 
-let new_context common_ctx debug file_info member_types =
+let new_context common_ctx debug file_info member_types super_deps constructor_deps =
   let null_file =
     new CppSourceWriter.source_writer common_ctx ignore ignore (fun () -> ())
   in
@@ -40,11 +41,8 @@ let new_context common_ctx debug file_info member_types =
       ctx_common = common_ctx;
       ctx_writer = null_file;
       ctx_file_id = ref (-1);
-      ctx_type_ids = Hashtbl.create 0;
       ctx_is_header = false;
       ctx_output = null_file#write;
-      ctx_interface_slot = ref (Hashtbl.create 0);
-      ctx_interface_slot_count = ref 2;
       ctx_debug_level =
         (if has_def Define.AnnotateSource then 3
          else if has_def Define.HxcppDebugger then 2
@@ -52,6 +50,8 @@ let new_context common_ctx debug file_info member_types =
       ctx_real_this_ptr = true;
       ctx_class_member_types = member_types;
       ctx_file_info = file_info;
+      ctx_super_deps = super_deps;
+      ctx_constructor_deps = constructor_deps;
     }
   in
   result

+ 0 - 19
src/generators/cpp/cppExprUtils.ml

@@ -1,19 +0,0 @@
-open Type
-
-let rec remove_parens expression =
-  match expression.eexpr with
-  | TParenthesis e -> remove_parens e
-  | TMeta(_,e) -> remove_parens e
-  | _ -> expression
-
-let rec remove_parens_cast expression =
-  match expression.eexpr with
-  | TParenthesis e -> remove_parens_cast e
-  | TMeta(_,e) -> remove_parens_cast e
-  | TCast ( e,None) -> remove_parens_cast e
-  | _ -> expression
-
-let is_static_access obj =
-  match (remove_parens obj).eexpr with
-  | TTypeExpr _ -> true
-  | _ -> false

File diff suppressed because it is too large
+ 568 - 556
src/generators/cpp/cppRetyper.ml


+ 19 - 50
src/generators/cpp/cppTypeUtils.ml

@@ -65,6 +65,24 @@ let is_internal_class = function
 let is_native_class class_def =
    (is_extern_class class_def || is_native_gen_class class_def) && not (is_internal_class class_def.cl_path)
 
+let can_quick_alloc klass =
+   let rec implements_native_interface class_def =
+      List.exists
+        (fun (intf_def, _) -> is_native_gen_class intf_def || implements_native_interface intf_def) class_def.cl_implements ||
+      match class_def.cl_super with
+      | Some (i, _) -> implements_native_interface i
+      | _ -> false
+   in
+
+  (not (is_native_class klass)) && not (implements_native_interface klass)
+
+let real_interfaces classes =
+   List.filter (function t, pl ->
+      (match (t, pl) with
+      | { cl_path = [ "cpp"; "rtti" ], _ }, [] -> false
+      | _ -> true))
+   classes
+
 let is_interface_type t =
    match follow t with
    | TInst (klass,params) -> (has_class_flag klass CInterface)
@@ -129,12 +147,7 @@ let is_numeric t =
       -> true
    | _
       -> false
-
-let is_cpp_function_instance t =
-   match follow t with
-   | TInst ({ cl_path = (["cpp"], "Function") }, _) -> true
-   | _ -> false
-
+   
 let is_objc_class klass =
    has_class_flag klass CExtern && Meta.has Meta.Objc klass.cl_meta
 
@@ -178,23 +191,6 @@ let is_array_or_dyn_array haxe_type =
    | TType ({ t_path = ([], "Array")}, _) -> true
    | _ -> false
 
-let is_array_implementer haxe_type =
-   match follow haxe_type with
-   | TInst ({ cl_array_access = Some _ }, _) -> true
-   | _ -> false
-
-let rec has_rtti_interface c interface =
-   List.exists (function (t,pl) ->
-      (snd t.cl_path) = interface && (match fst t.cl_path with | ["cpp";"rtti"] -> true | _ -> false )
-   ) c.cl_implements ||
-      (match c.cl_super with None -> false | Some (c,_) -> has_rtti_interface c interface)
-
-let has_field_integer_lookup class_def =
-   has_rtti_interface class_def "FieldIntegerLookup"
-
-let has_field_integer_numeric_lookup class_def =
-   has_rtti_interface class_def "FieldNumericIntegerLookup"
-
 let should_implement_field x = is_physical_field x
 
 let is_scalar_abstract abstract_def =
@@ -318,33 +314,6 @@ let has_boot_field class_def =
    | None -> List.exists has_field_init (List.filter should_implement_field class_def.cl_ordered_statics)
    | _ -> true
 
-(*
-   Functions are added in reverse order (oldest on right), then list is reversed because this is easier in ocaml
-   The order is important because cppia looks up functions by index
-*)
-let current_virtual_functions_rev clazz base_functions =
-   List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind  with
-      | _, Method MethDynamic -> result
-      | TFun (args,return_type), Method _  ->
-          if (is_override elem ) then
-            if List.exists (fun (e,a,r) -> e.cf_name=elem.cf_name ) result then
-               result
-            else
-               (elem,args,return_type) :: result
-          else
-             (elem,args,return_type) :: result
-      | _,_ -> result
-    ) base_functions clazz.cl_ordered_fields
-
-let all_virtual_functions clazz =
-  let rec all_virtual_functions_rec clazz =
-   current_virtual_functions_rev clazz (match clazz.cl_super with
-       | Some def -> all_virtual_functions_rec (fst def)
-       | _ -> []
-     )
-   in
-   List.rev (all_virtual_functions_rec clazz)
-
 let class_name class_def =
   let (_, class_path) = class_def.cl_path in
   let nativeGen       = Meta.has Meta.NativeGen class_def.cl_meta in

+ 16 - 4
src/generators/cpp/gen/cppCppia.ml

@@ -2,7 +2,6 @@ open Ast
 open Type
 open Error
 open Globals
-open CppExprUtils
 open CppTypeUtils
 open CppAst
 open CppAstTools
@@ -353,6 +352,19 @@ let rec is_null expr =
 
 let is_virtual_array expr = type_string expr.etype = "cpp::VirtualArray"
 
+let rec remove_parens expression =
+  match expression.eexpr with
+  | TParenthesis e -> remove_parens e
+  | TMeta(_,e) -> remove_parens e
+  | _ -> expression
+
+let rec remove_parens_cast expression =
+  match expression.eexpr with
+  | TParenthesis e -> remove_parens_cast e
+  | TMeta(_,e) -> remove_parens_cast e
+  | TCast ( e,None) -> remove_parens_cast e
+  | _ -> expression
+
 let is_this expression =
   match (remove_parens expression).eexpr with
   | TConst TThis -> true
@@ -447,7 +459,7 @@ and is_dynamic_member_lookup_in_cpp (ctx : context) field_object field =
     | "Dynamic" -> true
     | name ->
         let full_name = name ^ "." ^ member in
-        if Hashtbl.mem ctx.ctx_class_member_types full_name then false
+        if StringMap.mem full_name ctx.ctx_class_member_types then false
         else not (is_extern_class_instance field_object)
 
 and is_dynamic_member_return_in_cpp ctx field_object field =
@@ -462,7 +474,7 @@ and is_dynamic_member_return_in_cpp ctx field_object field =
           "::" ^ join_class_path_remap (t_path t) "::" ^ "." ^ member
         in
         try
-          let mem_type = Hashtbl.find ctx.ctx_class_member_types full_name in
+          let mem_type = StringMap.find full_name ctx.ctx_class_member_types in
           mem_type = "Dynamic"
           || mem_type = "cpp::ArrayBase"
           || mem_type = "cpp::VirtualArray"
@@ -479,7 +491,7 @@ and is_dynamic_member_return_in_cpp ctx field_object field =
             let full_name = name ^ "." ^ member in
             try
               let mem_type =
-                Hashtbl.find ctx.ctx_class_member_types full_name
+                StringMap.find full_name ctx.ctx_class_member_types
               in
               mem_type = "Dynamic"
               || mem_type = "cpp::ArrayBase"

+ 76 - 235
src/generators/cpp/gen/cppGen.ml

@@ -67,44 +67,18 @@ let print_arg_list_name arg_list prefix =
 let print_arg_names args =
   String.concat "," (List.map (fun (name, _, _) -> keyword_remap name) args)
 
-let rec print_tfun_arg_list include_names arg_list =
+let print_tfun_arg_list include_names arg_list =
   let oType o arg_type =
     let type_str = type_to_string arg_type in
     (* type_str may have already converted Null<X> to Dynamic because of NotNull tag ... *)
     if o && type_cant_be_null arg_type && type_str <> "Dynamic" then
       "::hx::Null< " ^ type_str ^ " > "
-    else type_str
-  in
-  match arg_list with
-  | [] -> ""
-  | [ (name, o, arg_type) ] ->
-      oType o arg_type ^ if include_names then " " ^ keyword_remap name else ""
-  | (name, o, arg_type) :: remaining ->
-      oType o arg_type
-      ^ (if include_names then " " ^ keyword_remap name else "")
-      ^ ","
-      ^ print_tfun_arg_list include_names remaining
-
-let has_new_gc_references class_def =
-  let is_gc_reference field =
-    should_implement_field field
-    && is_data_member field
-    && not (type_cant_be_null field.cf_type)
+    else
+      type_str
   in
-  List.exists is_gc_reference class_def.cl_ordered_fields
-
-let rec has_gc_references class_def =
-  (match class_def.cl_super with
-  | Some def when has_gc_references (fst def) -> true
-  | _ -> false)
-  || has_new_gc_references class_def
-
-let rec find_next_super_iteration class_def =
-  match class_def.cl_super with
-  | Some (klass, params) when has_new_gc_references klass ->
-      tcpp_to_string_suffix "_obj" (cpp_instance_type klass params)
-  | Some (klass, _) -> find_next_super_iteration klass
-  | _ -> ""
+  arg_list
+  |> List.map (fun (name, o, arg_type) -> (oType o arg_type) ^ (if include_names then " " ^ keyword_remap name else ""))
+  |> String.concat ","
 
 let cpp_member_name_of member =
   match get_meta_string member.cf_meta Meta.Native with
@@ -175,19 +149,6 @@ let cpp_class_name klass =
   let path = globalNamespace ^ join_class_path_remap klass.cl_path "::" in
   if is_native_class klass || path = "::String" then path else path ^ "_obj"
 
-let rec implements_native_interface class_def =
-  List.exists
-    (fun (intf_def, _) ->
-      is_native_gen_class intf_def || implements_native_interface intf_def)
-    class_def.cl_implements
-  ||
-  match class_def.cl_super with
-  | Some (i, _) -> implements_native_interface i
-  | _ -> false
-
-let can_quick_alloc klass =
-  (not (is_native_class klass)) && not (implements_native_interface klass)
-
 let only_stack_access haxe_type =
   match cpp_type_of haxe_type with
   | TCppInst (klass, _) -> Meta.has Meta.StackOnly klass.cl_meta
@@ -382,63 +343,7 @@ let hx_stack_push ctx output clazz func_name pos gc_stack =
 (* Add include to source code *)
 let add_include writer class_path = writer#add_include class_path
 
-let real_interfaces =
-  List.filter (function t, pl ->
-      (match (t, pl) with
-      | { cl_path = [ "cpp"; "rtti" ], _ }, [] -> false
-      | _ -> true))
-
-let native_field_name_remap is_static field =
-  let remap_name = keyword_remap field.cf_name in
-  if not is_static then remap_name
-  else
-    match get_meta_string field.cf_meta Meta.Native with
-    | Some nativeImpl ->
-        let r = Str.regexp "^[a-zA-Z_0-9]+$" in
-        if Str.string_match r remap_name 0 then "_hx_" ^ remap_name
-        else "_hx_f" ^ gen_hash 0 remap_name
-    | None -> remap_name
-
-let rec is_dynamic_accessor name acc field class_def =
-  acc ^ "_" ^ field.cf_name = name
-  && (not (List.exists (fun f -> f.cf_name = name) class_def.cl_ordered_fields))
-  &&
-  match class_def.cl_super with
-  | None -> true
-  | Some (parent, _) -> is_dynamic_accessor name acc field parent
-
-(* Builds inheritance tree, so header files can include parents defs.  *)
-let create_super_dependencies common_ctx =
-  let result = Hashtbl.create 0 in
-  let real_non_native_interfaces =
-    List.filter (function t, pl ->
-        (match (t, pl) with
-        | { cl_path = [ "cpp"; "rtti" ], _ }, [] -> false
-        | _ -> not (is_native_gen_class t)))
-  in
-  let iterator object_def =
-    match object_def with
-    | TClassDecl class_def when not (has_class_flag class_def CExtern) ->
-        let deps = ref [] in
-        (match class_def.cl_super with
-        | Some super ->
-            if not (has_class_flag (fst super) CExtern) then
-              deps := (fst super).cl_path :: !deps
-        | _ -> ());
-        List.iter
-          (fun imp ->
-            if not (has_class_flag (fst imp) CExtern) then
-              deps := (fst imp).cl_path :: !deps)
-          (real_non_native_interfaces class_def.cl_implements);
-        Hashtbl.add result class_def.cl_path !deps
-    | TEnumDecl enum_def when not (has_enum_flag enum_def EnExtern) ->
-        Hashtbl.add result enum_def.e_path []
-    | _ -> ()
-  in
-  List.iter iterator common_ctx.types;
-  result
-
-let can_inline_constructor baseCtx class_def super_deps constructor_deps =
+let can_inline_constructor base_ctx class_def =
   match class_def.cl_constructor with
   | Some { cf_expr = Some super_func } ->
       let is_simple = ref true in
@@ -461,25 +366,12 @@ let can_inline_constructor baseCtx class_def super_deps constructor_deps =
       (* Check to see if all the types required by the constructor are already in the header *)
       (* This is quite restrictive, since most classes are forward-declared *)
       let deps, _ =
-        CppReferences.find_referenced_types_flags baseCtx (TClassDecl class_def)
-          "new" super_deps constructor_deps false false true
+        CppReferences.find_referenced_types_flags base_ctx (TClassDecl class_def)
+          (Some "new") base_ctx.ctx_super_deps base_ctx.ctx_constructor_deps false false true
       in
       List.for_all (fun dep -> List.mem dep allowed) deps
   | _ -> true
 
-let create_constructor_dependencies common_ctx =
-  let result = Hashtbl.create 0 in
-  List.iter
-    (fun object_def ->
-      match object_def with
-      | TClassDecl class_def when not (has_class_flag class_def CExtern) -> (
-          match class_def.cl_constructor with
-          | Some func_def -> Hashtbl.add result class_def.cl_path func_def
-          | _ -> ())
-      | _ -> ())
-    common_ctx.types;
-  result
-
 let begin_namespace output class_path =
   List.iter
     (fun namespace -> output ("namespace " ^ namespace ^ "{\n"))
@@ -511,80 +403,44 @@ let cpp_tfun_signature include_names args return_type =
   let returnType = type_to_string return_type in
   "( " ^ returnType ^ " (::hx::Object::*)(" ^ argList ^ "))"
 
-exception FieldFound of tclass_field
-
-let find_class_implementation class_def name interface =
+let find_class_implementation func tcpp_class =
   let rec find def =
-    List.iter
-      (fun f -> if f.cf_name = name then raise (FieldFound f))
-      def.cl_ordered_fields;
-    match def.cl_super with Some (def, _) -> find def | _ -> ()
+    match List.find_opt (fun f -> f.tcf_name = func.iff_name) def.tcl_functions with
+    | Some f -> Some f.tcf_field
+    | None ->
+      match def.tcl_super with
+      | Some s -> find s
+      | None -> None
   in
-  try
-    find class_def;
-    abort
-      ("Could not find implementation of " ^ name ^ " in "
-      ^ join_class_path class_def.cl_path "."
-      ^ " required by "
-      ^ join_class_path interface.cl_path ".")
-      class_def.cl_pos
-  with FieldFound field -> (
-    match (follow field.cf_type, field.cf_kind) with
-    | _, Method MethDynamic -> ""
-    | TFun (args, return_type), Method _ ->
-        cpp_tfun_signature false args return_type
-    | _, _ -> "")
+
+  match find tcpp_class with
+  | Some { cf_type = TFun (args, ret) } -> 
+    cpp_tfun_signature false args ret
+  | _ ->
+    ""
 
 let gen_gc_name class_path =
   let class_name_text = join_class_path class_path "." in
   const_char_star class_name_text
 
-(* All interfaces (and sub-interfaces) implemented *)
-let implementations class_def =
-  let implemented_hash = Hashtbl.create 0 in
-  let native_implemented = Hashtbl.create 0 in
-
-  let cpp_interface_impl_name interface =
-    "_hx_" ^ join_class_path interface.cl_path "_"
+let needed_interface_functions implemented_instance_fields native_implementations =
+  let have =
+    implemented_instance_fields
+    |> List.map (fun (func) -> (func.tcf_name, ()))
+    |> string_map_of_list
   in
-  let iterator impl =
-    let rec descend_interface interface =
-      let intf_def = fst interface in
-      let interface_name = cpp_interface_impl_name intf_def in
-      let hash =
-        if is_native_gen_class intf_def then native_implemented
-        else implemented_hash
-      in
-      if not (Hashtbl.mem hash interface_name) then (
-        Hashtbl.replace hash interface_name intf_def;
-        List.iter descend_interface intf_def.cl_implements);
-      match intf_def.cl_super with
-      | Some (interface, params) -> descend_interface (interface, params)
-      | _ -> ()
-    in
-    descend_interface impl
+  let func_folder (have, acc) func =
+    if StringMap.mem func.iff_name have then
+      (have, acc)
+    else
+      (StringMap.add func.iff_name () have, func :: acc)
   in
-
-  List.iter iterator (real_interfaces class_def.cl_implements);
-  (implemented_hash, native_implemented)
-
-let needed_interface_functions implemented_instance_fields
-    native_implementations =
-  let have =
-    List.map (fun field -> (field.cf_name, ())) implemented_instance_fields
-    |> List.to_seq |> Hashtbl.of_seq
+  let iface_folder acc iface =
+    List.fold_left func_folder acc iface.if_functions
   in
-  let want = ref [] in
-  Hashtbl.iter
-    (fun _ intf_def ->
-      List.iter
-        (fun field ->
-          if not (Hashtbl.mem have field.cf_name) then (
-            Hashtbl.replace have field.cf_name ();
-            want := field :: !want))
-        intf_def.cl_ordered_fields)
-    native_implementations;
-  !want
+  native_implementations
+  |> List.fold_left iface_folder (have, [])
+  |> snd
 
 let gen_cpp_ast_expression_tree ctx class_name func_name function_args
     function_type injection tree =
@@ -1087,7 +943,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args
             separator := ","
         | _ -> ());
 
-        Hashtbl.iter
+        StringMap.iter
           (fun name value ->
             out !separator;
             separator := ",";
@@ -1603,8 +1459,9 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args
     | OpIn -> " in "
     | OpNullCoal -> "??"
     | OpAssign | OpAssignOp _ -> abort "Unprocessed OpAssign" pos
+
   and gen_closure closure =
-    let argc = Hashtbl.length closure.close_undeclared in
+    let argc = StringMap.bindings closure.close_undeclared |> List.length in
     let size = string_of_int argc in
     if argc >= 62 then
       (* Limited by c++ macro size of 128 args *)
@@ -1617,7 +1474,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args
       (if closure.close_this != None then "::hx::LocalThisFunc,"
        else "::hx::LocalFunc,");
     out ("_hx_Closure_" ^ string_of_int closure.close_id);
-    Hashtbl.iter
+    StringMap.iter
       (fun name var ->
         out ("," ^ cpp_macro_var_type_of var ^ "," ^ keyword_remap name))
       closure.close_undeclared;
@@ -1697,11 +1554,11 @@ let generate_main ctx super_deps class_def =
     | _ -> die "" __LOC__
   in
   CppReferences.find_referenced_types ctx (TClassDecl class_def) super_deps
-    (Hashtbl.create 0) false false false
+    PathMap.empty false false false
   |> ignore;
   let depend_referenced =
     CppReferences.find_referenced_types ctx (TClassDecl class_def) super_deps
-      (Hashtbl.create 0) false true false
+    PathMap.empty false true false
   in
   let generate_startup filename is_main =
     (*make_class_directories base_dir ( "src" :: []);*)
@@ -1739,7 +1596,7 @@ let generate_dummy_main common_ctx =
   generate_startup "__main__" true;
   generate_startup "__lib__" false
 
-let generate_boot ctx boot_enums boot_classes nonboot_classes init_classes =
+let generate_boot ctx boot_enums boot_classes nonboot_classes init_classes (slots:CppAst.InterfaceSlots.t) =
   let common_ctx = ctx.ctx_common in
   (* Write boot class too ... *)
   let base_dir = common_ctx.file in
@@ -1754,9 +1611,10 @@ let generate_boot ctx boot_enums boot_classes nonboot_classes init_classes =
   let newScriptable = Gctx.defined common_ctx Define.Scriptable in
   if newScriptable then (
     output_boot "#include <hx/Scriptable.h>\n";
-    let funcs =
-      hash_iterate !(ctx.ctx_interface_slot) (fun name id -> (name, id))
-    in
+
+    
+
+    let funcs = StringMap.bindings slots.hash in
     let sorted = List.sort (fun (_, id1) (_, id2) -> id1 - id2) funcs in
     output_boot
       "static const char *scriptableInterfaceFuncs[] = {\n\t0,\n\t0,\n";
@@ -1773,7 +1631,7 @@ let generate_boot ctx boot_enums boot_classes nonboot_classes init_classes =
   if newScriptable then
     output_boot
       ("::hx::ScriptableRegisterNameSlots(scriptableInterfaceFuncs,"
-      ^ string_of_int !(ctx.ctx_interface_slot_count)
+      ^ string_of_int slots.next
       ^ ");\n");
 
   List.iter
@@ -1905,33 +1763,27 @@ let gen_cpp_function_body ctx clazz is_static func_name function_def head_code
 
 let constructor_arg_var_list class_def =
   match class_def.cl_constructor with
-  | Some definition -> (
-      match definition.cf_expr with
-      | Some { eexpr = TFunction function_def } ->
-          List.map
-            (fun (v, o) ->
-              (v.v_name, type_arg_to_string v.v_name o v.v_type "__o_"))
-            function_def.tf_args
-      | _ -> (
-          match follow definition.cf_type with
-          | TFun (args, _) ->
-              List.map (fun (a, _, t) -> (a, (type_to_string t, a))) args
-          | _ -> []))
+  | Some { cf_expr = Some { eexpr = TFunction function_def } } ->
+    List.map
+      (fun (v, o) -> type_arg_to_string v.v_name o v.v_type "__o_")
+      function_def.tf_args
+  | Some definition ->
+    (match follow definition.cf_type with
+    | TFun (args, _) -> List.map (fun (a, _, t) -> type_to_string t, a) args
+    | _ -> [])
   | _ -> []
 
-let generate_constructor ctx out class_def isHeader =
-  let class_name = class_name class_def in
-  let ptr_name = class_pointer class_def in
-  let can_quick_alloc = can_quick_alloc class_def in
-  let gcName = gen_gc_name class_def.cl_path in
-  let isContainer = if has_gc_references class_def then "true" else "false" in
-  let cargs = constructor_arg_var_list class_def in
-  let constructor_type_var_list = List.map snd cargs in
+let generate_constructor ctx out tcpp_class isHeader =
+  let class_name = tcpp_class.tcl_name in
+  let ptr_name = class_pointer tcpp_class.tcl_class in
+  let can_quick_alloc = has_tcpp_class_flag tcpp_class QuickAlloc in
+  let gcName = gen_gc_name tcpp_class.tcl_class.cl_path in
+  let cargs = constructor_arg_var_list tcpp_class.tcl_class in
   let constructor_type_args =
     String.concat ","
-      (List.map (fun (t, a) -> t ^ " " ^ a) constructor_type_var_list)
+      (List.map (fun (t, a) -> t ^ " " ^ a) cargs)
   in
-  let constructor_var_list = List.map snd constructor_type_var_list in
+  let constructor_var_list = List.map snd cargs in
   let constructor_args = String.concat "," constructor_var_list in
 
   let classScope = if isHeader then "" else class_name ^ "::" in
@@ -1949,10 +1801,9 @@ let generate_constructor ctx out class_def isHeader =
       (staticHead ^ ptr_name ^ " " ^ classScope ^ "__alloc(::hx::Ctx *_hx_ctx"
       ^ (if constructor_type_args = "" then "" else "," ^ constructor_type_args)
       ^ ") {\n");
-    out
-      ("\t" ^ class_name ^ " *__this = (" ^ class_name
-     ^ "*)(::hx::Ctx::alloc(_hx_ctx, sizeof(" ^ class_name ^ "), " ^ isContainer
-     ^ ", " ^ gcName ^ "));\n");
+    Printf.sprintf
+    "\t%s* __this = (%s*)(::hx::Ctx::alloc(_hx_ctx, sizeof(%s), %b, %s));\n"
+    class_name class_name class_name (Option.is_some tcpp_class.tcl_container) gcName |> out;
     out ("\t*(void **)__this = " ^ class_name ^ "::_hx_vtable;\n");
     let rec dump_dynamic class_def =
       if has_dynamic_member_functions class_def then
@@ -1965,16 +1816,16 @@ let generate_constructor ctx out class_def isHeader =
         | Some super -> dump_dynamic (fst super)
         | _ -> ()
     in
-    dump_dynamic class_def;
+    dump_dynamic tcpp_class.tcl_class;
 
     if isHeader then
-      match class_def.cl_constructor with
+      match tcpp_class.tcl_class.cl_constructor with
       | Some
           ({ cf_expr = Some { eexpr = TFunction function_def } } as definition)
         ->
           with_debug ctx definition.cf_meta (fun no_debug ->
               ctx.ctx_real_this_ptr <- false;
-              gen_cpp_function_body ctx class_def false "new" function_def "" ""
+              gen_cpp_function_body ctx tcpp_class.tcl_class false "new" function_def "" ""
                 no_debug;
               out "\n")
       | _ -> ()
@@ -1984,12 +1835,12 @@ let generate_constructor ctx out class_def isHeader =
     out "}\n\n")
 
 let generate_native_constructor ctx out class_def isHeader =
-  let cargs = constructor_arg_var_list class_def in
-  let constructor_type_var_list = List.map snd cargs in
   let constructor_type_args =
-    String.concat ","
-      (List.map (fun (t, a) -> t ^ " " ^ a) constructor_type_var_list)
-  in
+    class_def
+      |> constructor_arg_var_list
+      |> List.map (fun (t, a) -> Printf.sprintf "%s %s" t a)
+      |> String.concat "," in
+
   let class_name = class_name class_def in
 
   match class_def.cl_constructor with
@@ -2035,13 +1886,3 @@ let generate_native_constructor ctx out class_def isHeader =
             gen_cpp_function_body ctx class_def false "new" function_def
               head_code tail_code no_debug)
   | _ -> ()
-
-let dynamic_functions class_def =
-  List.fold_left
-    (fun result field ->
-      match field.cf_expr with
-      | Some { eexpr = TFunction function_def }
-        when is_dynamic_haxe_method field ->
-          keyword_remap field.cf_name :: result
-      | _ -> result)
-    [] class_def.cl_ordered_fields

+ 296 - 458
src/generators/cpp/gen/cppGenClassHeader.ml

@@ -1,4 +1,3 @@
-open Ast
 open Type
 open Error
 open Globals
@@ -10,246 +9,70 @@ open CppSourceWriter
 open CppContext
 open CppGen
 
-let gen_member_def ctx class_def is_static is_interface field =
+let gen_member_variable ctx class_def is_static (var:tcpp_class_variable) =
+  let tcpp     = cpp_type_of var.tcv_type in
+  let tcpp_str = tcpp_to_string tcpp in
+
+  if not is_static && var.tcv_is_stackonly then
+    abort (Printf.sprintf "%s is marked as stack only and therefor cannot be used as the type for a non static variable" tcpp_str) var.tcv_field.cf_pos;
+
   let output = ctx.ctx_output in
-  let remap_name = keyword_remap field.cf_name in
-  let nativeGen = Meta.has Meta.NativeGen class_def.cl_meta in
-
-  if is_interface then
-    match (follow field.cf_type, field.cf_kind) with
-    | _, Method MethDynamic -> ()
-    | TFun (args, return_type), Method _ ->
-        let gen_args = print_tfun_arg_list true in
-        if is_static || nativeGen then (
-          output
-            ((if not is_static then "\t\tvirtual " else "\t\t")
-            ^ type_to_string return_type);
-          output (" " ^ remap_name ^ "( ");
-          output (gen_args args);
-          output (if not is_static then ")=0;\n" else ");\n");
-          if reflective class_def field then
-            if Gctx.defined ctx.ctx_common Define.DynamicInterfaceClosures
-            then
-              output
-                ("\t\tinline ::Dynamic " ^ remap_name
-               ^ "_dyn() { return __Field( "
-                ^ strq ctx.ctx_common field.cf_name
-                ^ ", ::hx::paccDynamic); }\n")
-            else output ("\t\tvirtual ::Dynamic " ^ remap_name ^ "_dyn()=0;\n"))
-        else
-          let argList = gen_args args in
-          let returnType = type_to_string return_type in
-          let returnStr = if returnType = "void" then "" else "return " in
-          let commaArgList = if argList = "" then argList else "," ^ argList in
-          let cast =
-            "::hx::interface_cast< ::"
-            ^ join_class_path_remap class_def.cl_path "::"
-            ^ "_obj *>"
-          in
-          output
-            ("\t\t" ^ returnType ^ " (::hx::Object :: *_hx_" ^ remap_name ^ ")("
-           ^ argList ^ "); \n");
-          output
-            ("\t\tstatic inline " ^ returnType ^ " " ^ remap_name
-           ^ "( ::Dynamic _hx_" ^ commaArgList ^ ") {\n");
-          output "\t\t\t#ifdef HXCPP_CHECK_POINTER\n";
-          output
-            "\t\t\tif (::hx::IsNull(_hx_)) ::hx::NullReference(\"Object\", \
-             false);\n";
-          output "\t\t\t#ifdef HXCPP_GC_CHECK_POINTER\n";
-          output "\t\t\t\tGCCheckPointer(_hx_.mPtr);\n";
-          output "\t\t\t#endif\n";
-          output "\t\t\t#endif\n";
-          output
-            ("\t\t\t" ^ returnStr ^ "(_hx_.mPtr->*( " ^ cast
-           ^ "(_hx_.mPtr->_hx_getInterface(" ^ cpp_class_hash class_def
-           ^ ")))->_hx_" ^ remap_name ^ ")(" ^ print_arg_names args
-           ^ ");\n\t\t}\n")
-    | _ -> ()
-  else
-    let nonVirtual = Meta.has Meta.NonVirtual field.cf_meta in
-    let doDynamic =
-      (nonVirtual || not (is_override field)) && reflective class_def field
-    in
-    let decl = get_meta_string field.cf_meta Meta.Decl in
-    let has_decl = match decl with Some _ -> true | None -> false in
-    if has_decl then output ("      typedef " ^ (decl |> Option.get) ^ ";\n");
-    output (if is_static then "\t\tstatic " else "\t\t");
-    match field.cf_expr with
-    | Some { eexpr = TFunction function_def } ->
-        (if is_dynamic_haxe_method field then (
-           if doDynamic then (
-             output ("::Dynamic " ^ remap_name ^ ";\n");
-             if (not is_static) && is_gc_element ctx TCppDynamic then
-               output
-                 ("\t\tinline ::Dynamic _hx_set_" ^ remap_name
-                ^ "(::hx::StackContext *_hx_ctx,::Dynamic _hx_v) { \
-                   HX_OBJ_WB(this,_hx_v.mPtr) return " ^ remap_name
-                ^ "=_hx_v; }\n");
-             output (if is_static then "\t\tstatic " else "\t\t");
-             output
-               ("inline ::Dynamic &" ^ remap_name ^ "_dyn() " ^ "{return "
-              ^ remap_name ^ "; }\n")))
-         else
-           let return_type = type_to_string function_def.tf_type in
-           (if (not is_static) && not nonVirtual then
-              let scriptable =
-                Gctx.defined ctx.ctx_common Define.Scriptable
-              in
-              if (not (is_internal_member field.cf_name)) && not scriptable then
-                let key =
-                  join_class_path class_def.cl_path "." ^ "." ^ field.cf_name
-                in
-                try output (Hashtbl.find ctx.ctx_class_member_types key)
-                with Not_found -> ()
-              else output "virtual ");
-           output (if return_type = "Void" then "void" else return_type);
-
-           let remap_name = native_field_name_remap is_static field in
-           output (" " ^ remap_name ^ "(");
-           output (print_arg_list function_def.tf_args "");
-           output ");\n";
-           if doDynamic then (
-             output (if is_static then "\t\tstatic " else "\t\t");
-             output ("::Dynamic " ^ remap_name ^ "_dyn();\n")));
-        output "\n"
-    | _ when has_class_field_flag field CfAbstract ->
-        let ctx_arg_list ctx arg_list prefix =
-          let get_default_value name =
-            try
-              match Meta.get Meta.Value field.cf_meta with
-              | _, [ (EObjectDecl decls, _) ], _ ->
-                  Some
-                    (List.find (fun ((n, _, _), _) -> n = name) decls
-                    |> snd
-                    |> type_constant_value ctx.ctx_common.basic)
-              | _ -> None
-            with Not_found -> None
-          in
+  let suffix = if is_static then "\t\tstatic " else "\t\t" in
 
-          String.concat ","
-            (List.map
-               (fun (n, o, t) -> print_arg n (get_default_value n) t prefix)
-               arg_list)
-        in
-        let tl, tr =
-          match follow field.cf_type with
-          | TFun (tl, tr) -> (tl, tr)
-          | _ -> die "" __LOC__
-        in
-        let return_type = type_to_string tr in
-        let remap_name = native_field_name_remap is_static field in
-        output "virtual ";
-        output (if return_type = "Void" then "void" else return_type);
-        output (" " ^ remap_name ^ "(");
-        output (ctx_arg_list ctx tl "");
-        output
-          (") "
-          ^ (if return_type = "void" then "{}" else "{ return 0; }")
-          ^ "\n");
-        if doDynamic then output ("\t\t::Dynamic " ^ remap_name ^ "_dyn();\n")
-    | _ when has_decl -> output (remap_name ^ "_decl " ^ remap_name ^ ";\n")
-    (* Variable access *)
-    | _ -> (
-        (* Variable access *)
-        let tcpp = cpp_type_of field.cf_type in
-        let tcppStr = tcpp_to_string tcpp in
-        if (not is_static) && only_stack_access field.cf_type then
-          abort
-            ("Variables of type " ^ tcppStr ^ " may not be used as members")
-            field.cf_pos;
-
-        output (tcppStr ^ " " ^ remap_name ^ ";\n");
-        (if (not is_static) && is_gc_element ctx tcpp then
-           let getPtr =
-             match tcpp with TCppString -> ".raw_ref()" | _ -> ".mPtr"
-           in
-           output
-             ("\t\tinline " ^ tcppStr ^ " _hx_set_" ^ remap_name
-            ^ "(::hx::StackContext *_hx_ctx," ^ tcppStr
-            ^ " _hx_v) { HX_OBJ_WB(this,_hx_v" ^ getPtr ^ ") return "
-            ^ remap_name ^ "=_hx_v; }\n"));
-
-        (* Add a "dyn" function for variable to unify variable/function access *)
-        match follow field.cf_type with
-        | _ when nativeGen -> ()
-        | TFun (_, _) ->
-            output (if is_static then "\t\tstatic " else "\t\t");
-            output
-              ("Dynamic " ^ remap_name ^ "_dyn() { return " ^ remap_name
-             ^ ";}\n")
-        | _ -> (
-            (match field.cf_kind with
-            | Var { v_read = AccCall }
-              when (not is_static)
-                   && is_dynamic_accessor ("get_" ^ field.cf_name) "get" field
-                        class_def ->
-                output ("\t\tDynamic get_" ^ field.cf_name ^ ";\n")
-            | _ -> ());
-            match field.cf_kind with
-            | Var { v_write = AccCall }
-              when (not is_static)
-                   && is_dynamic_accessor ("set_" ^ field.cf_name) "set" field
-                        class_def ->
-                output ("\t\tDynamic set_" ^ field.cf_name ^ ";\n")
-            | _ -> ()))
-
-let generate baseCtx class_def =
-  let common_ctx = baseCtx.ctx_common in
-  let class_path = class_def.cl_path in
-  let nativeGen = Meta.has Meta.NativeGen class_def.cl_meta in
-  let smart_class_name = snd class_path in
-  let scriptable =
-    Gctx.defined common_ctx Define.Scriptable && not class_def.cl_private
-  in
-  let class_name = class_name class_def in
-  let ptr_name = class_pointer class_def in
-  let can_quick_alloc = can_quick_alloc class_def in
-  let gcName = gen_gc_name class_def.cl_path in
-  let isContainer = if has_gc_references class_def then "true" else "false" in
-  let cargs = constructor_arg_var_list class_def in
-  let constructor_type_var_list = List.map snd cargs in
-  let constructor_type_args =
-    String.concat ","
-      (List.map (fun (t, a) -> t ^ " " ^ a) constructor_type_var_list)
+  Printf.sprintf "%s%s %s;\n" suffix tcpp_str var.tcv_name |> output;
+
+  if not is_static && var.tcv_is_gc_element then (
+    let get_ptr = match tcpp with TCppString -> ".raw_ref()" | _ -> ".mPtr" in
+    Printf.sprintf
+      "\t\tinline %s _hx_set_%s(::hx::StackContext* _hx_ctx, %s _hx_v) { HX_OBJ_WB(this, _hx_v%s) return %s = _hx_v; }\n"
+      tcpp_str var.tcv_name tcpp_str get_ptr var.tcv_name |> output;)
+
+let gen_dynamic_function ctx class_def is_static func =
+  let output = ctx.ctx_output in
+  let prefix = if is_static then "\t\tstatic " else "\t\t" in
+
+  Printf.sprintf "%sinline ::Dynamic& %s_dyn() { return %s; }\n" prefix func.tcf_name func.tcf_name |> output
+
+let gen_member_function ctx class_def is_static func =
+  let output = ctx.ctx_output in
+
+  let fold_static acc = if is_static then "static" :: acc else acc in
+  let fold_virtual acc =
+    if not is_static && func.tcf_is_virtual then (
+      if func.tcf_is_external && not func.tcf_is_scriptable then
+        let key = Printf.sprintf "%s.%s" (join_class_path class_def.cl_path ".") func.tcf_field.cf_name in
+        match StringMap.find_opt key ctx.ctx_class_member_types with
+        | Some v -> v :: acc
+        | None -> acc
+      else
+        "virtual" :: acc)
+    else
+      acc
   in
 
-  (*let cpp_file = new_cpp_file common_ctx.file class_path in*)
-  let debug =
-    if
-      Meta.has Meta.NoDebug class_def.cl_meta
-      || Gctx.defined baseCtx.ctx_common Define.NoDebug
-    then 0
-    else 1
+  let attributes = []
+    |> fold_static
+    |> fold_virtual
+    |> String.concat " "
   in
 
-  let h_file = new_header_file common_ctx common_ctx.file class_path in
-  let ctx = file_context baseCtx h_file debug true in
-  let strq = strq ctx.ctx_common in
+  let return_type     = type_to_string func.tcf_func.tf_type in
+  let return_type_str = if return_type = "Void" then "void" else return_type in
+  Printf.sprintf "\t\t%s %s %s(%s);\n" attributes return_type_str func.tcf_name (print_arg_list func.tcf_func.tf_args "") |> output;
 
-  let parent, super =
-    match class_def.cl_super with
-    | Some (klass, params) ->
-        let name =
-          tcpp_to_string_suffix "_obj" (cpp_instance_type klass params)
-        in
-        ( (if has_class_flag class_def CInterface && nativeGen then "virtual "
-           else "")
-          ^ name,
-          name )
-    | None when nativeGen && has_class_flag class_def CInterface ->
-        ("virtual ::hx::NativeInterface", "::hx::NativeInterface")
-    | None when has_class_flag class_def CInterface -> ("", "::hx::Object")
-    | None when nativeGen -> ("", "")
-    | None -> ("::hx::Object", "::hx::Object")
-  in
-  let output_h = h_file#write in
+  if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then
+    Printf.sprintf "\t\t%s::Dynamic %s_dyn();\n" (if is_static then "static " else "") func.tcf_name |> output;
+
+  output "\n"
+
+let gen_class_header ctx tcpp_class h_file scriptable parents =
+  let class_path = tcpp_class.tcl_class.cl_path in
   let def_string = join_class_path class_path "_" in
 
-  begin_header_file h_file#write_h def_string nativeGen;
+  begin_header_file h_file#write_h def_string false;
 
   (* Include the real header file for the super class *)
-  (match class_def.cl_super with
+  (match tcpp_class.tcl_class.cl_super with
   | Some super ->
       let klass = fst super in
       let include_files = get_all_meta_string_path klass.cl_meta Meta.Include in
@@ -272,274 +95,289 @@ let generate baseCtx class_def =
           (fun inc -> h_file#add_include (path_of_string inc))
           include_files
       else h_file#add_include interface.cl_path)
-    (real_interfaces class_def.cl_implements);
+    (real_interfaces tcpp_class.tcl_class.cl_implements);
 
   (* Only need to forward-declare classes that are mentioned in the header file
      (ie, not the implementation) *)
-  let super_deps = create_super_dependencies common_ctx in
+  let output_h   = h_file#write in
+  let class_path = tcpp_class.tcl_class.cl_path in
   let header_referenced, header_flags =
-    CppReferences.find_referenced_types_flags ctx (TClassDecl class_def) "*"
-      super_deps (Hashtbl.create 0) true false scriptable
+    CppReferences.find_referenced_types_flags ctx (TClassDecl tcpp_class.tcl_class) None
+    ctx.ctx_super_deps PathMap.empty true false scriptable
   in
   List.iter2
     (fun r f -> gen_forward_decl h_file r f)
     header_referenced header_flags;
   output_h "\n";
 
-  output_h (get_class_code class_def Meta.HeaderCode);
+  output_h (get_class_code tcpp_class.tcl_class Meta.HeaderCode);
   let includes =
-    get_all_meta_string_path class_def.cl_meta Meta.HeaderInclude
+    get_all_meta_string_path tcpp_class.tcl_class.cl_meta Meta.HeaderInclude
   in
   let printer inc = output_h ("#include \"" ^ inc ^ "\"\n") in
   List.iter printer includes;
 
   begin_namespace output_h class_path;
   output_h "\n\n";
-  output_h (get_class_code class_def Meta.HeaderNamespaceCode);
+  output_h (get_class_code tcpp_class.tcl_class Meta.HeaderNamespaceCode);
 
-  let extern_class = Gctx.defined common_ctx Define.DllExport in
+  let extern_class = Gctx.defined ctx.ctx_common Define.DllExport in
   let attribs =
     "HXCPP_" ^ (if extern_class then "EXTERN_" else "") ^ "CLASS_ATTRIBUTES"
   in
 
-  let dump_native_interfaces () =
-    List.iter
-      (fun (c, params) ->
-        output_h (" , public virtual " ^ join_class_path c.cl_path "::"))
-      (List.filter
-         (fun (t, _) -> is_native_gen_class t)
-         class_def.cl_implements)
+  let folder acc (cls, _) =
+    if is_native_class cls then
+      (Printf.sprintf "public virtual %s" (join_class_path cls.cl_path "::")) :: acc
+    else
+      acc
+    in
+  let all_parents =
+    tcpp_class.tcl_class.cl_implements
+    |> List.fold_left folder parents
+    |> List.rev in
+  let parent_string =
+    match all_parents with
+    | [] -> ""
+    | xs ->  " : " ^ String.concat ", " xs in
+
+  Printf.sprintf "class %s %s%s\n{\n\tpublic:\n" attribs tcpp_class.tcl_name parent_string |> output_h
+
+let generate_native_header base_ctx tcpp_class =
+  let common_ctx = base_ctx.ctx_common in
+  let class_def  = tcpp_class.tcl_class in
+  let class_path = class_def.cl_path in
+  let scriptable = has_tcpp_class_flag tcpp_class Scriptable in
+
+  let h_file = new_header_file common_ctx common_ctx.file class_path in
+  let ctx = file_context base_ctx h_file tcpp_class.tcl_debug_level true in
+
+  let parent, super =
+    match class_def.cl_super with
+    | Some (klass, params) ->
+        let name =
+          tcpp_to_string_suffix "_obj" (cpp_instance_type klass params)
+        in
+        ( name, name )
+    | None -> ("", "")
   in
+  let output_h = h_file#write in
+  let def_string = join_class_path class_path "_" in
 
-  if has_class_flag class_def CInterface && not nativeGen then (
-    output_h ("class " ^ attribs ^ " " ^ class_name ^ " {\n");
-    output_h "\tpublic:\n";
-    output_h ("\t\ttypedef " ^ super ^ " super;\n"))
-  else if super = "" then (
-    output_h ("class " ^ attribs ^ " " ^ class_name);
-    dump_native_interfaces ();
-    output_h "\n{\n\tpublic:\n")
-  else (
-    output_h ("class " ^ attribs ^ " " ^ class_name ^ " : public " ^ parent);
-    dump_native_interfaces ();
-    output_h "\n{\n\tpublic:\n";
-    if not nativeGen then (
-      output_h ("\t\ttypedef " ^ super ^ " super;\n");
-      output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n")));
-
-  let classId =
-    try Hashtbl.find baseCtx.ctx_type_ids (class_text class_def.cl_path)
-    with Not_found -> Int32.zero
+  gen_class_header ctx tcpp_class h_file scriptable (if super = "" then [] else [ (Printf.sprintf "public %s" parent) ]);
+      
+  CppGen.generate_native_constructor ctx output_h class_def true;
+
+  if has_tcpp_class_flag tcpp_class Boot then output_h "\t\tstatic void __boot();\n";
+
+  tcpp_class.tcl_static_variables
+  |> List.iter (gen_member_variable ctx class_def true);
+
+  tcpp_class.tcl_static_functions
+  |> List.iter (gen_member_function ctx class_def true);
+
+  tcpp_class.tcl_static_dynamic_functions
+  |> List.iter (gen_dynamic_function ctx class_def true);
+
+  tcpp_class.tcl_variables
+  |> List.iter (gen_member_variable ctx class_def false);
+
+  tcpp_class.tcl_functions
+  |> List.iter (gen_member_function ctx class_def false);
+
+  tcpp_class.tcl_dynamic_functions
+  |> List.iter (gen_dynamic_function ctx class_def false);
+
+  output_h (get_class_code class_def Meta.HeaderClassCode);
+  output_h "};\n\n";
+
+  end_namespace output_h class_path;
+
+  end_header_file output_h def_string;
+
+  h_file#close
+
+let generate_managed_header base_ctx tcpp_class =
+  let common_ctx = base_ctx.ctx_common in
+  let class_def = tcpp_class.tcl_class in
+  let class_path = class_def.cl_path in
+  let smart_class_name = snd class_path in
+  let scriptable = has_tcpp_class_flag tcpp_class Scriptable in
+  let class_name = tcpp_class.tcl_name in
+  let ptr_name = class_pointer class_def in
+  let can_quick_alloc = has_tcpp_class_flag tcpp_class QuickAlloc in
+  let gcName = gen_gc_name class_def.cl_path in
+
+  let constructor_type_args =
+    tcpp_class.tcl_class
+      |> constructor_arg_var_list
+      |> List.map (fun (t, a) -> Printf.sprintf "%s %s" t a)
+      |> String.concat "," in
+
+  let h_file = new_header_file common_ctx common_ctx.file class_path in
+  let ctx = file_context base_ctx h_file tcpp_class.tcl_debug_level true in
+  let strq = strq ctx.ctx_common in
+
+  let parent, super =
+    match tcpp_class.tcl_super with
+    | Some super ->
+        let name = tcpp_to_string_suffix "_obj" (cpp_instance_type super.tcl_class super.tcl_params) in
+        ( name, name )
+    | None -> ("::hx::Object", "::hx::Object")
   in
-  let classIdTxt = Printf.sprintf "0x%08lx" classId in
+  let output_h = h_file#write in
+  let def_string = join_class_path class_path "_" in
 
-  if (not (has_class_flag class_def CInterface)) && not nativeGen then (
-    output_h ("\t\t" ^ class_name ^ "();\n");
-    output_h "\n\tpublic:\n";
-    output_h ("\t\tenum { _hx_ClassId = " ^ classIdTxt ^ " };\n\n");
-    output_h ("\t\tvoid __construct(" ^ constructor_type_args ^ ");\n");
+  gen_class_header ctx tcpp_class h_file scriptable [ (Printf.sprintf "public %s" parent) ];
+
+  Printf.sprintf "\t\ttypedef %s super;\n" super |> output_h;
+  Printf.sprintf "\t\ttypedef %s OBJ_;\n" class_name |> output_h;
+
+  let classIdTxt = Printf.sprintf "0x%08lx" tcpp_class.tcl_id in
+
+  output_h ("\t\t" ^ class_name ^ "();\n");
+  output_h "\n\tpublic:\n";
+  output_h ("\t\tenum { _hx_ClassId = " ^ classIdTxt ^ " };\n\n");
+  output_h ("\t\tvoid __construct(" ^ constructor_type_args ^ ");\n");
+  Printf.sprintf "\t\tinline void *operator new(size_t inSize, bool inContainer=%b, const char* inName=%s)\n" (Option.is_some tcpp_class.tcl_container) gcName |> output_h;
+  output_h
+    "\t\t\t{ return ::hx::Object::operator new(inSize,inContainer,inName); }\n";
+  output_h "\t\tinline void *operator new(size_t inSize, int extra)\n";
+  Printf.sprintf "\t\t\t{ return ::hx::Object::operator new(inSize + extra, %b, %s); }\n" (Option.is_some tcpp_class.tcl_container) gcName |> output_h;
+  if has_class_flag class_def CAbstract then output_h "\n"
+  else if
+    can_inline_constructor base_ctx class_def
+  then (
+    output_h "\n";
+    CppGen.generate_constructor ctx
+      (fun str -> output_h ("\t\t" ^ str))
+      tcpp_class true)
+  else (
     output_h
-      ("\t\tinline void *operator new(size_t inSize, bool inContainer="
-     ^ isContainer ^ ",const char *inName=" ^ gcName ^ ")\n");
+      ("\t\tstatic " ^ ptr_name ^ " __new(" ^ constructor_type_args ^ ");\n");
+    if can_quick_alloc then
+      output_h
+        ("\t\tstatic " ^ ptr_name ^ " __alloc(::hx::Ctx *_hx_ctx"
+        ^ (if constructor_type_args = "" then ""
+            else "," ^ constructor_type_args)
+        ^ ");\n"));
+  if not (has_class_flag class_def CAbstract) then (
+    output_h "\t\tstatic void * _hx_vtable;\n";
+    output_h "\t\tstatic ::Dynamic __CreateEmpty();\n";
+    output_h "\t\tstatic ::Dynamic __Create(::hx::DynamicArray inArgs);\n");
+  if List.length (tcpp_class.tcl_dynamic_functions) > 0 then
     output_h
-      "\t\t\t{ return ::hx::Object::operator new(inSize,inContainer,inName); }\n";
-    output_h "\t\tinline void *operator new(size_t inSize, int extra)\n";
+      ("\t\tstatic void __alloc_dynamic_functions(::hx::Ctx *_hx_alloc," ^ class_name ^ " *_hx_obj);\n");
+  if scriptable then
+    output_h "\t\tstatic ::hx::ScriptFunction __script_construct;\n";
+  output_h ("\t\t//~" ^ class_name ^ "();\n\n");
+  output_h "\t\tHX_DO_RTTI_ALL;\n";
+  if has_tcpp_class_flag tcpp_class MemberGet then
     output_h
-      ("\t\t\t{ return ::hx::Object::operator new(inSize+extra," ^ isContainer
-     ^ "," ^ gcName ^ "); }\n");
-    if has_class_flag class_def CAbstract then output_h "\n"
-    else if
-      can_inline_constructor baseCtx class_def super_deps
-        (create_constructor_dependencies common_ctx)
-    then (
-      output_h "\n";
-      CppGen.generate_constructor ctx
-        (fun str -> output_h ("\t\t" ^ str))
-        class_def true)
-    else (
-      output_h
-        ("\t\tstatic " ^ ptr_name ^ " __new(" ^ constructor_type_args ^ ");\n");
-      if can_quick_alloc then
-        output_h
-          ("\t\tstatic " ^ ptr_name ^ " __alloc(::hx::Ctx *_hx_ctx"
-          ^ (if constructor_type_args = "" then ""
-             else "," ^ constructor_type_args)
-          ^ ");\n"));
-    if not (has_class_flag class_def CAbstract) then (
-      output_h "\t\tstatic void * _hx_vtable;\n";
-      output_h "\t\tstatic Dynamic __CreateEmpty();\n";
-      output_h "\t\tstatic Dynamic __Create(::hx::DynamicArray inArgs);\n");
-    if List.length (CppGen.dynamic_functions class_def) > 0 then
-      output_h
-        ("\t\tstatic void __alloc_dynamic_functions(::hx::Ctx *_hx_alloc,"
-       ^ class_name ^ " *_hx_obj);\n");
-    if scriptable then
-      output_h "\t\tstatic ::hx::ScriptFunction __script_construct;\n";
-    output_h ("\t\t//~" ^ class_name ^ "();\n\n");
-    output_h "\t\tHX_DO_RTTI_ALL;\n";
-    if has_get_member_field class_def then
-      output_h
-        "\t\t::hx::Val __Field(const ::String &inString, ::hx::PropertyAccess \
-         inCallProp);\n";
-    if has_get_static_field class_def then
-      output_h
-        "\t\tstatic bool __GetStatic(const ::String &inString, Dynamic \
-         &outValue, ::hx::PropertyAccess inCallProp);\n";
-    if has_set_member_field class_def then
-      output_h
-        "\t\t::hx::Val __SetField(const ::String &inString,const ::hx::Val \
-         &inValue, ::hx::PropertyAccess inCallProp);\n";
-    if has_set_static_field class_def then
+      "\t\t::hx::Val __Field(const ::String &inString, ::hx::PropertyAccess inCallProp);\n";
+  if has_tcpp_class_flag tcpp_class StaticGet then
+    output_h
+      "\t\tstatic bool __GetStatic(const ::String &inString, ::Dynamic &outValue, ::hx::PropertyAccess inCallProp);\n";
+  if has_tcpp_class_flag tcpp_class MemberSet then
+    output_h
+      "\t\t::hx::Val __SetField(const ::String &inString,const ::hx::Val &inValue, ::hx::PropertyAccess inCallProp);\n";
+  if has_tcpp_class_flag tcpp_class StaticSet then
+    output_h
+      "\t\tstatic bool __SetStatic(const ::String &inString, ::Dynamic &ioValue, ::hx::PropertyAccess inCallProp);\n";
+  if has_tcpp_class_flag tcpp_class GetFields then
+    output_h
+      "\t\tvoid __GetFields(::Array< ::String> &outFields);\n";
+  if has_tcpp_class_flag tcpp_class Compare then
+    output_h
+      ("\t\tint __Compare(const ::hx::Object *inRHS) const { "
+      ^ "return const_cast<" ^ class_name
+      ^ " *>(this)->__compare(::Dynamic((::hx::Object *)inRHS)); }\n");
+
+  output_h "\t\tstatic void __register();\n";
+  if tcpp_class.tcl_container = Some Current then (
+    output_h "\t\tvoid __Mark(HX_MARK_PARAMS);\n";
+    output_h "\t\tvoid __Visit(HX_VISIT_PARAMS);\n");
+
+  if List.length tcpp_class.tcl_native_interfaces > 0 then (
+    output_h "\n\t\tHX_NATIVE_IMPLEMENTATION\n";
+
+    tcpp_class.tcl_native_interfaces
+    |> CppGen.needed_interface_functions tcpp_class.tcl_functions
+    |> List.iter (fun func ->
+      let retVal   = type_to_string func.iff_return in
+      let ret      = if retVal = "void" then "" else "return " in
+      let argNames = List.map (fun (name, _, _) -> name) func.iff_args in
       output_h
-        "\t\tstatic bool __SetStatic(const ::String &inString, Dynamic \
-         &ioValue, ::hx::PropertyAccess inCallProp);\n";
-    if has_get_fields class_def then
-      output_h "\t\tvoid __GetFields(Array< ::String> &outFields);\n";
-
-    if has_compare_field class_def then
+        ("\t\t" ^ retVal ^ " " ^ func.iff_name ^ "( " ^ print_tfun_arg_list true func.iff_args ^ ") {\n");
       output_h
-        ("\t\tint __Compare(const ::hx::Object *inRHS) const { "
-       ^ "return const_cast<" ^ class_name
-       ^ " *>(this)->__compare(Dynamic((::hx::Object *)inRHS)); }\n");
-
-    output_h "\t\tstatic void __register();\n";
-    let native_gen = Meta.has Meta.NativeGen class_def.cl_meta in
-    let needs_gc_funcs = (not native_gen) && has_new_gc_references class_def in
-    if needs_gc_funcs then (
-      output_h "\t\tvoid __Mark(HX_MARK_PARAMS);\n";
-      output_h "\t\tvoid __Visit(HX_VISIT_PARAMS);\n");
-
-    let haxe_implementations, native_implementations =
-      CppGen.implementations class_def
-    in
-    let implements_haxe = Hashtbl.length haxe_implementations > 0 in
-    let implements_native = Hashtbl.length native_implementations > 0 in
+        ("\t\t\t" ^ ret ^ "super::" ^ func.iff_name ^ "( " ^ String.concat "," argNames ^ ");\n\t\t}\n"));
 
-    if implements_native then (
-      let implemented_instance_fields =
-        List.filter should_implement_field class_def.cl_ordered_fields
-      in
-      let neededInterfaceFunctions =
-        match implements_native with
-        | true ->
-            CppGen.needed_interface_functions implemented_instance_fields
-              native_implementations
-        | false -> []
-      in
+    output_h "\n");
 
-      output_h "\n\t\tHX_NATIVE_IMPLEMENTATION\n";
-      List.iter
-        (fun field ->
-          match (follow field.cf_type, field.cf_kind) with
-          | _, Method MethDynamic -> ()
-          | TFun (args, return_type), _ ->
-              let retVal = type_to_string return_type in
-              let ret = if retVal = "void" then "" else "return " in
-              let name = keyword_remap field.cf_name in
-              let argNames =
-                List.map (fun (name, _, _) -> keyword_remap name) args
-              in
-              output_h
-                ("\t\t" ^ retVal ^ " " ^ name ^ "( "
-                ^ print_tfun_arg_list true args
-                ^ ") {\n");
-              output_h
-                ("\t\t\t" ^ ret ^ "super::" ^ name ^ "( "
-               ^ String.concat "," argNames ^ ");\n\t\t}\n")
-          | _ -> ())
-        neededInterfaceFunctions;
-      output_h "\n");
-
-    output_h "\t\tbool _hx_isInstanceOf(int inClassId);\n";
-    if implements_haxe then (
-      output_h "\t\tvoid *_hx_getInterface(int inHash);\n";
-      (* generate header glue *)
-      let alreadyGlued = Hashtbl.create 0 in
-      Hashtbl.iter
-        (fun interface_name src ->
-          let rec check_interface interface =
-            let check_field field =
-              match (follow field.cf_type, field.cf_kind) with
-              | _, Method MethDynamic -> ()
-              | TFun (args, return_type), Method _ ->
-                  let cast = cpp_tfun_signature false args return_type in
-                  let class_implementation =
-                    find_class_implementation class_def field.cf_name interface
-                  in
-                  let realName = cpp_member_name_of field in
-                  let castKey = realName ^ "::" ^ cast in
-                  let castKey =
-                    if interface_name = "_hx_haxe_IMap" && realName = "set" then
-                      castKey ^ "*"
-                    else castKey
-                  in
-                  let implementationKey =
-                    realName ^ "::" ^ class_implementation
-                  in
-                  if castKey <> implementationKey then
-                    let glue =
-                      Printf.sprintf "%s_%08lx" field.cf_name
-                        (gen_hash32 0 cast)
-                    in
-                    if not (Hashtbl.mem alreadyGlued castKey) then (
-                      Hashtbl.replace alreadyGlued castKey ();
-                      let argList = print_tfun_arg_list true args in
-                      let returnType = type_to_string return_type in
-                      let headerCode =
-                        "\t\t" ^ returnType ^ " " ^ glue ^ "(" ^ argList
-                        ^ ");\n"
-                      in
-                      output_h headerCode;
-                      output_h "\n")
-              | _ -> ()
+  output_h "\t\tbool _hx_isInstanceOf(int inClassId);\n";
+  if List.length tcpp_class.tcl_haxe_interfaces > 0 then (
+    output_h "\t\tvoid *_hx_getInterface(int inHash);\n";
+    (* generate header glue *)
+    let alreadyGlued = Hashtbl.create 0 in
+    List.iter
+      (fun src ->
+        let rec check_interface (interface:tcpp_interface) =
+          let check_field func =
+            let cast = cpp_tfun_signature false func.iff_args func.iff_return in
+            let class_implementation = find_class_implementation func tcpp_class
             in
-            (match interface.cl_super with
-            | Some (super, _) -> check_interface super
-            | _ -> ());
-            List.iter check_field interface.cl_ordered_fields
+            let realName = cpp_member_name_of func.iff_field in
+            let castKey = realName ^ "::" ^ cast in
+            let castKey = match interface.if_class.cl_path with
+            | ([ "haxe" ], "IMap") when realName = "set" ->
+              castKey ^ "*"
+            | _ ->
+              castKey
+            in
+            let implementationKey =
+              realName ^ "::" ^ class_implementation
+            in
+            if castKey <> implementationKey then
+              let glue = Printf.sprintf "%s_%08lx" func.iff_field.cf_name (gen_hash32 0 cast) in
+              if not (Hashtbl.mem alreadyGlued castKey) then (
+                Hashtbl.replace alreadyGlued castKey ();
+                let argList = print_tfun_arg_list true func.iff_args in
+                let returnType = type_to_string func.iff_return in
+                let headerCode = "\t\t" ^ returnType ^ " " ^ glue ^ "(" ^ argList ^ ");\n" in
+                output_h headerCode;
+                output_h "\n")
           in
-          check_interface src)
-        haxe_implementations);
+          (match interface.if_extends with
+          | Some super -> check_interface super
+          | _ -> ());
+          List.iter check_field interface.if_functions
+        in
+        check_interface src)
+        tcpp_class.tcl_haxe_interfaces);
 
-    if has_init_field class_def then output_h "\t\tstatic void __init__();\n\n";
-    output_h
-      ("\t\t::String __ToString() const { return " ^ strq smart_class_name
-     ^ "; }\n\n"))
-  else if not nativeGen then output_h "\t\tHX_DO_INTERFACE_RTTI;\n\n"
-  else (
-    CppGen.generate_native_constructor ctx output_h class_def true;
-    (* native interface *) ());
+  if Option.is_some tcpp_class.tcl_init then output_h "\t\tstatic void __init__();\n\n";
+  output_h
+    ("\t\t::String __ToString() const { return " ^ strq smart_class_name ^ "; }\n\n");
 
-  if has_boot_field class_def then output_h "\t\tstatic void __boot();\n";
+  if has_tcpp_class_flag tcpp_class Boot then output_h "\t\tstatic void __boot();\n";
 
-  (match class_def.cl_array_access with
-  | Some t -> output_h ("\t\ttypedef " ^ type_string t ^ " __array_access;\n")
-  | _ -> ());
+  tcpp_class.tcl_static_functions
+  |> List.iter (gen_member_function ctx class_def true);
 
-  List.iter
-    (gen_member_def ctx class_def true (has_class_flag class_def CInterface))
-    (List.filter should_implement_field class_def.cl_ordered_statics);
+  tcpp_class.tcl_static_dynamic_functions
+  |> List.iter (gen_dynamic_function ctx class_def true);
 
-  let not_toString (field, args, _) =
-    field.cf_name <> "toString" || has_class_flag class_def CInterface
-  in
-  let functions = List.filter not_toString (all_virtual_functions class_def) in
-  if has_class_flag class_def CInterface then
-    List.iter
-      (fun (field, _, _) -> gen_member_def ctx class_def false true field)
-      functions
-  else
-    List.iter
-      (gen_member_def ctx class_def false false)
-      (List.filter should_implement_field class_def.cl_ordered_fields);
-
-  (if has_class_flag class_def CInterface then
-     match get_meta_string class_def.cl_meta Meta.ObjcProtocol with
-     | Some protocol ->
-         output_h
-           ("\t\tstatic id<" ^ protocol
-          ^ "> _hx_toProtocol(Dynamic inImplementation);\n")
-     | None -> ());
+  tcpp_class.tcl_static_variables
+  |> List.iter (gen_member_variable ctx class_def true);
+
+  tcpp_class.tcl_functions
+  |> List.iter (gen_member_function ctx class_def false);
+
+  tcpp_class.tcl_dynamic_functions
+  |> List.iter (gen_dynamic_function ctx class_def false);
+
+  tcpp_class.tcl_variables
+  |> List.iter (fun field -> gen_member_variable ctx class_def false field);
 
   output_h (get_class_code class_def Meta.HeaderClassCode);
   output_h "};\n\n";

File diff suppressed because it is too large
+ 719 - 874
src/generators/cpp/gen/cppGenClassImplementation.ml


+ 80 - 91
src/generators/cpp/gen/cppGenEnum.ml

@@ -1,64 +1,69 @@
 open Type
 open CppStrings
+open CppAst
 open CppAstTools
 open CppSourceWriter
 open CppContext
 open CppGen
 
-let generate baseCtx enum_def =
-  let common_ctx       = baseCtx.ctx_common in
-  let class_path       = enum_def.e_path in
+let constructor_arg_count constructor =
+  match constructor.ef_type with
+  | TFun(args, _) -> List.length args
+  | _ -> 0
+
+let gen_enum_constructor remap_class_name class_name output_cpp constructor =
+  match constructor.tef_field.ef_type with
+  | TFun (args, _) ->
+    Printf.sprintf "%s %s::%s(%s)\n" remap_class_name class_name constructor.tef_name (print_tfun_arg_list true args) |> output_cpp;
+    Printf.sprintf "{\n\treturn ::hx::CreateEnum<%s>(%s,%i,%i)" class_name constructor.tef_hash constructor.tef_field.ef_index (List.length args) |> output_cpp;
+
+    args
+      |> List.mapi (fun i (arg, _, _) -> Printf.sprintf "->_hx_init(%i,%s)" i (keyword_remap arg))
+      |> List.iter output_cpp;
+
+    output_cpp ";\n}\n\n"
+  | _ ->
+    output_cpp ( remap_class_name ^ " " ^ class_name ^ "::" ^ constructor.tef_name ^ ";\n\n" )
+
+let gen_static_reflection class_name output_cpp constructor =
+  let dyn = if constructor_arg_count constructor.tef_field > 0 then "_dyn()" else "" in
+  Printf.sprintf "\tif (inName==%s) { outValue = %s::%s%s; return true; }\n" constructor.tef_hash class_name constructor.tef_name dyn |> output_cpp
+
+let gen_dynamic_constructor class_name output_cpp constructor =
+  let count = constructor_arg_count constructor.tef_field in
+  if (count>0) then begin
+    Printf.sprintf "STATIC_HX_DEFINE_DYNAMIC_FUNC%i(%s, %s, return)\n\n" count class_name constructor.tef_name |> output_cpp;
+  end
+
+let generate base_ctx tcpp_enum =
+  let common_ctx       = base_ctx.ctx_common in
+  let class_path       = tcpp_enum.te_enum.e_path in
   let just_class_name  = (snd class_path) in
   let class_name       = just_class_name ^ "_obj" in
   let remap_class_name = ("::" ^ (join_class_path_remap class_path "::") )  in
   let cpp_file         = new_placed_cpp_file common_ctx class_path in
   let output_cpp       = (cpp_file#write) in
-  let debug            = if (Meta.has Meta.NoDebug enum_def.e_meta) || ( Gctx.defined common_ctx Define.NoDebug) then 0 else 1 in
+  let debug            = if (Meta.has Meta.NoDebug tcpp_enum.te_enum.e_meta) || ( Gctx.defined common_ctx Define.NoDebug) then 0 else 1 in
 
-  let ctx = file_context baseCtx cpp_file debug false in
+  let ctx = file_context base_ctx cpp_file debug false in
   let strq = strq ctx.ctx_common in
-
-  let classId = try Hashtbl.find baseCtx.ctx_type_ids (class_text enum_def.e_path) with Not_found -> Int32.zero in
-  let classIdTxt = Printf.sprintf "0x%08lx" classId in
+  let classIdTxt = Printf.sprintf "0x%08lx" tcpp_enum.te_id in
 
   if (debug>1) then
-      print_endline ("Found enum definition:" ^ (join_class_path  class_path "::" ));
+    print_endline ("Found enum definition:" ^ (join_class_path  class_path "::" ));
 
   cpp_file#write_h "#include <hxcpp.h>\n\n";
 
-  let super_deps       = create_super_dependencies common_ctx in
-  let referenced,flags = CppReferences.find_referenced_types_flags ctx (TEnumDecl enum_def) "*" super_deps (Hashtbl.create 0) false false false in
+  let referenced,flags = CppReferences.find_referenced_types_flags ctx (TEnumDecl tcpp_enum.te_enum) None ctx.ctx_super_deps PathMap.empty false false false in
   List.iter (add_include cpp_file) referenced;
 
   begin_namespace output_cpp class_path;
   output_cpp "\n";
 
-  PMap.iter (fun _ constructor ->
-      let name = keyword_remap constructor.ef_name in
-      match constructor.ef_type with
-      | TFun (args,_) ->
-        output_cpp (remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ "(" ^
-            (print_tfun_arg_list true args) ^")\n");
-
-        output_cpp ("{\n\treturn ::hx::CreateEnum< " ^ class_name ^ " >(" ^ (strq name) ^ "," ^
-            (string_of_int constructor.ef_index) ^ "," ^ (string_of_int (List.length args)) ^  ")" );
-          ExtList.List.iteri (fun i (arg,_,_) -> output_cpp ("->_hx_init(" ^ (string_of_int i) ^ "," ^ (keyword_remap arg) ^ ")")) args;
-        output_cpp ";\n}\n\n"
-      | _ ->
-        output_cpp ( remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ ";\n\n" )
-  ) enum_def.e_constrs;
-
-
-  let constructor_arg_count constructor =
-      (match constructor.ef_type with | TFun(args,_) -> List.length args | _ -> 0 )
-  in
+  List.iter (gen_enum_constructor remap_class_name class_name output_cpp) tcpp_enum.te_constructors;
 
   output_cpp ("bool " ^ class_name ^ "::__GetStatic(const ::String &inName, ::Dynamic &outValue, ::hx::PropertyAccess inCallProp)\n{\n");
-  PMap.iter (fun _ constructor ->
-      let name = constructor.ef_name in
-      let dyn = if constructor_arg_count constructor > 0 then "_dyn()" else "" in
-      output_cpp ("\tif (inName==" ^ strq name ^ ") { outValue = " ^ class_name ^ "::" ^ keyword_remap name ^ dyn ^ "; return true; }\n" );
-  ) enum_def.e_constrs;
+  List.iter (gen_static_reflection class_name output_cpp) tcpp_enum.te_constructors;
   output_cpp ("\treturn super::__GetStatic(inName, outValue, inCallProp);\n}\n\n");
 
   output_cpp ("HX_DEFINE_CREATE_ENUM(" ^ class_name ^ ")\n\n");
@@ -68,51 +73,35 @@ let generate baseCtx enum_def =
   output_cpp ("}\n");
 
   output_cpp ("int " ^ class_name ^ "::__FindIndex(::String inName)\n{\n");
-  PMap.iter (fun _ constructor ->
-      let name = constructor.ef_name in
-      let idx = string_of_int constructor.ef_index in
-      output_cpp ("\tif (inName==" ^ (strq name) ^ ") return " ^ idx ^ ";\n") ) enum_def.e_constrs;
+  List.iter
+    (fun constructor -> Printf.sprintf "\tif (inName==%s) return %i;\n" constructor.tef_hash constructor.tef_field.ef_index |> output_cpp)
+    tcpp_enum.te_constructors;
   output_cpp ("\treturn super::__FindIndex(inName);\n");
   output_cpp ("}\n\n");
 
   (* Dynamic versions of constructors *)
-  let dump_dynamic_constructor _ constr =
-      let count = constructor_arg_count constr in
-      if (count>0) then begin
-        let nargs = string_of_int count in
-        output_cpp ("STATIC_HX_DEFINE_DYNAMIC_FUNC" ^ nargs ^ "(" ^ class_name ^ "," ^
-              (keyword_remap constr.ef_name) ^ ",return)\n\n");
-      end
-  in
-  PMap.iter dump_dynamic_constructor enum_def.e_constrs;
-
+  List.iter (gen_dynamic_constructor class_name output_cpp) tcpp_enum.te_constructors;
 
   output_cpp ("int " ^ class_name ^ "::__FindArgCount(::String inName)\n{\n");
-  PMap.iter (fun _ constructor ->
-      let name = constructor.ef_name in
-      let count = string_of_int (constructor_arg_count constructor) in
-      output_cpp ("\tif (inName==" ^ (strq name) ^ ") return " ^ count ^ ";\n") ) enum_def.e_constrs;
-      output_cpp ("\treturn super::__FindArgCount(inName);\n");
-      output_cpp ("}\n\n");
+  List.iter
+    (fun constructor -> Printf.sprintf "\tif (inName==%s) return %i;\n" constructor.tef_hash (constructor_arg_count constructor.tef_field) |> output_cpp)
+    tcpp_enum.te_constructors;
+
+  output_cpp ("\treturn super::__FindArgCount(inName);\n");
+  output_cpp ("}\n\n");
 
   (* Dynamic "Get" Field function - string version *)
   output_cpp ("::hx::Val " ^ class_name ^ "::__Field(const ::String &inName,::hx::PropertyAccess inCallProp)\n{\n");
-  let dump_constructor_test _ constr =
-      output_cpp ("\tif (inName==" ^ (strq constr.ef_name) ^ ") return " ^
-                  (keyword_remap constr.ef_name) );
-      if ( (constructor_arg_count constr) > 0 ) then output_cpp "_dyn()";
+  let dump_constructor_test constructor =
+      output_cpp ("\tif (inName==" ^ constructor.tef_hash ^ ") return " ^ constructor.tef_name );
+      if ( (constructor_arg_count constructor.tef_field) > 0 ) then output_cpp "_dyn()";
       output_cpp (";\n")
   in
-  PMap.iter dump_constructor_test enum_def.e_constrs;
+  List.iter dump_constructor_test tcpp_enum.te_constructors;
   output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n");
 
   output_cpp ("static ::String " ^ class_name ^ "_sStaticFields[] = {\n");
-  let sorted =
-      List.sort (fun f1 f2 -> (PMap.find f1 enum_def.e_constrs ).ef_index -
-              (PMap.find f2 enum_def.e_constrs ).ef_index )
-        (pmap_keys enum_def.e_constrs) in
-
-    List.iter (fun name -> output_cpp ("\t" ^ (strq name) ^ ",\n") ) sorted;
+  List.iter (fun constructor -> output_cpp ("\t" ^ constructor.tef_hash ^ ",\n") ) tcpp_enum.te_constructors;
 
   output_cpp "\t::String(null())\n};\n\n";
 
@@ -121,7 +110,7 @@ let generate baseCtx enum_def =
 
   output_cpp ("::hx::Class " ^ class_name ^ "::__mClass;\n\n");
 
-  output_cpp ("Dynamic __Create_" ^ class_name ^ "() { return new " ^ class_name ^ "; }\n\n");
+  output_cpp ("::Dynamic __Create_" ^ class_name ^ "() { return new " ^ class_name ^ "; }\n\n");
 
   output_cpp ("void " ^ class_name ^ "::__register()\n{\n");
   let text_name = strq (join_class_path class_path ".") in
@@ -136,19 +125,21 @@ let generate baseCtx enum_def =
   output_cpp "}\n\n";
 
   output_cpp ("void " ^ class_name ^ "::__boot()\n{\n");
-  (match Texpr.build_metadata common_ctx.basic (TEnumDecl enum_def) with
-      | Some expr ->
-        let ctx = file_context ctx cpp_file 1 false in
-        gen_cpp_init ctx class_name "boot" "__mClass->__meta__ = " expr
-      | _ -> () );
-  PMap.iter (fun _ constructor ->
-      let name = constructor.ef_name in
-      match constructor.ef_type with
-      | TFun (_,_) -> ()
+  (match Texpr.build_metadata common_ctx.basic (TEnumDecl tcpp_enum.te_enum) with
+  | Some expr ->
+    let ctx = file_context ctx cpp_file 1 false in
+    gen_cpp_init ctx class_name "boot" "__mClass->__meta__ = " expr
+  | _ -> () );
+
+  List.iter
+    (fun constructor ->
+      match constructor.tef_field.ef_type with
+      | TFun (_,_) ->
+        ()
       | _ ->
-        output_cpp ( (keyword_remap name) ^ " = ::hx::CreateConstEnum< " ^ class_name ^ " >(" ^ (strq name) ^  "," ^
-            (string_of_int constructor.ef_index) ^ ");\n" )
-  ) enum_def.e_constrs;
+        Printf.sprintf "%s = ::hx::CreateConstEnum<%s>(%s, %i);\n" constructor.tef_name class_name constructor.tef_hash constructor.tef_field.ef_index |> output_cpp)
+    tcpp_enum.te_constructors;
+
   output_cpp ("}\n\n");
 
   output_cpp "\n";
@@ -164,7 +155,7 @@ let generate baseCtx enum_def =
 
   List.iter2 (fun r f -> gen_forward_decl h_file r f) referenced flags;
 
-  output_h ( get_code enum_def.e_meta Meta.HeaderCode );
+  output_h ( get_code tcpp_enum.te_enum.e_meta Meta.HeaderCode );
 
   begin_namespace output_h class_path;
 
@@ -178,24 +169,22 @@ let generate baseCtx enum_def =
   output_h ("\t\tHX_DO_ENUM_RTTI;\n");
   output_h ("\t\tstatic void __boot();\n");
   output_h ("\t\tstatic void __register();\n");
-  output_h ("\t\tstatic bool __GetStatic(const ::String &inName, Dynamic &outValue, ::hx::PropertyAccess inCallProp);\n");
+  output_h ("\t\tstatic bool __GetStatic(const ::String &inName, ::Dynamic &outValue, ::hx::PropertyAccess inCallProp);\n");
   output_h ("\t\t::String GetEnumName( ) const { return " ^ (strq (join_class_path class_path "."))  ^ "; }\n" );
   output_h ("\t\t::String __ToString() const { return " ^ (strq (just_class_name ^ ".") )^ " + _hx_tag; }\n");
   output_h ("\t\tbool _hx_isInstanceOf(int inClassId);\n\n");
 
-
-  PMap.iter (fun _ constructor ->
-      let name = keyword_remap constructor.ef_name in
-      output_h ( "\t\tstatic " ^  remap_class_name ^ " " ^ name );
-      match constructor.ef_type with
+  List.iter
+    (fun constructor ->
+      Printf.sprintf "\t\tstatic %s %s" remap_class_name constructor.tef_name |> output_h;
+      match constructor.tef_field.ef_type with
       | TFun (args,_) ->
-        output_h ( "(" ^ (print_tfun_arg_list true args) ^");\n");
-        output_h ( "\t\tstatic ::Dynamic " ^ name ^ "_dyn();\n");
+        Printf.sprintf "(%s);\n" (print_tfun_arg_list true args) |> output_h;
+        Printf.sprintf "\t\tstatic ::Dynamic %s_dyn();\n" constructor.tef_name |> output_h;
       | _ ->
         output_h ";\n";
-        output_h ( "\t\tstatic inline " ^  remap_class_name ^ " " ^ name ^
-                  "_dyn() { return " ^name ^ "; }\n" );
-  ) enum_def.e_constrs;
+        Printf.sprintf "\t\tstatic inline %s %s_dyn() { return %s; }\n" remap_class_name constructor.tef_name constructor.tef_name |> output_h;)
+    tcpp_enum.te_constructors;
 
   output_h "};\n\n";
 

+ 186 - 0
src/generators/cpp/gen/cppGenInterfaceHeader.ml

@@ -0,0 +1,186 @@
+open Ast
+open Type
+open Common
+open CppStrings
+open CppTypeUtils
+open CppAst
+open CppAstTools
+open CppSourceWriter
+open CppContext
+open CppGen
+
+let attribs common_ctx = match Gctx.defined common_ctx Define.DllExport with
+  | true -> "HXCPP_EXTERN_CLASS_ATTRIBUTES"
+  | false -> "HXCPP_CLASS_ATTRIBUTES"
+
+let gen_native_function ctx interface func =
+  let output   = ctx.ctx_output in
+  let gen_args = print_tfun_arg_list true in
+  let strq     = strq ctx.ctx_common in
+
+  Printf.sprintf "\t\tvirtual %s %s(%s)=0;\n" (type_to_string func.iff_return) func.iff_name (gen_args func.iff_args) |> output;
+  if reflective interface.if_class func.iff_field then
+    if Gctx.defined ctx.ctx_common Define.DynamicInterfaceClosures then
+      Printf.sprintf
+        "\t\tinline ::Dynamic %s_dyn() { return __Field( %s, ::hx::paccDynamic ); }\n"
+        func.iff_name
+        (strq func.iff_field.cf_name) |> output
+    else
+      Printf.sprintf "\t\tvirtual ::Dynamic %s_dyn()=0;\n" func.iff_name |> output
+
+let gen_function ctx interface func =
+  let output       = ctx.ctx_output in
+  let argList      = print_tfun_arg_list true func.iff_args in
+  let returnType   = type_to_string func.iff_return in
+  let returnStr    = if returnType = "void" then "" else "return " in
+  let commaArgList = if argList = "" then argList else "," ^ argList in
+  let cast = Printf.sprintf "::hx::interface_cast< ::%s_obj *>" (join_class_path_remap interface.if_class.cl_path "::") in
+
+  Printf.sprintf "\t\t%s (::hx::Object :: *_hx_%s)(%s);\n" returnType func.iff_name argList |> output;
+  Printf.sprintf "\t\tstatic inline %s %s( ::Dynamic _hx_%s ){\n" returnType func.iff_name commaArgList |> output;
+  output "\t\t\t#ifdef HXCPP_CHECK_POINTER\n";
+  output "\t\t\tif (::hx::IsNull(_hx_)) ::hx::NullReference(\"Object\", false);\n";
+  output "\t\t\t#ifdef HXCPP_GC_CHECK_POINTER\n";
+  output "\t\t\t\tGCCheckPointer(_hx_.mPtr);\n";
+  output "\t\t\t#endif\n";
+  output "\t\t\t#endif\n";
+  Printf.sprintf
+    "\t\t\t%s( _hx_.mPtr->*( %s(_hx_.mPtr->_hx_getInterface(%s)))->_hx_%s )(%s);\n\t\t}\n"
+    returnStr cast interface.if_hash func.iff_name (print_arg_names func.iff_args) |> output
+
+let gen_includes h_file interface_def =
+  let add_class_includes cls =
+    match get_all_meta_string_path cls.cl_meta Meta.Include with
+    | [] ->
+      h_file#add_include cls.cl_path
+    | includes ->
+      List.iter (fun inc -> h_file#add_include (path_of_string inc)) includes in
+
+  (* Include the real header file for the super class *)
+  match interface_def.cl_super with
+  | Some (cls, _) -> add_class_includes cls
+  | _ -> ();
+
+  (* And any interfaces ... *)
+  interface_def.cl_implements
+    |> real_interfaces
+    |> List.iter (fun (cls, _) -> add_class_includes cls)
+
+let gen_forward_decls h_file tcpp_interface ctx common_ctx =
+  (* Only need to forward-declare classes that are mentioned in the header file (ie, not the implementation) *)
+  let header_referenced, header_flags =
+    CppReferences.find_referenced_types_flags ctx (TClassDecl tcpp_interface.if_class) None ctx.ctx_super_deps PathMap.empty true false tcpp_interface.if_scriptable
+  in
+
+  List.iter2
+    (fun r f -> gen_forward_decl h_file r f)
+    header_referenced header_flags
+
+let gen_header_includes interface_def output_h =
+  output_h "\n";
+  output_h (get_class_code interface_def Meta.HeaderCode);
+  let includes = get_all_meta_string_path interface_def.cl_meta Meta.HeaderInclude in
+  let printer inc = output_h ("#include \"" ^ inc ^ "\"\n") in
+  List.iter printer includes
+
+let gen_body tcpp_interface ctx output_h iter =
+  if has_boot_field tcpp_interface.if_class then output_h "\t\tstatic void __boot();\n";
+
+  all_interface_functions tcpp_interface |> List.iter iter;
+
+  match get_meta_string tcpp_interface.if_class.cl_meta Meta.ObjcProtocol with
+  | Some protocol ->
+    output_h ("\t\tstatic id<" ^ protocol ^ "> _hx_toProtocol(::Dynamic inImplementation);\n")
+  | None ->
+    ();
+
+  output_h (get_class_code tcpp_interface.if_class Meta.HeaderClassCode)
+
+let generate_native_interface base_ctx tcpp_interface =
+  let common_ctx = base_ctx.ctx_common in
+  let class_path = tcpp_interface.if_class.cl_path in
+
+  let parent, super =
+    match tcpp_interface.if_class.cl_super with
+    | Some (klass, params) ->
+      let name = tcpp_to_string_suffix "_obj" (cpp_instance_type klass params) in
+      ( "virtual " ^ name, name )
+    | None ->
+      ("virtual ::hx::NativeInterface", "::hx::NativeInterface")
+  in
+
+  let h_file     = new_header_file common_ctx common_ctx.file class_path in
+  let ctx        = file_context base_ctx h_file tcpp_interface.if_debug_level true in
+  let output_h   = h_file#write in
+  let def_string = join_class_path class_path "_" in
+
+  begin_header_file h_file#write_h def_string true;
+
+  gen_includes h_file tcpp_interface.if_class;
+  gen_forward_decls h_file tcpp_interface ctx common_ctx;
+  gen_header_includes tcpp_interface.if_class output_h;
+
+  begin_namespace output_h class_path;
+  output_h "\n\n";
+  output_h (get_class_code tcpp_interface.if_class Meta.HeaderNamespaceCode);
+
+  output_h ("class " ^ (attribs common_ctx) ^ " " ^ tcpp_interface.if_name ^ " : public " ^ parent);
+  
+  tcpp_interface.if_class.cl_implements
+    |> List.filter (fun (t, _) -> is_native_gen_class t)
+    |> List.iter (fun (c, _) -> output_h (" , public virtual " ^ join_class_path c.cl_path "::"));
+
+  output_h "\n{\n\tpublic:\n";
+  output_h ("\t\ttypedef " ^ super ^ " super;\n");
+  output_h ("\t\ttypedef " ^ tcpp_interface.if_name ^ " OBJ_;\n");
+
+  CppGen.generate_native_constructor ctx output_h tcpp_interface.if_class true;
+
+  gen_body tcpp_interface ctx output_h (gen_native_function ctx tcpp_interface);
+  
+  output_h "};\n\n";
+
+  end_namespace output_h class_path;
+  end_header_file output_h def_string;
+
+  h_file#close
+
+let generate_managed_interface base_ctx tcpp_interface =
+  let common_ctx = base_ctx.ctx_common in
+  let class_path = tcpp_interface.if_class.cl_path in
+
+  let super =
+    match tcpp_interface.if_class.cl_super with
+    | Some (klass, params) ->
+      tcpp_to_string_suffix "_obj" (cpp_instance_type klass params)
+    | None ->
+      "::hx::Object"
+  in
+  let h_file     = new_header_file common_ctx common_ctx.file class_path in
+  let ctx        = file_context base_ctx h_file tcpp_interface.if_debug_level true in
+  let output_h   = h_file#write in
+  let def_string = join_class_path class_path "_" in
+
+  begin_header_file h_file#write_h def_string false;
+
+  gen_includes h_file tcpp_interface.if_class;
+  gen_forward_decls h_file tcpp_interface ctx common_ctx;
+  gen_header_includes tcpp_interface.if_class output_h;
+
+  begin_namespace output_h class_path;
+  output_h "\n\n";
+  output_h (get_class_code tcpp_interface.if_class Meta.HeaderNamespaceCode);
+
+  output_h ("class " ^ (attribs common_ctx) ^ " " ^ tcpp_interface.if_name ^ " {\n");
+  output_h "\tpublic:\n";
+  output_h ("\t\ttypedef " ^ super ^ " super;\n");
+  output_h "\t\tHX_DO_INTERFACE_RTTI;\n\n";
+
+  gen_body tcpp_interface ctx output_h (gen_function ctx tcpp_interface);
+  
+  output_h "};\n\n";
+
+  end_namespace output_h class_path;
+  end_header_file output_h def_string;
+
+  h_file#close

+ 264 - 0
src/generators/cpp/gen/cppGenInterfaceImplementation.ml

@@ -0,0 +1,264 @@
+open Ast
+open Type
+open Error
+open CppStrings
+open CppTypeUtils
+open CppAst
+open CppAstTools
+open CppSourceWriter
+open CppContext
+open CppGen
+
+let generate_protocol_delegate ctx protocol full_class_name functions output =
+  let name = "_hx_" ^ protocol ^ "_delegate" in
+  output ("@interface " ^ name ^ " : NSObject<" ^ protocol ^ "> {\n");
+  output "\t::hx::Object *haxeObj;\n";
+  output "}\n";
+  output "@end\n\n";
+  output ("@implementation " ^ name ^ "\n");
+  output "- (id)initWithImplementation:( ::hx::Object *)inInplemnetation {\n";
+  output "  if (self = [super init]) {\n";
+  output "     self->haxeObj = inInplemnetation;\n";
+  output "     GCAddRoot(&self->haxeObj);\n";
+  output "  }\n";
+  output "  return self;\n";
+  output "}\n";
+  output "- (void)dealloc {\n";
+  output "   GCRemoveRoot(&self->haxeObj);\n";
+  output "   #ifndef OBJC_ARC\n";
+  output "   [super dealloc];\n";
+  output "   #endif\n";
+  output "}\n\n";
+
+  let dump_delegate func =
+    let retStr = type_to_string func.iff_return in
+    let fieldName, argNames =
+      match get_meta_string func.iff_field.cf_meta Meta.ObjcProtocol with
+      | Some nativeName ->
+        let parts = ExtString.String.nsplit nativeName ":" in
+        (List.hd parts, parts)
+      | None -> (func.iff_field.cf_name, List.map (fun (n, _, _) -> n) func.iff_args)
+    in
+    output ("- (" ^ retStr ^ ") " ^ fieldName);
+
+    let first = ref true in
+    (try
+        List.iter2
+          (fun (name, _, argType) signature_name ->
+            if !first then
+              output (" :(" ^ type_to_string argType ^ ")" ^ name)
+            else
+              output
+                (" " ^ signature_name ^ ":(" ^ type_to_string argType ^ ")"
+              ^ name);
+            first := false)
+          func.iff_args argNames
+      with Invalid_argument _ ->
+        abort
+          (let argString =
+            String.concat "," (List.map (fun (name, _, _) -> name) func.iff_args)
+          in
+          "Invalid arg count in delegate in " ^ func.iff_field.cf_name ^ " '"
+          ^ func.iff_field.cf_name ^ "," ^ argString ^ "' != '"
+          ^ String.concat "," argNames ^ "'")
+          func.iff_field.cf_pos);
+    output " {\n";
+    output "\t::hx::NativeAttach _hx_attach;\n";
+    output
+      ((if retStr = "void" then "\t" else "\treturn ")
+      ^ full_class_name ^ "::"
+      ^ func.iff_name
+      ^ "(haxeObj");
+    List.iter (fun (name, _, _) -> output ("," ^ name)) func.iff_args;
+    output ");\n}\n\n"
+  in
+  List.iter dump_delegate functions;
+
+  output "@end\n\n"
+
+let generate_managed_interface base_ctx tcpp_interface =
+  let class_path = tcpp_interface.if_class.cl_path in
+  let cpp_file = new_placed_cpp_file base_ctx.ctx_common class_path in
+  let cpp_ctx = file_context base_ctx cpp_file tcpp_interface.if_debug_level false in
+  let ctx = cpp_ctx in
+  let output_cpp = cpp_file#write in
+  let strq = strq ctx.ctx_common in
+
+  cpp_file#write_h "#include <hxcpp.h>\n\n";
+
+  let all_referenced =
+    CppReferences.find_referenced_types ctx (TClassDecl tcpp_interface.if_class) ctx.ctx_super_deps
+    ctx.ctx_constructor_deps false false tcpp_interface.if_scriptable
+  in
+  List.iter (add_include cpp_file) all_referenced;
+
+  if tcpp_interface.if_scriptable then cpp_file#write_h "#include <hx/Scriptable.h>\n";
+
+  cpp_file#write_h "\n";
+
+  output_cpp (get_class_code tcpp_interface.if_class Meta.CppFileCode);
+  let includes = get_all_meta_string_path tcpp_interface.if_class.cl_meta Meta.CppInclude in
+  let printer inc = output_cpp ("#include \"" ^ inc ^ "\"\n") in
+  List.iter printer includes;
+
+  begin_namespace output_cpp class_path;
+  output_cpp "\n";
+
+  output_cpp (get_class_code tcpp_interface.if_class Meta.CppNamespaceCode);
+
+  output_cpp "\n";
+
+  (* cl_interface *)
+  let var_folder cur acc = if (reflective tcpp_interface.if_class cur) then strq cur.cf_name :: acc else acc in
+  let fun_folder cur acc = if (reflective tcpp_interface.if_class cur.iff_field) then strq cur.iff_field.cf_name :: acc else acc in
+  let members =
+    [ "\t::String(null())" ]
+    |> List.fold_right var_folder tcpp_interface.if_variables
+    |> List.fold_right fun_folder tcpp_interface.if_functions
+    |> List.map (fun n -> Printf.sprintf "\t%s" n)
+  in
+
+  let sMemberFields =
+    if List.length members > 1 then
+      let memberFields = tcpp_interface.if_name ^ "_sMemberFields" in
+      let concat       = String.concat ",\n" members in
+
+      Printf.sprintf "static ::String %s[] = {\n%s\n};\n\n" memberFields concat |> output_cpp;
+
+      memberFields
+    else
+      "0 /* sMemberFields */"
+  in
+
+  let all_functions = all_interface_functions tcpp_interface in
+
+  if tcpp_interface.if_scriptable then (
+    let dump_script_field idx func =
+      let args = print_tfun_arg_list true func.iff_args in
+      let return_type = type_to_string func.iff_return in
+      let ret = if return_type = "Void" || return_type = "void" then " " else "return " in
+
+      output_cpp ("\t" ^ return_type ^ " " ^ func.iff_name ^ "( " ^ args ^ " ) {\n");
+      output_cpp "\t\t::hx::CppiaCtx *__ctx = ::hx::CppiaCtx::getCurrent();\n";
+      output_cpp "\t\t::hx::AutoStack __as(__ctx);\n";
+      output_cpp "\t\t__ctx->pushObject(this);\n";
+      List.iter
+        (fun (name, opt, t) ->
+          output_cpp
+            ("\t\t__ctx->push" ^ CppCppia.script_type t opt ^ "(" ^ name ^ ");\n"))
+        func.iff_args;
+      let interfaceSlot = string_of_int (func.iff_script_slot |> Option.map (fun v -> -v) |>  Option.default 0) in
+      output_cpp
+        ("\t\t" ^ ret ^ "__ctx->run"
+        ^ CppCppia.script_type func.iff_return false
+        ^ "(__GetScriptVTable()[" ^ interfaceSlot ^ "]);\n");
+      output_cpp "\t}\n";
+    in
+
+    let script_name = tcpp_interface.if_name ^ "__scriptable" in
+
+    output_cpp ("class " ^ script_name ^ " : public ::hx::Object {\n");
+    output_cpp "public:\n";
+
+    ExtList.List.iteri dump_script_field all_functions;
+    output_cpp "};\n\n";
+
+    let generate_script_function func =
+      let scriptName = ("__s_" ^ func.iff_field.cf_name) in
+
+      output_cpp ("\nstatic void CPPIA_CALL " ^ scriptName ^ "(::hx::CppiaCtx *ctx) {\n");
+      let ret =
+        match cpp_type_of func.iff_return with
+        | TCppScalar "bool" -> "b"
+        | _ -> CppCppia.script_signature func.iff_return false in
+      if ret <> "v" then
+        output_cpp ("ctx->return" ^ CppCppia.script_type func.iff_return false ^ "(");
+
+      let signature =
+        output_cpp (tcpp_interface.if_name ^ "::" ^ func.iff_name ^ "(ctx->getThis()" ^ if List.length func.iff_args > 0 then "," else "");
+
+        let signature, _, _ =
+          List.fold_left
+            (fun (signature, sep, size) (_, opt, t) ->
+              output_cpp (sep ^ "ctx->get" ^ CppCppia.script_type t opt ^ "(" ^ size ^ ")");
+              ( signature ^ CppCppia.script_signature t opt, ",", size ^ "+sizeof(" ^ CppCppia.script_size_type t opt ^ ")" ))
+            (ret, "", "sizeof(void*)") func.iff_args in
+        output_cpp ")";
+        signature
+      in
+
+      if ret <> "v" then output_cpp ")";
+      output_cpp ";\n}\n";
+      (signature, func)
+    in
+
+    (match all_functions with
+    | [] ->
+      output_cpp "static ::hx::ScriptNamedFunction *__scriptableFunctions = 0;\n"
+    | _ ->
+      let sig_and_funcs = List.map generate_script_function all_functions in
+
+      output_cpp "#ifndef HXCPP_CPPIA_SUPER_ARG\n";
+      output_cpp "#define HXCPP_CPPIA_SUPER_ARG(x)\n";
+      output_cpp "#endif\n";
+      output_cpp "static ::hx::ScriptNamedFunction __scriptableFunctions[] = {\n";
+      let dump_func (s, func) =
+        Printf.sprintf
+          "\t::hx::ScriptNamedFunction(\"%s\", __s_%s, \"%s\", false HXCPP_CPPIA_SUPER_ARG(0)),\n"
+          func.iff_field.cf_name
+          func.iff_field.cf_name
+          s |> output_cpp;
+      in
+      List.iter dump_func sig_and_funcs;
+      output_cpp "\t::hx::ScriptNamedFunction(0,0,0 HXCPP_CPPIA_SUPER_ARG(0) ) };\n");
+
+    let mapper f = Printf.sprintf "\t%s&%s::%s" (cpp_tfun_signature true f.iff_args f.iff_return) script_name f.iff_name in
+    let strings =
+      all_functions
+      |> List.map mapper
+      |> String.concat ",\n" in
+
+    Printf.sprintf "\n\n%s %s_scriptable = {\n%s\n};\n" tcpp_interface.if_name tcpp_interface.if_name strings |> output_cpp);
+
+  let class_name_text = join_class_path class_path "." in
+
+  output_cpp ("::hx::Class " ^ tcpp_interface.if_name ^ "::__mClass;\n\n");
+
+  output_cpp ("void " ^ tcpp_interface.if_name ^ "::__register()\n{\n");
+
+  output_cpp "\t::hx::Static(__mClass) = new ::hx::Class_obj();\n";
+  output_cpp ("\t__mClass->mName = " ^ strq class_name_text ^ ";\n");
+  output_cpp "\t__mClass->mSuper = &super::__SGetClass();\n";
+  output_cpp ("\t__mClass->mMembers = ::hx::Class_obj::dupFunctions(" ^ sMemberFields ^ ");\n");
+  output_cpp ("\t__mClass->mCanCast = ::hx::TIsInterface< (int)" ^ tcpp_interface.if_hash ^ " >;\n");
+  output_cpp "\t::hx::_hx_RegisterClass(__mClass->mName, __mClass);\n";
+  if tcpp_interface.if_scriptable then
+    output_cpp ("  HX_SCRIPTABLE_REGISTER_INTERFACE(\"" ^ class_name_text ^ "\"," ^ tcpp_interface.if_name ^ ");\n");
+  output_cpp "}\n\n";
+
+  if has_boot_field tcpp_interface.if_class then (
+    output_cpp ("void " ^ tcpp_interface.if_name ^ "::__boot()\n{\n");
+
+    let dot_name = join_class_path tcpp_interface.if_class.cl_path "." in
+
+    (match tcpp_interface.if_meta with
+    | Some expr -> gen_cpp_init ctx dot_name "boot" "__mClass->__meta__ = " expr
+    | None -> ());
+
+    (match tcpp_interface.if_rtti with
+    | Some expr -> gen_cpp_init ctx dot_name "boot" "__mClass->__rtti__ = " expr
+    | None -> ());
+
+    output_cpp "}\n\n");
+
+  end_namespace output_cpp class_path;
+
+  if Meta.has Meta.ObjcProtocol tcpp_interface.if_class.cl_meta then (
+    let full_class_name = ("::" ^ join_class_path_remap class_path "::") ^ "_obj" in
+    let protocol = get_meta_string tcpp_interface.if_class.cl_meta Meta.ObjcProtocol |> Option.default "" in
+    generate_protocol_delegate ctx full_class_name protocol all_functions output_cpp;
+    output_cpp ("id<" ^ protocol ^ "> " ^ full_class_name ^ "::_hx_toProtocol(::Dynamic inImplementation) {\n");
+    output_cpp ("\treturn [ [_hx_" ^ protocol ^ "_delegate alloc] initWithImplementation:inImplementation.mPtr];\n");
+    output_cpp "}\n\n");
+
+  cpp_file#close

+ 41 - 7
src/generators/cpp/gen/cppReferences.ml

@@ -1,4 +1,5 @@
 open Type
+open CppAst
 open CppStrings
 open CppTypeUtils
 open CppAstTools
@@ -9,7 +10,37 @@ open CppContext
    These are used for "#include"ing the appropriate header files,
    or for building the dependencies in the Build.xml file
 *)
-let find_referenced_types_flags ctx obj field_name super_deps constructor_deps header_only for_depends include_super_args =
+let find_referenced_types_flags ctx obj filter super_deps constructor_deps header_only for_depends include_super_args =
+  let all_virtual_functions clazz =
+    let current_virtual_functions_rev clazz base_functions =
+       let folder result elem =
+          match follow elem.cf_type, elem.cf_kind  with
+          | _, Method MethDynamic -> result
+          | TFun (args,return_type), Method _  ->
+              if (is_override elem ) then
+                if List.exists (fun (e,a,r) -> e.cf_name=elem.cf_name ) result then
+                   result
+                else
+                   (elem,args,return_type) :: result
+              else
+                 (elem,args,return_type) :: result
+          | _,_ -> result
+       in
+    
+       List.fold_left folder base_functions clazz.cl_ordered_fields
+    in
+ 
+    let rec all_virtual_functions_rec clazz =
+       let initial =
+          match clazz.cl_super with
+          | Some (def, _) -> all_virtual_functions_rec def
+          | _ -> [] in
+       current_virtual_functions_rev clazz initial
+    in
+ 
+    all_virtual_functions_rec clazz
+  in
+
   let types = ref PMap.empty in
   (if for_depends then
      let include_files =
@@ -22,7 +53,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
   let rec add_type_flag isNative in_path =
     if not (PMap.mem in_path !types) then (
       types := PMap.add in_path isNative !types;
-      try List.iter (add_type_flag isNative) (Hashtbl.find super_deps in_path)
+      try List.iter (add_type_flag isNative) (PathMap.find in_path super_deps)
       with Not_found -> ())
   and add_type in_path = add_type_flag false in_path in
   let add_extern_type decl =
@@ -113,7 +144,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
       | TNew (klass, params, _) -> (
           visit_type (TInst (klass, params));
           try
-            let construct_type = Hashtbl.find constructor_deps klass.cl_path in
+            let construct_type = PathMap.find klass.cl_path constructor_deps in
             visit_type construct_type.cf_type
           with Not_found -> ())
       (* Must visit type too, Type.iter will visit the expressions ... *)
@@ -133,7 +164,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
           | TInst (klass, params) -> (
               try
                 let construct_type =
-                  Hashtbl.find constructor_deps klass.cl_path
+                  PathMap.find klass.cl_path constructor_deps
                 in
                 visit_type construct_type.cf_type
               with Not_found -> ())
@@ -164,8 +195,11 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
         (match class_def.cl_constructor with Some expr -> [ expr ] | _ -> [])
     in
     let fields_and_constructor =
-      if field_name = "*" then fields_and_constructor
-      else List.filter (fun f -> f.cf_name = field_name) fields_and_constructor
+      match filter with
+      | Some field_name ->
+        List.filter (fun f -> f.cf_name = field_name) fields_and_constructor
+      | None ->
+        fields_and_constructor
     in
     List.iter visit_field fields_and_constructor;
     if include_super_args then
@@ -223,7 +257,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
 
 let find_referenced_types ctx obj super_deps constructor_deps header_only for_depends include_super_args =
   let deps, _ =
-    find_referenced_types_flags ctx obj "*" super_deps constructor_deps
+    find_referenced_types_flags ctx obj None super_deps constructor_deps
       header_only for_depends include_super_args
   in
   deps

+ 177 - 109
src/generators/gencpp.ml

@@ -17,6 +17,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *)
 open Ast
+open CppAst
 open Gctx
 open Type
 open Error
@@ -176,21 +177,65 @@ let write_build_options common_ctx filename defines =
    writer#close
 
 let create_member_types common_ctx =
-   let result = Hashtbl.create 0 in
-      List.iter (fun object_def ->
-         (match object_def with
-         | TClassDecl class_def when not (has_class_flag class_def CInterface) ->
-            let rec add_override to_super =
-               let class_name = (join_class_path to_super.cl_path ".") in
-               List.iter (fun member -> Hashtbl.add result (class_name ^ "." ^ member.cf_name) "virtual " ) class_def.cl_ordered_fields;
-               match to_super.cl_super with
-               | Some super -> add_override (fst super)
-               | _ -> ()
-             in
-             (match  class_def.cl_super with Some super -> add_override (fst super) | _->())
-         | _ -> ()
-         ) ) common_ctx.types;
-   result
+   let folder acc object_def =
+      match object_def with
+      | TClassDecl class_def when not (has_class_flag class_def CInterface) ->
+         let rec add_override acc to_super =
+            let class_name = (join_class_path to_super.cl_path ".") in
+            let folder acc member = StringMap.add (class_name ^ "." ^ member.cf_name) "virtual " acc in
+            let acc = List.fold_left folder acc class_def.cl_ordered_fields in
+            match to_super.cl_super with
+            | Some (super, _) -> add_override acc super
+            | _ -> acc
+         in
+         (match class_def.cl_super with Some (super, _) -> add_override acc super | _ -> acc)
+      | _ -> acc
+   in
+   List.fold_left folder StringMap.empty common_ctx.types
+
+(* Builds inheritance tree, so header files can include parents defs.  *)
+let create_super_dependencies common_ctx =
+   let real_non_native_interfaces =
+     List.filter (function t, pl ->
+      (match (t, pl) with
+      | { cl_path = [ "cpp"; "rtti" ], _ }, [] -> false
+      | _ -> not (is_native_gen_class t)))
+   in
+   let folder acc object_def =
+     match object_def with
+     | TClassDecl class_def when not (has_class_flag class_def CExtern) ->
+         let initial = match class_def.cl_super with
+         | Some (cls, _) when not (has_class_flag cls CExtern) ->
+            [ cls.cl_path ]
+         | _ ->
+            [] in
+
+         let deps =
+            class_def.cl_implements
+            |> real_non_native_interfaces
+            |> List.fold_left
+               (fun acc (cls, _) -> if has_class_flag cls CExtern then acc else cls.cl_path :: acc)
+               initial in
+
+         PathMap.add class_def.cl_path deps acc
+     | TEnumDecl enum_def when not (has_enum_flag enum_def EnExtern) ->
+         PathMap.add enum_def.e_path [] acc
+     | _ ->
+         acc
+   in
+   List.fold_left folder PathMap.empty common_ctx.types
+
+let create_constructor_dependencies common_ctx =
+   List.fold_left
+      (fun acc object_def ->
+         match object_def with
+         | TClassDecl class_def when not (has_class_flag class_def CExtern) ->
+            (match class_def.cl_constructor with
+            | Some func -> PathMap.add class_def.cl_path func acc
+            | None -> acc)
+         | _ -> acc)
+      PathMap.empty
+      common_ctx.types
 
 let is_assign_op op =
    match op with
@@ -198,107 +243,128 @@ let is_assign_op op =
    | OpAssignOp _ -> true
    | _ -> false
 
-let generate_class_files ctx class_def =
-   (* create header and cpp files *)
-   let nativeGen = Meta.has Meta.NativeGen class_def.cl_meta in
-   if not (nativeGen && (has_class_flag class_def CInterface)) then
-      CppGenClassImplementation.generate ctx class_def;
-   CppGenClassHeader.generate ctx class_def
-
 (*
  The common_ctx contains the haxe AST in the "types" field and the resources
 *)
+
+type gensrc_ctx = {
+   extern_src : string list;
+   build_xml : string;
+   boot_classes : path list;
+   init_classes : path list;
+   nonboot_classes : path list;
+   boot_enums : path list;
+   exe_classes : (path * path list * module_type) list;
+   decls : tcpp_decl list;
+   ids : CppAst.ObjectIds.t;
+   slots : CppAst.InterfaceSlots.t;
+}
+
 let generate_source ctx =
    let common_ctx = ctx.ctx_common in
-   let debug = ctx.ctx_debug_level in
    make_base_directory common_ctx.file;
-   let exe_classes = ref [] in
-   let boot_classes = ref [] in
-   let boot_enums = ref [] in
-   let nonboot_classes = ref [] in
-   let init_classes = ref [] in
-   let super_deps = CppGen.create_super_dependencies common_ctx in
-   let constructor_deps = CppGen.create_constructor_dependencies common_ctx in
    let main_deps = ref [] in
-   let extern_src = ref [] in
-   let jobs = ref [] in
-   let build_xml = ref "" in
    let scriptable = (Gctx.defined common_ctx Define.Scriptable) in
-   let existingIds = Hashtbl.create 0 in
 
-   List.iter (fun object_def ->
-      (* check if any @:objc class is referenced while '-D objc' is not defined
-         This will guard all code changes to this flag *)
-      (if not (Gctx.defined common_ctx Define.Objc) then match object_def with
+   let initial = {
+      extern_src = [];
+      build_xml = "";
+      boot_classes = [];
+      init_classes = [];
+      nonboot_classes = [];
+      boot_enums = [];
+      exe_classes = [];
+      decls = [];
+      ids = ObjectIds.empty;
+      slots = InterfaceSlots.empty;
+   } in
+
+   let folder acc cur =
+      (if not (Gctx.defined common_ctx Define.Objc) then
+         match cur with
          | TClassDecl class_def when Meta.has Meta.Objc class_def.cl_meta ->
             abort "In order to compile '@:objc' classes, please define '-D objc'" class_def.cl_pos
          | _ -> ());
-      (match object_def with
+
+      match cur with
       | TClassDecl class_def when is_extern_class class_def ->
-         build_xml := !build_xml ^ (CppGen.get_class_code class_def Meta.BuildXml);
-         let source = get_meta_string_path class_def.cl_meta Meta.SourceFile in
-         if (source<>"") then
-            extern_src := source :: !extern_src;
+         let acc_build_xml  = acc.build_xml ^ (CppGen.get_class_code class_def Meta.BuildXml) in
+         let acc_extern_src =
+            match Ast.get_meta_string class_def.cl_meta Meta.SourceFile with
+            | Some source -> make_path_absolute source class_def.cl_pos :: acc.extern_src
+            | None -> acc.extern_src in
+
+         { acc with build_xml = acc_build_xml; extern_src = acc_extern_src }
+
+      | TClassDecl class_def when is_internal_class class_def.cl_path || Meta.has Meta.Macro class_def.cl_meta ->
+         acc
+
       | TClassDecl class_def ->
-         let name =  class_text class_def.cl_path in
-         let is_internal = is_internal_class class_def.cl_path in
-         if (is_internal || (Meta.has Meta.Macro class_def.cl_meta)) then
-            ( if (debug>=4) then print_endline (" internal class " ^ name ))
-         else begin
-            let rec makeId class_name seed =
-               let id = gen_hash32 seed class_name in
-               (* reserve first 100 ids for runtime *)
-               if id < Int32.of_int 100 || Hashtbl.mem existingIds id then
-                  makeId class_name (seed+100)
-               else begin
-                  Hashtbl.add existingIds id true;
-                  Hashtbl.add ctx.ctx_type_ids class_name id;
-               end in
-            makeId name 0;
-
-            build_xml := !build_xml ^ (CppGen.get_class_code class_def Meta.BuildXml);
-            if (has_init_field class_def) then
-               init_classes := class_def.cl_path ::  !init_classes;
-            if (has_boot_field class_def) then
-               boot_classes := class_def.cl_path ::  !boot_classes
-            else if not (Meta.has Meta.NativeGen class_def.cl_meta) then
-               nonboot_classes := class_def.cl_path ::  !nonboot_classes;
-            jobs := (fun () -> generate_class_files ctx class_def) :: !jobs;
-            let deps = CppReferences.find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true scriptable in
-            if not ((has_class_flag class_def CInterface) && (is_native_gen_class class_def)) then
-               exe_classes := (class_def.cl_path, deps, object_def)  ::  !exe_classes;
-         end
-      | TEnumDecl enum_def when has_enum_flag enum_def EnExtern -> ()
-      | TEnumDecl enum_def ->
-         let name =  class_text enum_def.e_path in
-         let is_internal = is_internal_class enum_def.e_path in
-         if (is_internal) then
-            (if (debug>1) then print_endline (" internal enum " ^ name ))
-         else begin
-            let rec makeId enum_name seed =
-               let id = gen_hash32 seed enum_name in
-               (* reserve first 100 ids for runtime *)
-               if id < Int32.of_int 100 || Hashtbl.mem existingIds id then
-                  makeId enum_name (seed+100)
-               else begin
-                  Hashtbl.add existingIds id true;
-                  Hashtbl.add ctx.ctx_type_ids enum_name id;
-               end in
-            makeId name 0;
-
-            if (has_enum_flag enum_def EnExtern) then
-               (if (debug>1) then print_endline ("external enum " ^ name ));
-            boot_enums := enum_def.e_path :: !boot_enums;
-            jobs := (fun () -> CppGenEnum.generate ctx enum_def) :: !jobs;
-            let deps = CppReferences.find_referenced_types ctx (TEnumDecl enum_def) super_deps (Hashtbl.create 0) false true false in
-            exe_classes := (enum_def.e_path, deps, object_def) :: !exe_classes;
-         end
-      | TTypeDecl _ | TAbstractDecl _ -> (* already done *) ()
-      );
-   ) common_ctx.types;
-
-   List.iter (fun job -> job () ) !jobs;
+         let native_gen       = Meta.has Meta.NativeGen class_def.cl_meta in
+         let decl, slots, ids =
+            match has_class_flag class_def CInterface with
+            | true ->
+               let (slots, iface) = CppRetyper.tcpp_interface_from_tclass ctx acc.slots class_def in
+               if native_gen then (NativeInterface iface, slots, acc.ids) else (ManagedInterface iface, acc.slots, acc.ids)
+            | false ->
+               let (slots, ids, cls) = CppRetyper.tcpp_class_from_tclass ctx acc.ids acc.slots class_def [] in
+               if native_gen then (NativeClass cls, slots, ids) else (ManagedClass cls, slots, ids) in
+
+         let acc_decls           = decl :: acc.decls in
+         let acc_build_xml       = acc.build_xml ^ (CppGen.get_class_code class_def Meta.BuildXml) in
+         let acc_init_classes    = if has_init_field class_def then class_def.cl_path :: acc.init_classes else acc.init_classes in
+         let acc_boot_classes    = if has_boot_field class_def then class_def.cl_path :: acc.boot_classes else acc.boot_classes in
+         let acc_nonboot_classes = if Meta.has Meta.NativeGen class_def.cl_meta then acc.nonboot_classes else class_def.cl_path :: acc.nonboot_classes in
+         let acc_exe_classes     =
+            if (has_class_flag class_def CInterface) && (is_native_gen_class class_def) then
+               acc.exe_classes
+            else
+               let deps = CppReferences.find_referenced_types ctx (TClassDecl class_def) ctx.ctx_super_deps ctx.ctx_constructor_deps false true scriptable in
+
+               (class_def.cl_path, deps, cur) :: acc.exe_classes in
+
+         { acc with
+            build_xml = acc_build_xml;
+            decls = acc_decls;
+            init_classes = acc_init_classes;
+            boot_classes = acc_boot_classes;
+            nonboot_classes = acc_nonboot_classes;
+            exe_classes = acc_exe_classes;
+            ids = ids;
+            slots = slots
+         }
+
+      | TEnumDecl enum_def when is_extern_enum enum_def || is_internal_class enum_def.e_path ->
+         acc
 
+      | TEnumDecl enum_def ->
+         let deps             = CppReferences.find_referenced_types ctx (TEnumDecl enum_def) ctx.ctx_super_deps PathMap.empty false true false in
+         let ids, enum        = CppRetyper.tcpp_enum_from_tenum ctx acc.ids enum_def in
+         let acc_decls        = (Enum enum) :: acc.decls in
+         let acc_boot_enums   = enum_def.e_path :: acc.boot_enums in
+         let acc_exe_classes  = (enum_def.e_path, deps, cur) :: acc.exe_classes in
+         
+         { acc with decls = acc_decls; boot_enums = acc_boot_enums; exe_classes = acc_exe_classes; ids = ids }
+      | _ ->
+         acc
+   in
+   let srcctx = List.fold_left folder initial common_ctx.types in
+
+   List.iter (fun tcpp_type ->
+      match tcpp_type with
+      | ManagedClass tcpp_class ->
+         CppGenClassHeader.generate_managed_header ctx tcpp_class;
+         CppGenClassImplementation.generate_managed_class ctx tcpp_class;
+      | NativeClass tcpp_class ->
+         CppGenClassHeader.generate_native_header ctx tcpp_class;
+         CppGenClassImplementation.generate_native_class ctx tcpp_class;
+      | ManagedInterface interface_def ->
+         CppGenInterfaceHeader.generate_managed_interface ctx interface_def;
+         CppGenInterfaceImplementation.generate_managed_interface ctx interface_def;
+      | NativeInterface interface_def ->
+         CppGenInterfaceHeader.generate_native_interface ctx interface_def
+      | Enum tcpp_enum ->
+         CppGenEnum.generate ctx tcpp_enum) srcctx.decls;
 
    (match common_ctx.main.main_expr with
    | None -> CppGen.generate_dummy_main common_ctx
@@ -307,11 +373,11 @@ let generate_source ctx =
          cf_expr = Some e;
 	  } in
       let class_def = { null_class with cl_path = ([],"@Main"); cl_ordered_statics = [main_field] } in
-      main_deps := CppReferences.find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true false;
-      CppGen.generate_main ctx super_deps class_def
+      main_deps := CppReferences.find_referenced_types ctx (TClassDecl class_def) ctx.ctx_super_deps ctx.ctx_constructor_deps false true false;
+      CppGen.generate_main ctx ctx.ctx_super_deps class_def
    );
 
-   CppGen.generate_boot ctx !boot_enums !boot_classes !nonboot_classes !init_classes;
+   CppGen.generate_boot ctx srcctx.boot_enums srcctx.boot_classes srcctx.nonboot_classes srcctx.init_classes srcctx.slots;
 
    CppGen.generate_files common_ctx ctx.ctx_file_info;
 
@@ -351,7 +417,7 @@ let generate_source ctx =
             | TEnumDecl enum_def ->
                 out ("enum " ^ (spath name) ^ "\n");
             | _ -> ()
-            ) !exe_classes;
+            ) srcctx.exe_classes;
 
          (* Output file info too *)
          List.iter ( fun file ->
@@ -367,7 +433,7 @@ let generate_source ctx =
    | Some path -> (snd path)
    | _ -> "output" in
 
-   write_build_data common_ctx (common_ctx.file ^ "/Build.xml") !exe_classes !main_deps (!boot_enums@ !boot_classes) !build_xml !extern_src output_name;
+   write_build_data common_ctx (common_ctx.file ^ "/Build.xml") srcctx.exe_classes !main_deps (srcctx.boot_enums@ srcctx.boot_classes) srcctx.build_xml srcctx.extern_src output_name;
    write_build_options common_ctx (common_ctx.file ^ "/Options.txt") common_ctx.defines.Define.values;
    if ( not (Gctx.defined common_ctx Define.NoCompilation) ) then begin
       let t = Timer.timer ["generate";"cpp";"native compilation"] in
@@ -391,10 +457,12 @@ let generate_source ctx =
 
 let generate common_ctx =
    let debug_level = if (Gctx.defined common_ctx Define.NoDebug) then 0 else 1 in
+   let super_deps = create_super_dependencies common_ctx in
+   let constructor_deps = create_constructor_dependencies common_ctx in
    if (Gctx.defined common_ctx Define.Cppia) then begin
-      let ctx = new_context common_ctx debug_level (ref PMap.empty) (Hashtbl.create 0)  in
+      let ctx = new_context common_ctx debug_level (ref PMap.empty) StringMap.empty super_deps constructor_deps in
       CppCppia.generate_cppia ctx
-   end else begin
-      let ctx = new_context common_ctx debug_level (ref PMap.empty) (create_member_types common_ctx) in
+   end else begin   
+      let ctx = new_context common_ctx debug_level (ref PMap.empty) (create_member_types common_ctx) super_deps constructor_deps in
       generate_source ctx
    end

Some files were not shown because too many files changed in this diff