Sfoglia il codice sorgente

Merge branch 'development' of github.com:HaxeFoundation/haxe into development

杨博 11 anni fa
parent
commit
17a1f39cfa

+ 1 - 1
.travis.yml

@@ -25,7 +25,7 @@ env:
     - TEST=flash8
 
 matrix:
-  fast_finish: true
+  # fast_finish: true #https://github.com/travis-ci/travis-ci/issues/1696
   allow_failures:
     - env: TEST=flash8
 

+ 10 - 9
README.md

@@ -1,4 +1,5 @@
-![Haxe logo](http://haxe.org/img/haxe2/logo.png)
+![Haxe logo](http://haxe.org/img/haxe-logo-horizontal.svg)
+
 # [Haxe - The Cross-Platform Toolkit](http://haxe.org)
 
 [![Build Status](https://travis-ci.org/HaxeFoundation/haxe.png?branch=development)](https://travis-ci.org/HaxeFoundation/haxe)
@@ -31,7 +32,7 @@ The Haxe project has several licenses, covering different parts of the projects.
  * The Haxe libraries are released under a "two-clause" BSD license.
  * The Neko runtime is licensed under the GNU Lesser General Public License version 2.1 or any later version.
 
-For the complete Haxe licenses, please see http://haxe.org/doc/license or [extra/LICENSE.txt](extra/LICENSE.txt).
+For the complete Haxe licenses, please see http://haxe.org/foundation/open-source.html or [extra/LICENSE.txt](extra/LICENSE.txt).
 
 ## Installing Haxe
 
@@ -53,23 +54,23 @@ Automated development builds are available from [build.haxe.org](http://build.ha
         git clone --recursive git://github.com/HaxeFoundation/haxe.git
         cd haxe
 
- 2. Follow the [documentation on building Haxe for your platform](http://haxe.org/doc/build).
+ 2. Follow the [documentation on building Haxe for your platform](http://haxe.org/documentation/introduction/building-haxe.html).
 
 ## Using Haxe
 
-For information on on using Haxe, consult the [Haxe documentation](http://haxe.org/doc):
+For information on on using Haxe, consult the [Haxe documentation](http://haxe.org/documentation):
 
- * [Haxe introduction](http://haxe.org/doc/intro), an introduction to the Haxe toolkit
- * [Haxe language reference](http://haxe.org/ref), an overview of the Haxe programming language
- * [Haxe API](http://api.haxe.org/), a reference for the Haxe standard and native APIs
- * [Haxelib](http://lib.haxe.org/), a repository of Haxe libraries for a variety of needs
+ * [Haxe Introduction](http://haxe.org/documentation/introduction), an introduction to the Haxe toolkit
+ * [The Haxe Manual](http://haxe.org/manual), the reference manual for the Haxe language
+ * [Haxe API](http://api.haxe.org), documentation for the Haxe standard and native APIs
+ * [Haxelib](http://lib.haxe.org), a repository of Haxe libraries for a variety of needs
 
 ## Community
 
 You can get help and talk with fellow Haxers from around the world via:
 
  * the [official Haxe Google Group](https://groups.google.com/forum/#!forum/haxelang)
- * the [Haxe IRC chatroom](http://unic0rn.github.io/tiramisu/haxe/), #haxe on chat.freenode.net
+ * the [Haxe IRC chatroom](http://unic0rn.github.io/tiramisu/haxe), #haxe on chat.freenode.net
 
 ## Version compatibility
 

+ 4 - 1
codegen.ml

@@ -249,7 +249,10 @@ let rec generic_substitute_type gctx t =
 		(match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
 		t
 	| _ ->
-		try List.assq t gctx.subst with Not_found -> Type.map (generic_substitute_type gctx) t
+		try
+			generic_substitute_type gctx (List.assq t gctx.subst)
+		with Not_found ->
+			Type.map (generic_substitute_type gctx) t
 
 let generic_substitute_expr gctx e =
 	let vars = Hashtbl.create 0 in

+ 8 - 1
gencommon.ml

@@ -3987,6 +3987,8 @@ struct
 
 			(try
 				List.iter2 (fun a o ->
+					let o = run_follow gen o in
+					let a = run_follow gen a in
 					unify a o
 					(* type_eq EqStrict a o *)
 				) applied original
@@ -5959,6 +5961,7 @@ struct
 			match arglist, elist with
 			| [], [] -> true
 			| (_,_,t) :: arglist, et :: elist -> (try
+				let t = run_follow gen t in
 				unify et t;
 				check_arg arglist elist
 			with | Unify_error el ->
@@ -5972,7 +5975,11 @@ struct
 			let args, _ = get_fun t in
 			check_arg args etl
 		in
-		is_overload, List.find check_cf ctors, sup, ret_stl
+		match is_overload, ctors with
+			| false, [c] ->
+				false, c, sup, ret_stl
+			| _ ->
+				is_overload, List.find check_cf ctors, sup, ret_stl
 
 	(*
 

+ 280 - 154
gencpp.ml

@@ -65,7 +65,8 @@ let is_internal_class = function
    |  ([],"Array") | ([], "Class") | ([], "Enum") | ([], "Bool")
    |  ([], "Dynamic") | ([], "ArrayAccess") | (["cpp"], "FastIterator")
    |  (["cpp"],"Pointer") | (["cpp"],"ConstPointer")
-   |  (["cpp"],"BasePointer") | (["cpp"],"Function") -> true
+   |  (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer")
+   |  (["cpp"],"Function") -> true
    |  ([],"Math") | (["haxe";"io"], "Unsigned_char__") -> true
    |  (["cpp"],"Int8") | (["cpp"],"UInt8") | (["cpp"],"Char")
    |  (["cpp"],"Int16") | (["cpp"],"UInt16")
@@ -492,21 +493,23 @@ let is_lvalue var =
 
 
 
-let is_pointer haxe_type =
+let is_pointer haxe_type includeRaw =
    match follow haxe_type with
    | TInst (klass,params) ->
       (match klass.cl_path with
       | ["cpp"] , "Pointer"
       | ["cpp"] , "ConstPointer"
-      | ["cpp"] , "BasePointer"
       | ["cpp"] , "Function" -> true
+      | ["cpp"] , "RawPointer" when includeRaw -> true
+      | ["cpp"] , "RawConstPointer" when includeRaw -> true
       | _ -> false )
    | TType (type_def,params) ->
       (match type_def.t_path with
       | ["cpp"] , "Pointer"
       | ["cpp"] , "ConstPointer"
-      | ["cpp"] , "BasePointer"
       | ["cpp"] , "Function" -> true
+      | ["cpp"] , "RawPointer" when includeRaw -> true
+      | ["cpp"] , "RawConstPointer" when includeRaw -> true
       | _ -> false )
    | _ -> false
    ;;
@@ -530,9 +533,12 @@ let rec class_string klass suffix params =
    |  (["cpp"],"FastIterator") -> "::cpp::FastIterator" ^ suffix ^ "< " ^ (String.concat ","
                (List.map type_string  params) ) ^ " >"
    |  (["cpp"],"Pointer")
-   |  (["cpp"],"ConstPointer")
-   |  (["cpp"],"BasePointer") ->
+   |  (["cpp"],"ConstPointer") ->
         "::cpp::Pointer< " ^ (String.concat "," (List.map type_string params) ) ^ " >"
+   |  (["cpp"],"RawPointer") ->
+        " " ^ (String.concat "," (List.map type_string params) ) ^ " "
+   |  (["cpp"],"RawConstPointer") ->
+        " const " ^ (String.concat "," (List.map type_string params) ) ^ " * "
    |  (["cpp"],"Function") ->
         "::cpp::Function< " ^ (cpp_function_signature_params params) ^ " >"
    | _ when is_dynamic_type_param klass.cl_kind -> "Dynamic"
@@ -594,11 +600,18 @@ and type_string_suff suffix haxe_type =
          | [t] -> "::cpp::FastIterator< " ^ (type_string (follow t) ) ^ " >"
          | _ -> assert false)
       | ["cpp"] , "Pointer"
-      | ["cpp"] , "ConstPointer"
-      | ["cpp"] , "BasePointer" ->
+      | ["cpp"] , "ConstPointer" ->
          (match params with
          | [t] -> "::cpp::Pointer< " ^ (type_string (follow t) ) ^ " >"
          | _ -> assert false)
+      | ["cpp"] , "RawPointer" ->
+         (match params with
+         | [t] -> " " ^ (type_string (follow t) ) ^ " *"
+         | _ -> assert false)
+      | ["cpp"] , "RawConstPointer" ->
+         (match params with
+         | [t] -> "const " ^ (type_string (follow t) ) ^ " *"
+         | _ -> assert false)
       | ["cpp"] , "Function" -> "::cpp::Function< " ^ (cpp_function_signature_params params) ^ " >"
       | _ ->  type_string_suff suffix (apply_params type_def.t_types params type_def.t_type)
       )
@@ -632,6 +645,7 @@ and is_dynamic_array_param haxe_type =
    | TInst (klass,params) ->
          (match klass.cl_path with
          | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator")
+         | (["cpp"],"RawPointer") |(["cpp"],"ConstRawPointer")
          | (["cpp"],"Pointer") |(["cpp"],"ConstPointer")|(["cpp"],"Function") -> false
          | _ -> (match klass.cl_kind with KTypeParameter _ -> true | _ -> false)
          )
@@ -751,7 +765,10 @@ let is_internal_member member =
 
 
 let is_extern_class class_def =
-   class_def.cl_extern || (has_meta_key class_def.cl_meta Meta.Extern)
+   class_def.cl_extern || (has_meta_key class_def.cl_meta Meta.Extern) ||
+      (match class_def.cl_kind with
+       | KAbstractImpl abstract_def -> (has_meta_key abstract_def.a_meta Meta.Extern)
+       | _ -> false );
 ;;
 
 let is_extern_class_instance obj =
@@ -1198,7 +1215,7 @@ and is_dynamic_member_lookup_in_cpp ctx field_object field =
    let member = field_name field in
    ctx.ctx_dbgout ("/*mem."^member^".*/");
    if (is_internal_member member) then false else
-   if (is_pointer field_object.etype) then false else
+   if (is_pointer field_object.etype true) then false else
    if (match field_object.eexpr with | TTypeExpr _ -> ctx.ctx_dbgout "/*!TTypeExpr*/"; true | _ -> false) then false else
    if (is_dynamic_in_cpp ctx field_object) then true else
    if (is_array field_object.etype) then false else (
@@ -1219,7 +1236,7 @@ and is_dynamic_member_lookup_in_cpp ctx field_object field =
 and is_dynamic_member_return_in_cpp ctx field_object field =
    let member = field_name field in
    if (is_array field_object.etype) then false else
-   if (is_pointer field_object.etype) then false else
+   if (is_pointer field_object.etype true) then false else
    if (is_internal_member member) then false else
    match field_object.eexpr with
    | TTypeExpr t ->
@@ -1932,7 +1949,7 @@ and gen_expression ctx retval expression =
          when class_def.cl_extern ->
          (try
             let return_type = expression.etype in
-            is_pointer return_type &&
+            (is_pointer return_type false) &&
                ( output ( (type_string return_type) ^ "(" ); true; )
          with Not_found -> false )
       | _ -> false
@@ -2078,7 +2095,7 @@ and gen_expression ctx retval expression =
          output "->__get(";
          gen_expression ctx true index;
          output ")";
-         if not (is_pointer array_expr.etype ) then
+         if not (is_pointer array_expr.etype true) then
             check_array_element_cast array_expr.etype ".StaticCast" "()";
       end
    (* Get precidence matching haxe ? *)
@@ -2552,6 +2569,16 @@ let gen_field_init ctx field =
 
 
 
+let has_field_init field =
+   match field.cf_expr with
+   (* Function field *)
+   | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field
+   (* Data field *)
+   | Some _ -> true
+   | _ -> false
+;;
+
+
 let gen_member_def ctx class_def is_static is_interface field =
    let output = ctx.ctx_output in
    let remap_name = keyword_remap field.cf_name in
@@ -2662,7 +2689,9 @@ let find_referenced_types ctx obj super_deps constructor_deps header_only for_de
          for the Array, Class, FastIterator or Pointer classes, for which we do a fully typed object *)
       | TInst (klass,params) ->
          (match klass.cl_path with
-         | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator") | (["cpp"],"Pointer") | (["cpp"],"ConstPointer") | (["cpp"],"Function") -> List.iter visit_type params
+         | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator")
+         | (["cpp"],"Pointer") | (["cpp"],"ConstPointer") | (["cpp"],"Function")
+         | (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer") -> List.iter visit_type params
          | _ when is_extern_class klass -> add_extern_class klass
          | _ -> (match klass.cl_kind with KTypeParameter _ -> () | _ -> add_type klass.cl_path);
          )
@@ -2813,20 +2842,21 @@ let generate_dummy_main common_ctx =
    generate_startup "__lib__" false
    ;;
 
-let generate_boot common_ctx boot_classes init_classes =
+let generate_boot common_ctx boot_classes nonboot_classes init_classes =
    (* Write boot class too ... *)
    let base_dir = common_ctx.file in
    let boot_file = new_cpp_file common_ctx base_dir ([],"__boot__") in
    let output_boot = (boot_file#write) in
    output_boot "#include <hxcpp.h>\n\n";
-   List.iter ( fun class_path -> boot_file#add_include class_path ) boot_classes;
+   List.iter ( fun class_path -> boot_file#add_include class_path ) (boot_classes @ nonboot_classes);
 
    output_boot "\nvoid __files__boot();\n";
    output_boot "\nvoid __boot_all()\n{\n";
    output_boot "__files__boot();\n";
    output_boot "hx::RegisterResources( hx::GetResources() );\n";
    List.iter ( fun class_path ->
-      output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__register();\n") ) boot_classes;
+      output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__register();\n") )
+         (boot_classes @ nonboot_classes);
    List.iter ( fun class_path ->
       output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__init__();\n") ) (List.rev init_classes);
    let dump_boot =
@@ -3161,6 +3191,78 @@ let has_init_field class_def =
    | Some _ -> true
    | _ -> false;;
 
+
+let is_abstract_impl class_def = match class_def.cl_kind with
+   | KAbstractImpl _ -> true
+   | _ -> false
+;;
+
+let variable_field field =
+   (match field.cf_expr with
+   | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field
+   | _ -> true)
+;;
+
+let is_readable class_def field =
+   (match field.cf_kind with
+   | Var { v_read = AccNever } when (is_extern_field field) -> false
+   | Var { v_read = AccInline } -> false
+   | Var _ when is_abstract_impl class_def -> false
+   | _ -> true)
+;;
+
+let is_writable class_def field =
+   (match field.cf_kind with
+   | Var { v_write = AccNever } when (is_extern_field field) -> false
+   | Var { v_read = AccInline } -> false
+   | Var _ when is_abstract_impl class_def -> false
+   | _ -> true)
+;;
+
+let reflective class_def field = not (
+    (Meta.has Meta.Unreflective class_def.cl_meta) ||
+    (Meta.has Meta.Unreflective field.cf_meta) ||
+    (match field.cf_type with
+       | TInst (klass,_) ->  Meta.has Meta.Unreflective klass.cl_meta
+       | _ -> false
+    )
+)
+;;
+ 
+let statics_except_meta class_def = (List.filter (fun static -> static.cf_name <> "__meta__") class_def.cl_ordered_statics);;
+
+let has_set_field class_def =
+   implement_dynamic_here class_def || (
+      let reflect_fields = List.filter (reflective class_def) ((statics_except_meta class_def) @ class_def.cl_ordered_fields) in
+      let reflect_writable = List.filter (is_writable class_def) reflect_fields in
+      List.exists variable_field reflect_writable
+   )
+;;
+
+let has_get_fields class_def =
+   implement_dynamic_here class_def || (
+      let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in
+      List.exists is_data_field class_def.cl_ordered_fields
+   )
+;;
+
+let has_get_field class_def =
+   implement_dynamic_here class_def || (
+      let reflect_fields = List.filter (reflective class_def) ((statics_except_meta class_def) @ class_def.cl_ordered_fields) in
+      List.exists (is_readable class_def) reflect_fields
+   )
+;;
+
+
+
+
+
+
+let has_boot_field class_def =
+   List.exists has_field_init (List.filter should_implement_field class_def.cl_ordered_statics);
+;;
+
+
 let is_macro meta =
    Meta.has Meta.Macro meta
 ;;
@@ -3179,7 +3281,6 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
    let class_path = class_def.cl_path in
    let class_name = (snd class_path) ^ "_obj" in
    let dot_name = join_class_path class_path "." in
-   let is_abstract_impl = match class_def.cl_kind with | KAbstractImpl _ -> true | _ -> false in
    let smart_class_name =  (snd class_path)  in
    (*let cpp_file = new_cpp_file common_ctx.file class_path in*)
    let cpp_file = new_placed_cpp_file common_ctx class_path in
@@ -3220,8 +3321,9 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 
    output_cpp "#include <hxcpp.h>\n\n";
 
-   let field_integer_dynamic = scriptable || (has_field_integer_lookup class_def) in
-   let field_integer_numeric = scriptable || (has_field_integer_numeric_lookup class_def) in
+   let force_field = scriptable && (has_get_field class_def) in
+   let field_integer_dynamic = force_field || (has_field_integer_lookup class_def) in
+   let field_integer_numeric = force_field || (has_field_integer_numeric_lookup class_def) in
 
    let all_referenced = find_referenced_types ctx.ctx_common (TClassDecl class_def) super_deps constructor_deps false false scriptable in
    List.iter ( add_include cpp_file  ) all_referenced;
@@ -3316,7 +3418,7 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
       output_cpp "}\n\n";
    | _ -> ());
 
-   let statics_except_meta = (List.filter (fun static -> static.cf_name <> "__meta__") class_def.cl_ordered_statics) in
+   let statics_except_meta = statics_except_meta class_def in
    let implemented_fields = List.filter should_implement_field statics_except_meta in
    let dump_field_name = (fun field -> output_cpp ("\t" ^  (str field.cf_name) ^ ",\n")) in
    let implemented_instance_fields = List.filter should_implement_field class_def.cl_ordered_fields in
@@ -3389,33 +3491,9 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 
 
 
-      let variable_field field =
-         (match field.cf_expr with
-         | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field
-         | _ -> true)
-      in
-      let is_readable field =
-         (match field.cf_kind with
-         | Var { v_read = AccNever } when (is_extern_field field) -> false
-         | Var { v_read = AccInline } -> false
-         | Var _ when is_abstract_impl -> false
-         | _ -> true) in
-      let is_writable field =
-         (match field.cf_kind with
-         | Var { v_write = AccNever } when (is_extern_field field) -> false
-         | Var { v_read = AccInline } -> false
-         | Var _ when is_abstract_impl -> false
-         | _ -> true) in
-
-      let reflective field = not ( (Meta.has Meta.Unreflective field.cf_meta) ||
-          (match field.cf_type with
-          | TInst (klass,_) ->  Meta.has Meta.Unreflective klass.cl_meta
-          | _ -> false
-          )
-      ) in
-      let reflect_fields = List.filter reflective (statics_except_meta @ class_def.cl_ordered_fields) in
-      let reflect_writable = List.filter is_writable reflect_fields in
-      let reflect_readable = List.filter is_readable reflect_fields in
+      let reflect_fields = List.filter (reflective class_def) (statics_except_meta @ class_def.cl_ordered_fields) in
+      let reflect_writable = List.filter (is_writable class_def) reflect_fields in
+      let reflect_readable = List.filter (is_readable class_def) reflect_fields in
       let reflect_write_variables = List.filter variable_field reflect_writable in
 
       let dump_quick_field_test fields =
@@ -3436,97 +3514,99 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
          end;
       in
 
-
-      (* Dynamic "Get" Field function - string version *)
-      output_cpp ("Dynamic " ^ class_name ^ "::__Field(const ::String &inName,bool inCallProp)\n{\n");
-      let get_field_dat = List.map (fun f ->
-         (f.cf_name, String.length f.cf_name, "return " ^
-            (match f.cf_kind with
-            | Var { v_read = AccCall } when is_extern_field f -> (keyword_remap ("get_" ^ f.cf_name)) ^ "()"
-            | Var { v_read = AccCall } -> "inCallProp ? " ^ (keyword_remap ("get_" ^ f.cf_name)) ^ "() : " ^
-                  ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()")
-            | _ -> ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()")
-            ) ^ ";"
-         ) )
-      in
-      dump_quick_field_test (get_field_dat reflect_readable);
-      if (implement_dynamic) then
-         output_cpp "\tHX_CHECK_DYNAMIC_GET_FIELD(inName);\n";
-      output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n");
-
-      (* Dynamic "Get" Field function - int version *)
-      if ( field_integer_numeric || field_integer_dynamic) then begin
-         let dump_static_ids = (fun field ->
-            let remap_name = keyword_remap field.cf_name in
-            output_cpp ("static int __id_" ^ remap_name ^ " = __hxcpp_field_to_id(\"" ^
-                           (field.cf_name) ^ "\");\n");
-            ) in
-         List.iter dump_static_ids reflect_readable;
-         output_cpp "\n\n";
-
-
-         let output_ifield return_type function_name all_fields =
-         output_cpp (return_type ^" " ^ class_name ^ "::" ^ function_name ^ "(int inFieldID)\n{\n");
-         let dump_field_test = (fun f ->
-            let remap_name = keyword_remap f.cf_name in
-            output_cpp ("\tif (inFieldID==__id_" ^ remap_name ^ ") return "  ^
-               ( if (return_type="Float") then "hx::ToDouble( " else "" ) ^
+   
+      if (has_get_field class_def) then begin
+         (* Dynamic "Get" Field function - string version *)
+         output_cpp ("Dynamic " ^ class_name ^ "::__Field(const ::String &inName,bool inCallProp)\n{\n");
+         let get_field_dat = List.map (fun f ->
+            (f.cf_name, String.length f.cf_name, "return " ^
                (match f.cf_kind with
-               | Var { v_read = AccCall } -> (keyword_remap ("get_" ^ f.cf_name)) ^ "()"
-               | _ -> (remap_name ^ if ( variable_field f) then "" else "_dyn()")
-               ) ^ ( if (return_type="Float") then " ) " else "" ) ^ ";\n");
-            ) in
-         List.iter dump_field_test (List.filter (fun f -> all_fields || (is_numeric_field f)) reflect_readable);
-         if (implement_dynamic) then
-            output_cpp "\tHX_CHECK_DYNAMIC_GET_INT_FIELD(inFieldID);\n";
-         output_cpp ("\treturn super::" ^ function_name ^ "(inFieldID);\n}\n\n");
+               | Var { v_read = AccCall } when is_extern_field f -> (keyword_remap ("get_" ^ f.cf_name)) ^ "()"
+               | Var { v_read = AccCall } -> "inCallProp ? " ^ (keyword_remap ("get_" ^ f.cf_name)) ^ "() : " ^
+                     ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()")
+               | _ -> ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()")
+               ) ^ ";"
+            ) )
          in
-
-         if (field_integer_dynamic) then output_ifield "Dynamic" "__IField" true;
-         if (field_integer_numeric) then output_ifield "double" "__INumField" false;
+         dump_quick_field_test (get_field_dat reflect_readable);
+         if (implement_dynamic) then
+            output_cpp "\tHX_CHECK_DYNAMIC_GET_FIELD(inName);\n";
+         output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n");
+   
+         (* Dynamic "Get" Field function - int version *)
+         if ( field_integer_numeric || field_integer_dynamic) then begin
+            let dump_static_ids = (fun field ->
+               let remap_name = keyword_remap field.cf_name in
+               output_cpp ("static int __id_" ^ remap_name ^ " = __hxcpp_field_to_id(\"" ^
+                              (field.cf_name) ^ "\");\n");
+               ) in
+            List.iter dump_static_ids reflect_readable;
+            output_cpp "\n\n";
+   
+   
+            let output_ifield return_type function_name all_fields =
+            output_cpp (return_type ^" " ^ class_name ^ "::" ^ function_name ^ "(int inFieldID)\n{\n");
+            let dump_field_test = (fun f ->
+               let remap_name = keyword_remap f.cf_name in
+               output_cpp ("\tif (inFieldID==__id_" ^ remap_name ^ ") return "  ^
+                  ( if (return_type="Float") then "hx::ToDouble( " else "" ) ^
+                  (match f.cf_kind with
+                  | Var { v_read = AccCall } -> (keyword_remap ("get_" ^ f.cf_name)) ^ "()"
+                  | _ -> (remap_name ^ if ( variable_field f) then "" else "_dyn()")
+                  ) ^ ( if (return_type="Float") then " ) " else "" ) ^ ";\n");
+               ) in
+            List.iter dump_field_test (List.filter (fun f -> all_fields || (is_numeric_field f)) reflect_readable);
+            if (implement_dynamic) then
+               output_cpp "\tHX_CHECK_DYNAMIC_GET_INT_FIELD(inFieldID);\n";
+            output_cpp ("\treturn super::" ^ function_name ^ "(inFieldID);\n}\n\n");
+            in
+   
+            if (field_integer_dynamic) then output_ifield "Dynamic" "__IField" true;
+            if (field_integer_numeric) then output_ifield "double" "__INumField" false;
+         end;
       end;
 
 
       (* Dynamic "Set" Field function *)
-      output_cpp ("Dynamic " ^ class_name ^ "::__SetField(const ::String &inName,const Dynamic &inValue,bool inCallProp)\n{\n");
-
-      let set_field_dat = List.map (fun f ->
-         let default_action =
-            (keyword_remap f.cf_name) ^ "=inValue.Cast< " ^ (type_string f.cf_type) ^ " >();" ^
-               " return inValue;" in
-         (f.cf_name, String.length f.cf_name,
-            (match f.cf_kind with
-            | Var { v_write = AccCall } when is_extern_field f -> "return " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(inValue);"
-            | Var { v_write = AccCall } -> "if (inCallProp) return " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(inValue);"
-               ^ default_action
-            | _ -> default_action
+      if (has_set_field class_def) then begin
+         output_cpp ("Dynamic " ^ class_name ^ "::__SetField(const ::String &inName,const Dynamic &inValue,bool inCallProp)\n{\n");
+   
+         let set_field_dat = List.map (fun f ->
+            let default_action =
+               (keyword_remap f.cf_name) ^ "=inValue.Cast< " ^ (type_string f.cf_type) ^ " >();" ^
+                  " return inValue;" in
+            (f.cf_name, String.length f.cf_name,
+               (match f.cf_kind with
+               | Var { v_write = AccCall } when is_extern_field f -> "return " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(inValue);"
+               | Var { v_write = AccCall } -> "if (inCallProp) return " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(inValue);"
+                  ^ default_action
+               | _ -> default_action
+               )
             )
-         )
-      ) in
-
-      dump_quick_field_test (set_field_dat reflect_write_variables);
-      if (implement_dynamic) then begin
-         output_cpp ("\ttry { return super::__SetField(inName,inValue,inCallProp); }\n");
-         output_cpp ("\tcatch(Dynamic e) { HX_DYNAMIC_SET_FIELD(inName,inValue); }\n");
-         output_cpp "\treturn inValue;\n}\n\n";
-      end else
-         output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n");
+         ) in
+   
+         dump_quick_field_test (set_field_dat reflect_write_variables);
+         if (implement_dynamic) then begin
+            output_cpp ("\ttry { return super::__SetField(inName,inValue,inCallProp); }\n");
+            output_cpp ("\tcatch(Dynamic e) { HX_DYNAMIC_SET_FIELD(inName,inValue); }\n");
+            output_cpp "\treturn inValue;\n}\n\n";
+         end else
+            output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n");
+      end;
 
       (* For getting a list of data members (eg, for serialization) *)
-      let append_field =
-         (fun field -> output_cpp ("\toutFields->push(" ^( str field.cf_name )^ ");\n")) in
-      let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in
-
-      output_cpp ("void " ^ class_name ^ "::__GetFields(Array< ::String> &outFields)\n{\n");
-      List.iter append_field (List.filter is_data_field class_def.cl_ordered_fields);
-      if (implement_dynamic) then
-         output_cpp "\tHX_APPEND_DYNAMIC_FIELDS(outFields);\n";
-      output_cpp "\tsuper::__GetFields(outFields);\n";
-      output_cpp "};\n\n";
-
-      output_cpp "static ::String sStaticFields[] = {\n";
-      List.iter dump_field_name  implemented_fields;
-      output_cpp "\tString(null()) };\n\n";
+      if (has_get_fields class_def) then begin
+         let append_field =
+            (fun field -> output_cpp ("\toutFields->push(" ^( str field.cf_name )^ ");\n")) in
+         let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in
+   
+         output_cpp ("void " ^ class_name ^ "::__GetFields(Array< ::String> &outFields)\n{\n");
+         List.iter append_field (List.filter is_data_field class_def.cl_ordered_fields);
+         if (implement_dynamic) then
+            output_cpp "\tHX_APPEND_DYNAMIC_FIELDS(outFields);\n";
+         output_cpp "\tsuper::__GetFields(outFields);\n";
+         output_cpp "};\n\n";
+      end;
 
       let dump_member_storage = (fun field ->
          let storage = match type_string field.cf_type with
@@ -3551,9 +3631,15 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
       output_cpp "#endif\n\n";
    end; (* cl_interface *)
 
-   output_cpp "static ::String sMemberFields[] = {\n";
-   List.iter dump_field_name  implemented_instance_fields;
-   output_cpp "\tString(null()) };\n\n";
+   let reflective_members = List.filter (reflective class_def) implemented_instance_fields in
+   let sMemberFields = if List.length reflective_members>0 then begin
+      output_cpp "static ::String sMemberFields[] = {\n";
+      List.iter dump_field_name  reflective_members;
+      output_cpp "\tString(null()) };\n\n";
+      "sMemberFields"
+   end else
+      "0 /* sMemberFields */";
+   in
 
    (* Mark static variables as used *)
    output_cpp "static void sMarkStatics(HX_MARK_PARAMS) {\n";
@@ -3713,9 +3799,19 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
          );
       end;
 
+      let reflective_statics = List.filter (reflective class_def) implemented_fields in
+      let sStaticFields = if List.length reflective_statics > 0 then begin
+         output_cpp "static ::String sStaticFields[] = {\n";
+         List.iter dump_field_name  reflective_statics;
+         output_cpp "\tString(null()) };\n\n";
+         "sStaticFields";
+      end else
+        "0 /* sStaticFields */"
+      in
+
       output_cpp ("void " ^ class_name ^ "::__register()\n{\n");
       output_cpp ("\thx::Static(__mClass) = hx::RegisterClass(" ^ (str class_name_text)  ^
-            ", hx::TCanCast< " ^ class_name ^ "> ,sStaticFields,sMemberFields,\n");
+            ", hx::TCanCast< " ^ class_name ^ "> ," ^ sStaticFields ^ "," ^ sMemberFields ^ ",\n");
       output_cpp ("\t&__CreateEmpty, &__Create,\n");
       output_cpp ("\t&super::__SGetClass(), 0, sMarkStatics\n");
       output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n    , sVisitStatics\n#endif\n");
@@ -3732,7 +3828,7 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 
       output_cpp ("void " ^ class_name ^ "::__register()\n{\n");
       output_cpp ("\thx::Static(__mClass) = hx::RegisterClass(" ^ (str class_name_text)  ^
-            ", hx::TCanCast< " ^ class_name ^ "> ,0,sMemberFields,\n");
+            ", hx::TCanCast< " ^ class_name ^ "> ,0," ^ sMemberFields ^ ",\n");
       output_cpp ("\t0, 0,\n");
       output_cpp ("\t&super::__SGetClass(), 0, sMarkStatics\n");
       output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n    , sVisitStatics\n#endif\n");
@@ -3743,9 +3839,11 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
       output_cpp ("}\n\n");
    end;
 
-   output_cpp ("void " ^ class_name ^ "::__boot()\n{\n");
-   List.iter (gen_field_init ctx ) (List.filter should_implement_field class_def.cl_ordered_statics);
-   output_cpp ("}\n\n");
+   if (has_boot_field class_def) then begin
+      output_cpp ("void " ^ class_name ^ "::__boot()\n{\n");
+      List.iter (gen_field_init ctx ) (List.filter should_implement_field class_def.cl_ordered_statics);
+      output_cpp ("}\n\n");
+   end;
 
 
    gen_close_namespace output_cpp class_path;
@@ -3807,12 +3905,18 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
       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;\n");
+      output_h ("\t\tHX_DO_RTTI_ALL;\n");
+      if (has_get_field class_def) then
+         output_h ("Dynamic __Field(const ::String &inString, bool inCallProp);\n");
+      if (has_set_field class_def) then
+         output_h ("Dynamic __SetField(const ::String &inString,const Dynamic &inValue, bool inCallProp);\n");
+      if (has_get_fields class_def) then
+         output_h ("void __GetFields(Array< ::String> &outFields);\n");
+      
       if (field_integer_dynamic) then output_h "\t\tDynamic __IField(int inFieldID);\n";
       if (field_integer_numeric) then output_h "\t\tdouble __INumField(int inFieldID);\n";
       if (implement_dynamic) then
          output_h ("\t\tHX_DECLARE_IMPLEMENT_DYNAMIC;\n");
-      output_h ("\t\tstatic void __boot();\n");
       output_h ("\t\tstatic void __register();\n");
       if (override_iteration) then begin
          output_h ("\t\tvoid __Mark(HX_MARK_PARAMS);\n");
@@ -3832,8 +3936,9 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
       output_h ("\t\t::String __ToString() const { return " ^ (str smart_class_name) ^ "; }\n\n");
    end else begin
       output_h ("\t\tHX_DO_INTERFACE_RTTI;\n");
-      output_h ("\t\tstatic void __boot();\n");
    end;
+   if (has_boot_field class_def) then
+      output_h ("\t\tstatic void __boot();\n");
 
 
    (match class_def.cl_array_access with
@@ -4175,7 +4280,8 @@ let gen_extern_enum common_ctx enum_def file_info =
    output ( "@:include extern " ^ (if enum_def.e_private then "private " else "")
             ^ " enum " ^ (snd path) ^ (params enum_def.e_types) );
    output " {\n";
-   PMap.iter (fun _ constructor ->
+   let sorted_items = List.sort (fun f1 f2 -> (f1.ef_index - f2.ef_index ) ) (pmap_values enum_def.e_constrs) in
+   List.iter (fun constructor ->
       let name = keyword_remap constructor.ef_name in
       match constructor.ef_type with
       | TFun (args,_) ->
@@ -4183,7 +4289,7 @@ let gen_extern_enum common_ctx enum_def file_info =
          output ( String.concat "," (List.map (fun (arg,_,t) -> arg ^ ":" ^ (s_type t) ) args) );
          output ");\n\n";
       | _ -> output ( name ^ ";\n\n" )
-   ) enum_def.e_constrs;
+   ) sorted_items;
 
    output "}\n";
    file#close
@@ -4239,8 +4345,8 @@ let rec script_type_string haxe_type =
          )
       | TAbstract (abs,pl) when abs.a_impl <> None ->
          script_type_string  (Codegen.Abstract.get_underlying_type abs pl);
-      | t ->
-         type_string_suff "" t
+      | _ ->
+         type_string_suff "" haxe_type
 ;;
 
 type array_of =
@@ -4294,6 +4400,7 @@ class script_writer common_ctx ctx filename =
    method writeBool value = this#write (if value then "1 " else "0 ")
    method staticText value = if value then "s" else "m"
    method write str = Buffer.add_string buffer str ; just_finished_block <- false
+   method writeData str = Buffer.add_string buffer str;
    method wint ival = this#write ((string_of_int ival)^" ")
    method ident name = this#wint (this#stringId name)
    method instText clazz = match clazz.cl_path with
@@ -4356,8 +4463,9 @@ class script_writer common_ctx ctx filename =
          | Some ({ eexpr = TFunction function_def } as e) -> this#gen_expression e
          | _ -> print_endline ("Missing function body for " ^ funcName );
       end
-   method var readAcc writeAcc isStatic name varType varExpr =
-      this#write ("VAR " ^ (this#staticText isStatic) ^ " " ^ readAcc ^ " " ^ writeAcc ^ " " ^ (this#stringText name)^ (this#typeText varType) ^
+   method var readAcc writeAcc isExtern isStatic name varType varExpr =
+      this#write ("VAR " ^ (this#staticText isStatic) ^ " " ^ readAcc ^ " " ^ writeAcc ^ " " ^
+         (this#boolText isExtern) ^ " " ^ (this#stringText name)^ (this#typeText varType) ^
          (match varExpr with Some _ -> "1\n" | _ -> "0\n" ) );
       match varExpr with
       | Some expression -> this#gen_expression expression
@@ -4439,7 +4547,7 @@ class script_writer common_ctx ctx filename =
             this#write (indent ^ indent_str );
             this#writeVar arg;
             match init with
-            | Some const -> this#write ("1 " ^ (this#constText const) ^ "\n")
+            | Some const when const <> TNull -> this#write ("1 " ^ (this#constText const) ^ "\n")
             | _ -> this#write "0\n";
          ) function_def.tf_args;
          this#gen_expression function_def.tf_expr;
@@ -4595,9 +4703,12 @@ class script_writer common_ctx ctx filename =
          this#write "\n";
          this#gen_expression init;
          this#gen_expression loop;
-   | TEnumParameter (expr,_,i) ->
-         let enum = match follow expr.etype with TEnum(enum,_) -> expr.etype | _ -> assert false in
-         this#write ("ENUMI " ^ (this#typeText enum) ^ (string_of_int i) ^ "\n");
+   | TEnumParameter (expr,ef,i) ->
+         let enum = match follow ef.ef_type with
+            | TEnum(en,_) | TFun(_,TEnum(en,_)) -> en
+            | _ -> assert false
+         in
+         this#write ("ENUMI " ^ (this#typeText (TEnum(enum,[])) ) ^ (string_of_int i) ^ "\n");
          this#gen_expression expr;
    | TSwitch (condition,cases,optional_default)  ->
          this#write ("SWITCH " ^ (string_of_int (List.length cases)) ^ " " ^
@@ -4668,7 +4779,8 @@ let generate_script_class common_ctx script class_def =
          | AccInline -> "N"
          | AccRequire (_,_) -> "?"
          in
-         script#var (mode_code v.v_read) (mode_code v.v_write) isStatic field.cf_name t field.cf_expr
+         let isExtern = is_extern_field field in
+         script#var (mode_code v.v_read) (mode_code v.v_write) isExtern isStatic field.cf_name t field.cf_expr
       | Method MethDynamic, TFun(args,ret) ->
          script#func isStatic true field.cf_name ret args class_def.cl_interface field.cf_expr
       | Method _, TFun(args,ret) when field.cf_name="new" ->
@@ -4705,6 +4817,10 @@ let generate_script_enum common_ctx script enum_def meta =
       | _ -> script#write ( name ^ " 0\n" )
    ) sorted_items;
 
+   match meta with
+   | Some expr -> script#write "1\n";
+      script#gen_expression expr
+   | _ -> script#write "0\n";
    script#write "\n"
 ;;
 
@@ -4753,6 +4869,12 @@ let generate_cppia common_ctx =
          script#gen_expression e
    );
 
+   script#write ("RESOURCES " ^ (string_of_int (Hashtbl.length common_ctx.resources)) ^ "\n");
+   Hashtbl.iter (fun name data -> 
+      script#write ("RESO " ^ (script#stringText name) ^  (string_of_int (String.length data)) ^ "\n");
+   ) common_ctx.resources;
+   Hashtbl.iter (fun _ data -> script#writeData data) common_ctx.resources;
+
    script#close
 ;;
 
@@ -4766,6 +4888,7 @@ let generate_source common_ctx =
    let debug = 1 in
    let exe_classes = ref [] in
    let boot_classes = ref [] in
+   let nonboot_classes = ref [] in
    let init_classes = ref [] in
    let file_info = ref PMap.empty in
    let class_text path = join_class_path path "::" in
@@ -4793,9 +4916,12 @@ let generate_source common_ctx =
             ( if (debug>1) then print_endline (" internal class " ^ name ))
          else begin
             build_xml := !build_xml ^ (get_code class_def.cl_meta Meta.BuildXml);
-            boot_classes := class_def.cl_path ::  !boot_classes;
             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
+               nonboot_classes := class_def.cl_path ::  !nonboot_classes;
             let deps = generate_class_files common_ctx
                member_types super_deps constructor_deps class_def file_info scriptable in
             exe_classes := (class_def.cl_path, deps)  ::  !exe_classes;
@@ -4829,7 +4955,7 @@ let generate_source common_ctx =
       generate_main common_ctx member_types super_deps class_def file_info
    );
 
-   generate_boot common_ctx !boot_classes !init_classes;
+   generate_boot common_ctx !boot_classes !nonboot_classes !init_classes;
 
    generate_files common_ctx file_info;
 

+ 13 - 13
genjava.ml

@@ -2135,20 +2135,20 @@ let configure gen =
 	mkdir (gen.gcon.file ^ "/src");
 
 	(* add resources array *)
+	let res = ref [] in
+	Hashtbl.iter (fun name v ->
+		res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = Ast.null_pos } :: !res;
+
+		let full_path = gen.gcon.file ^ "/src/" ^ name in
+		mkdir_from_path full_path;
+
+		let f = open_out_bin full_path in
+		output_string f v;
+		close_out f
+	) gen.gcon.resources;
 	(try
-		let res = get_cl (Hashtbl.find gen.gtypes (["haxe"], "Resource")) in
-		let cf = PMap.find "content" res.cl_statics in
-		let res = ref [] in
-		Hashtbl.iter (fun name v ->
-			res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = Ast.null_pos } :: !res;
-
-			let full_path = gen.gcon.file ^ "/src/" ^ name in
-			mkdir_from_path full_path;
-
-			let f = open_out full_path in
-			output_string f v;
-			close_out f
-		) gen.gcon.resources;
+		let c = get_cl (Hashtbl.find gen.gtypes (["haxe"], "Resource")) in
+		let cf = PMap.find "content" c.cl_statics in
 		cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = Ast.null_pos })
 	with | Not_found -> ());
 

+ 10 - 12
genpy.ml

@@ -1337,6 +1337,11 @@ module Printer = struct
 		let do_default () =
 			Printf.sprintf "%s.%s" obj (if is_extern then name else (handle_keywords name))
 		in
+		let call_override s =
+			match s with
+			| "iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift" | "join" | "push" -> true
+			| _ -> false
+		in
 		match fa with
 			(* we need to get rid of these cases in the transformer, how is this handled in js *)
 			| FInstance(c,{cf_name = "length" | "get_length"}) when (is_type "" "list")(TClassDecl c) ->
@@ -1347,17 +1352,10 @@ module Printer = struct
 				Printf.sprintf "HxString.fromCharCode"
 			| FInstance _ | FStatic _ ->
 				do_default ()
-			| FAnon cf when name = "iterator" && not is_assign ->
-				begin match follow cf.cf_type with
-					| TFun([],_) ->
-						Printf.sprintf "python_lib_FuncTools.partial(HxOverrides.iterator, %s)" obj
-					| _ ->
-						do_default()
-				end
-			| FAnon cf when name = "shift" && not is_assign ->
+			| FAnon cf when is_assign && call_override(name) ->
 				begin match follow cf.cf_type with
 					| TFun([],_) ->
-						Printf.sprintf "python_lib_FuncTools.partial(HxOverrides.shift, %s)" obj
+						Printf.sprintf "python_lib_FuncTools.partial(HxOverrides.%s, %s)" name obj
 					| _ ->
 						do_default()
 				end
@@ -1506,9 +1504,9 @@ module Printer = struct
 
 	and print_call pctx e1 el =
 		match e1.eexpr, el with
-			| TField(e1,((FAnon {cf_name = "iterator"}) | FDynamic ("iterator"))), [] ->
-				Printf.sprintf "HxOverrides.iterator(%s)" (print_expr pctx e1)
-			| TField(e1,((FAnon {cf_name = ("toUpperCase" | "toLowerCase" as s)}) | FDynamic ("toUpperCase" | "toLowerCase" as s))), [] ->
+			| TField(e1,((FAnon {cf_name = (("join" | "push") as s)}) | FDynamic (("join" | "push") as s))), [x] ->
+				Printf.sprintf "HxOverrides.%s(%s, %s)" s (print_expr pctx e1) (print_expr pctx x)
+			| TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] ->
 				Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
 			| _,_ ->
 				print_call2 pctx e1 el

+ 1 - 1
genxml.ml

@@ -167,7 +167,7 @@ let gen_constr e =
 		| _ ->
 			[] , doc
 	) in
-	node e.ef_name args t
+	node e.ef_name args (t @ gen_meta e.ef_meta)
 
 let gen_ordered_constr e =
 	let rec loop el = match el with

+ 5 - 5
main.ml

@@ -1047,7 +1047,7 @@ try
 		("-swf-version",Arg.Float (fun v ->
 			if not !swf_version || com.flash_version < v then com.flash_version <- v;
 			swf_version := true;
-		),"<version> : change the SWF version (6 to 10)");
+		),"<version> : change the SWF version");
 		("-swf-header",Arg.String (fun h ->
 			try
 				swf_header := Some (match ExtString.String.nsplit h ":" with
@@ -1379,9 +1379,6 @@ try
 	end;
 	com.config <- get_config com; (* make sure to adapt all flags changes defined after platform *)
 
-	(* check file extension. In case of wrong commandline, we don't want
-		to accidentaly delete a source file. *)
-	if not !no_output && file_extension com.file = ext then delete_file com.file;
 	List.iter (fun f -> f()) (List.rev (!pre_compilation));
 	if !classes = [([],"Std")] && not !force_typing then begin
 		let help_spec = basic_args_spec @ [
@@ -1418,6 +1415,9 @@ try
 		com.modules <- modules;
 		Filters.run com tctx main;
 		if ctx.has_error then raise Abort;
+		(* check file extension. In case of wrong commandline, we don't want
+			to accidentaly delete a source file. *)
+		if not !no_output && file_extension com.file = ext then delete_file com.file;
 		(match !xml_out with
 		| None -> ()
 		| Some "hx" ->
@@ -1561,7 +1561,7 @@ with
 			| Typer.ITEnum(en,ef) -> Buffer.add_string b (Printf.sprintf "<i k=\"enum\" t=\"%s\">%s</i>\n" (s_type ef.ef_type) ef.ef_name);
 			| Typer.ITGlobal(mt,s,t) -> Buffer.add_string b (Printf.sprintf "<i k=\"global\" p=\"%s\" t=\"%s\">%s</i>\n" (s_type_path (t_infos mt).mt_path) (s_type t) s);
 			| Typer.ITType(mt) -> Buffer.add_string b (Printf.sprintf "<i k=\"type\" p=\"%s\">%s</i>\n" (s_type_path (t_infos mt).mt_path) (snd (t_infos mt).mt_path));
-			| Typer.ITPackage s -> Buffer.add_string b (Printf.sprintf "<i k=\"package\">%s<i>\n" s)
+			| Typer.ITPackage s -> Buffer.add_string b (Printf.sprintf "<i k=\"package\">%s</i>\n" s)
 		) il;
 		Buffer.add_string b "</il>";
 		raise (Completion (Buffer.contents b))

+ 3 - 3
std/IntIterator.hx

@@ -41,7 +41,7 @@ class IntIterator {
 
 		If `max <= min`, the iterator will not act as a countdown.
 	**/
-	public function new( min : Int, max : Int ) {
+	public inline function new( min : Int, max : Int ) {
 		this.min = min;
 		this.max = max;
 	}
@@ -49,7 +49,7 @@ class IntIterator {
 	/**
 		Returns true if the iterator has other items, false otherwise.
 	**/
-	public function hasNext() {
+	public inline function hasNext() {
 		return min < max;
 	}
 
@@ -58,7 +58,7 @@ class IntIterator {
 
 		If this is called while hasNext() is false, the result is unspecified.
 	**/
-	public function next() {
+	public inline function next() {
 		return min++;
 	}
 

+ 0 - 19
std/cpp/BasePointer.hx

@@ -1,19 +0,0 @@
-package cpp;
-
-@:coreType @:include("cpp/Pointer.h")
-extern class BasePointer<T>
-{
-   // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers
-   // Use value or ref to get dereferenced value
-	public var ptr:T;
-
-	public var value(get,never):T;
-
-	public function lt(inOther:BasePointer<T>):Bool;
-	public function leq(inOther:BasePointer<T>):Bool;
-	public function gt(inOther:BasePointer<T>):Bool;
-	public function geq(inOther:BasePointer<T>):Bool;
-
-}
-
-

+ 17 - 1
std/cpp/ConstPointer.hx

@@ -1,8 +1,24 @@
 package cpp;
 
 @:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer")
-extern class ConstPointer<T> extends BasePointer<T>
+extern class ConstPointer<T>
 {
+   // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers
+   // Use value or ref to get dereferenced value
+	private var ptr:T;
+
+	public var value(get,never):T;
+	public var raw(get,never):RawConstPointer<T>;
+
+   public function get_raw() : RawConstPointer<T>;
+
+	public function lt(inOther:Pointer<T>):Bool;
+	public function leq(inOther:Pointer<T>):Bool;
+	public function gt(inOther:Pointer<T>):Bool;
+	public function geq(inOther:Pointer<T>):Bool;
+
+
+
    public static function fromPointer<T>(inNativePointer:Dynamic) : ConstPointer<T>;
 
 	public function reinterpret<Other>():Pointer<Other>;

+ 2 - 0
std/cpp/Function.hx

@@ -3,6 +3,8 @@ package cpp;
 @:coreType @:structAccess @:include("cpp/Pointer.h")
 extern class Function<T>
 {
+   public function new(d:Dynamic);
+
    // Actually a function pointer, but can be called using haxe notation
 	public var call(default,null):T;
 

+ 58 - 2
std/cpp/Lib.hx

@@ -21,8 +21,19 @@
  */
 package cpp;
 
+#if macro
+import haxe.macro.Context;
+import haxe.macro.Type;
+import haxe.macro.Expr;
+#end
+
+using cpp.NativeString;
+using cpp.RawConstPointer;
+using cpp.Char;
+
 class Lib {
 
+   #if !macro
 	/**
 		Load and return a Cpp primitive from a DLL library.
 	**/
@@ -37,10 +48,23 @@ class Lib {
 	/**
 		Load and return a Cpp primitive from a DLL library.
 	**/
-	@:extern public static inline function getProcAddress( lib : String, prim : String ) : Dynamic {
-		return untyped __global__.__hxcpp_cast_get_proc_address(lib,prim);
+	@:extern public static inline function getProcAddress( lib : String, prim : String, quietFail=false ) : Dynamic {
+		return untyped __global__.__hxcpp_cast_get_proc_address(lib,prim,quietFail);
+	}
+
+	public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic {
+		var factory:Function< RawConstPointer<Char> -> RawPointer<Object> > = getProcAddress(lib, prim + "__prime", quietFail);
+      if (factory!=null)
+      {
+         var func:Dynamic = factory.call(signature.raw());
+         if (func==null && !quietFail)
+            throw '$prim does not have signature $signature';
+         return func;
+      }
+      return null;
 	}
 
+
 	/**
 		Tries to load, and always returns a valid function, but the function may throw
 		if called.
@@ -94,4 +118,36 @@ class Lib {
 		untyped __global__.__hxcpp_println(v);
 	}
 
+   #else
+   static function codeToType(code:String) : String
+   {
+      switch(code)
+      {
+         case "b" : return "Bool";
+         case "i" : return "Int";
+         case "d" : return "Float";
+         case "f" : return "cpp.Float32";
+         case "s" : return "String";
+         case "o" : return "cpp.Object";
+         case "v" : return "cpp.Void";
+         case "c" : return "cpp.RawConstPtr<cpp.Char> ";
+         default:
+            throw "Unknown signature type :" + code;
+      }
+   }
+   #end
+
+   public static macro function loadPrime(inModule:String, inName:String, inSig:String,inAllowFail:Bool = false)
+   {
+      var parts = inSig.split("");
+      if (parts.length<1)
+         throw "Invalid function signature " + inSig;
+      var typeString = parts.length==1 ? "Void" : codeToType(parts.shift());
+      for(p in parts)
+         typeString += "->" + codeToType(p);
+      typeString = "cpp.Function<" + typeString + ">";
+      var expr = 'new $typeString(cpp.Lib._loadPrime("$inModule","$inName","$inSig",$inAllowFail))';
+      return Context.parse( expr, Context.currentPos() );
+   }
+
 }

+ 3 - 0
std/cpp/NativeString.hx

@@ -2,6 +2,9 @@ package cpp;
 
 extern class NativeString {
 
+	public static inline function raw( inString:String ) : RawConstPointer<Char> {
+      return untyped inString.__s;
+   }
 	public static inline function c_str( inString:String ) : ConstPointer<Char> {
 		return cpp.ConstPointer.fromPointer(untyped inString.__s);
    }

+ 16 - 0
std/cpp/Object.hx

@@ -0,0 +1,16 @@
+package cpp;
+
+@:native("::hx::Object *")
+extern class HxObjectPtr
+{
+   @:native("hx::DynamicPtr")
+   static function fromDynamic(x:Dynamic):Object;
+   @:native("Dynamic")
+   static function toDynamic(x:Object):Dynamic;
+}
+
+@:extern
+abstract Object(HxObjectPtr) {
+	@:from public inline static function from(x:Dynamic):Object return HxObjectPtr.fromDynamic(x);
+	@:to public inline static function to(inVal:HxObjectPtr):Dynamic return HxObjectPtr.toDynamic(inVal);
+}

+ 2 - 0
std/cpp/Pointer.hx

@@ -13,6 +13,8 @@ extern class Pointer<T> extends ConstPointer<T> implements ArrayAccess<T>
 
 	public static function arrayElem<T>(array:Array<T>, inElem:Int):Pointer<T>;
 
+   override public function get_raw() : RawPointer<T>;
+
 	override public function inc():Pointer<T>;
 	override public function dec():Pointer<T>;
 	override public function incBy(inT:Int):Pointer<T>;

+ 6 - 0
std/cpp/RawConstPointer.hx

@@ -0,0 +1,6 @@
+package cpp;
+
+@:unreflective
+extern class RawConstPointer<T>
+{
+}

+ 6 - 0
std/cpp/RawPointer.hx

@@ -0,0 +1,6 @@
+package cpp;
+
+@:unreflective
+extern class RawPointer<T> extends RawConstPointer<T>
+{
+}

+ 5 - 0
std/cpp/Void.hx

@@ -0,0 +1,5 @@
+package cpp;
+
+@:native("void")
+extern class Void { }
+

+ 3 - 2
std/cpp/_std/Type.hx

@@ -148,8 +148,9 @@ enum ValueType {
       for(name in names)
       {
          try {
-            var result:T = untyped e.mConstructEnum(name,null);
-            enums.push( result );
+            var result:T = untyped e.ConstructEnum(name,null);
+            if (result!=null)
+               enums.push( result );
          } catch ( invalidArgCount:String) {
          }
       }

+ 1 - 1
std/cs/internal/Runtime.hx

@@ -350,7 +350,7 @@ import cs.system.Type;
 			t = obj.GetType();
 			bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy;
 		} else {
-			if (obj == typeof(string) && field.Equals("fromCharCode"))
+			if (t == typeof(string) && field.Equals("fromCharCode"))
 				return new haxe.lang.Closure(typeof(haxe.lang.StringExt), field, 0);
 
 			obj = null;

+ 2 - 0
std/haxe/io/Bytes.hx

@@ -287,6 +287,8 @@ class Bytes {
 		try
 			return new String(b, pos, len, "UTF-8")
 		catch (e:Dynamic) throw e;
+		#elseif python
+		return python.Syntax.pythonCode("self.b[pos:pos+len].decode('UTF-8','replace')");
 		#else
 		var s = "";
 		var b = b;

+ 1 - 0
std/haxe/macro/ExampleJSGenerator.hx

@@ -49,6 +49,7 @@ class ExampleJSGenerator {
 		return switch(t) {
 			case TInst(c, _): getPath(c.get());
 			case TEnum(e, _): getPath(e.get());
+			case TAbstract(a, _): getPath(a.get());
 			default: throw "assert";
 		};
 	}

+ 43 - 3
std/haxe/rtti/CType.hx

@@ -61,7 +61,7 @@ typedef ClassField = {
 	var type : CType;
 	var isPublic : Bool;
 	var isOverride : Bool;
-	var doc : String;
+	var doc : Null<String>;
 	var get : Rights;
 	var set : Rights;
 	var params : TypeParams;
@@ -76,7 +76,7 @@ typedef TypeInfos = {
 	var module : Path;
 	var file : Null<String>;
 	var params : TypeParams;
-	var doc : String;
+	var doc : Null<String>;
 	var isPrivate : Bool;
 	var platforms : Platforms;
 	var meta : MetaData;
@@ -85,7 +85,7 @@ typedef TypeInfos = {
 typedef Classdef = {> TypeInfos,
 	var isExtern : Bool;
 	var isInterface : Bool;
-	var superClass : PathParams;
+	var superClass : Null<PathParams>;
 	var interfaces : List<PathParams>;
 	var fields : List<ClassField>;
 	var statics : List<ClassField>;
@@ -263,3 +263,43 @@ class TypeApi {
 	}
 
 }
+
+class CTypeTools {
+	static public function toString(t:CType):String {
+		return switch (t) {
+			case CUnknown:
+				"unknown";
+			case CClass(name, params), CEnum(name, params), CTypedef(name, params), CAbstract(name, params):
+				nameWithParams(name, params);
+			case CFunction(args, ret):
+				if (args.length == 0) {
+					"Void -> " +toString(ret);
+				} else {
+					args.map(functionArgumentName).join(" -> ");
+				}
+			case CDynamic(d):
+				if (d == null) {
+					"Dynamic";
+				} else {
+					"Dynamic<" + toString(d) + ">";
+				}
+			case CAnonymous(fields):
+				"{ " + fields.map(classField).join(", ");
+		}
+	}
+
+	static function nameWithParams(name:String, params:List<CType>) {
+		if (params.length == 0) {
+			return name;
+		}
+		return name + "<" + params.map(toString).join(", ") + ">";
+	}
+
+	static function functionArgumentName(arg:FunctionArgument) {
+		(arg.opt ? "?" : "") + arg.name + ":" + toString(arg.t) + (arg.value == null ? "" : " = " +arg.value);
+	}
+
+	static function classField(cf:ClassField) {
+		return cf.name + ":" +toString(cf.type);
+	}
+}

+ 57 - 0
std/haxe/rtti/Rtti.hx

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C)2005-2014 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package haxe.rtti;
+import haxe.rtti.CType;
+
+/**
+	Rtti is a helper class which supplements the `@:rtti` metadata.
+**/
+class Rtti {
+
+	/**
+		Returns the `haxe.rtti.CType.Classdef` corresponding to class `c`.
+
+		If `c` has no runtime type information, e.g. because no `@:rtti@` was
+		added, `null` is returned.
+
+		If `c` is null, the result is unspecified.
+	**/
+	static public function getRtti<T>(c:Class<T>):Null<Classdef> {
+		var rtti = Reflect.field(c, "__rtti");
+		var x = Xml.parse(rtti).firstElement();
+		var infos = new haxe.rtti.XmlParser().processElement(x);
+		switch (infos) {
+			case TClassdecl(c): return c;
+			case t: throw 'Enum mismatch: expected TClassDecl but found $t';
+		}
+	}
+
+	/**
+		Tells if `c` has runtime type information.
+
+		If `c` is null, the result is unspecified.
+	**/
+	static public function hasRtti<T>(c:Class<T>):Bool {
+		return Lambda.has(Type.getClassFields(c), "__rtti");
+	}
+}

+ 1 - 1
std/haxe/rtti/XmlParser.hx

@@ -393,7 +393,7 @@ class XmlParser {
 		};
 	}
 
-	function xclassfield( x : Fast, ?defPublic ) : ClassField {
+	function xclassfield( x : Fast, ?defPublic = false ) : ClassField {
 		var e = x.elements;
 		var t = xtype(e.next());
 		var doc = null;

+ 34 - 3
std/python/internal/HxOverrides.hx

@@ -32,14 +32,45 @@ class HxOverrides {
 	}
 
 	static public function shift(x) {
-		return Reflect.callMethod(null, Reflect.field(x, "shift"), []);
+		if (Boot.isArray(x)) {
+			return (x:Array<Dynamic>).shift();
+		}
+		return Syntax.callField(x, "shift");
 	}
+
+	static public function pop(x) {
+		if (Boot.isArray(x)) {
+			return (x:Array<Dynamic>).pop();
+		}
+		return Syntax.callField(x, "pop");
+	}
+
+	static public function push(x, e) {
+		if (Boot.isArray(x)) {
+			return (x:Array<Dynamic>).push(e);
+		}
+		return Syntax.callField(x, "push", e);
+	}
+
+	static public function join(x, sep) {
+		if (Boot.isArray(x)) {
+			return (x:Array<Dynamic>).join(sep);
+		}
+		return Syntax.callField(x, "join", sep);
+	}
+
 	static public function toUpperCase(x) {
-		return Reflect.callMethod(null, Reflect.field(x, "toUpperCase"), []);
+		if (Boot.isString(x)) {
+			return (x:String).toUpperCase();
+		}
+		return Syntax.callField(x, "toUpperCase");
 	}
 
 	static public function toLowerCase(x) {
-		return Reflect.callMethod(null, Reflect.field(x, "toLowerCase"), []);
+		if (Boot.isString(x)) {
+			return (x:String).toLowerCase();
+		}
+		return Syntax.callField(x, "toLowerCase");
 	}
 
 	static public function rshift(val:Int, n:Int) {

+ 10 - 9
tests/RunTravis.hx

@@ -373,7 +373,7 @@ class RunTravis {
 
 				//generate documentation
 				haxelibInstallGit("Simn", "hxparse", "development", "src", true);
-				haxelibInstallGit("Simn", "hxtemplo", "master", "src", true);
+				haxelibInstallGit("Simn", "hxtemplo", true);
 				haxelibInstallGit("Simn", "hxargs", true);
 				haxelibInstallGit("dpeek", "haxe-markdown", "master", "src", true, "markdown");
 
@@ -382,7 +382,7 @@ class RunTravis {
 				haxelibInstallGit("HaxeFoundation", "hxcs", true);
 
 				haxelibInstallGit("dpeek", "dox", true);
-				changeDirectory(getHaxelibPath("dox") + "..");
+				changeDirectory(getHaxelibPath("dox"));
 				runCommand("haxe", ["run.hxml"]);
 				runCommand("haxe", ["gen.hxml"]);
 				haxelibRun(["dox", "-o", "bin/api.zip", "-i", "bin/xml"]);
@@ -432,8 +432,11 @@ class RunTravis {
 				runCommand("./Main-debug", ["foo", "12", "a b c\\\\"]);
 			case Js:
 				getJSDependencies();
-				runCommand("haxe", ["compile-js.hxml"]);
-				runCommand("node", ["-e", "var unit = require('./unit.js').unit; unit.Test.main(); process.exit(unit.Test.success ? 0 : 1);"]);
+
+				for (flatten in [true, false]) {
+					runCommand("haxe", ["compile-js.hxml"].concat(flatten ? ["-D", "js-flatten"] : []));
+					runCommand("node", ["-e", "var unit = require('./unit.js').unit; unit.Test.main(); process.exit(unit.Test.success ? 0 : 1);"]);
+				}
 
 				if (Sys.getEnv("TRAVIS_SECURE_ENV_VARS") == "true" && systemName == "Linux") {
 					//https://saucelabs.com/opensource/travis
@@ -512,8 +515,6 @@ class RunTravis {
 		haxelibInstallGit("Simn", "hxparse", "development", "src");
 		haxelibInstallGit("Simn", "hxtemplo");
 
-		changeDirectory(getHaxelibPath("hxtemplo"));
-
 		var buildArgs = [
 			"-cp", "src",
 			"-cp", "test",
@@ -522,7 +523,7 @@ class RunTravis {
 			"-dce", "full"
 		];
 
-		changeDirectory(getHaxelibPath("hxtemplo"));
+		changeDirectory(getHaxelibPath("hxtemplo") + "..");
 		runCommand("haxe", ["build.hxml"]);
 	}
 
@@ -550,9 +551,9 @@ class RunTravis {
 		haxelibInstallGit("massiveinteractive", "MassiveUnit", "master", "src", false, "munit");
 		changeDirectory(Path.join([getHaxelibPath("munit"), "..", "tool"]));
 		runCommand("haxe", ["build.hxml"]);
-		haxelibRun(["munit", "test", "-result-exit-code", "-neko"]);
+		haxelibRun(["munit", "test", "-result-exit-code", "-neko"], true);
 		changeDirectory("../");
-		haxelibRun(["munit", "test", "-result-exit-code", "-neko"]);
+		haxelibRun(["munit", "test", "-result-exit-code", "-neko"], true);
 	}
 
 	static function testFlambe() {

+ 11 - 0
tests/optimization/src/Test.hx

@@ -8,6 +8,10 @@ class InlineCtor {
 	}
 }
 
+@:enum abstract MyEnum(String) to String {
+	var A = "a";
+}
+
 class Test {
 	@:js('3;')
 	static function testNoOpRemoval() {
@@ -128,4 +132,11 @@ class Test {
 		var a = [1, 2];
 		a[2];
 	}
+
+	@:js('
+		var s = "" + "a";
+	')
+	static function testAbstractOverStringBinop() {
+		var s = "" + A;
+	}
 }

+ 1 - 1
tests/unit/MyAbstract.hx

@@ -181,7 +181,7 @@ abstract MyInt(Int) from Int to Int {
 	}
 }
 
-abstract MyInt2(Int){
+abstract MyInt2(Int) from MyInt {
 	public inline function new(v) {
 		this = v;
 	}

+ 17 - 14
tests/unit/RunSauceLabs.hx

@@ -17,7 +17,7 @@ class RunSauceLabs {
 			tags.push("TravisCI");
 
 		//https://saucelabs.com/platforms
-		var browsers = [
+		var browsers:Array<Dynamic> = [
 			// {
 			// 	"browserName": "internet explorer",
 			// 	"platform": "Windows XP",
@@ -51,12 +51,12 @@ class RunSauceLabs {
 			{
 				"browserName": "chrome",
 				"platform": "Windows XP",
-				"version": "31"
+				"version": "35"
 			},
 			{
 				"browserName": "firefox",
 				"platform": "Windows XP",
-				"version": "26"
+				"version": "30"
 			},
 			{
 				"browserName": "safari",
@@ -73,28 +73,22 @@ class RunSauceLabs {
 				"platform": "OS X 10.9",
 				"version": "7"
 			},
-			{
-				"browserName": "iphone",
-				"platform": "OS X 10.8",
-				"version": "6.1",
-				"device-orientation": "portrait"
-			},
 			{
 				"browserName": "iphone",
 				"platform": "OS X 10.9",
-				"version": "7",
+				"version": "7.1",
 				"device-orientation": "portrait"
 			},
 			{
-				"browserName": "iphone",
-				"platform": "OS X 10.9",
-				"version": "7.1",
+				"browserName": "android",
+				"platform": "Linux",
+				"version": "4.0",
 				"device-orientation": "portrait"
 			},
 			{
 				"browserName": "android",
 				"platform": "Linux",
-				"version": "4.0",
+				"version": "4.3",
 				"device-orientation": "portrait"
 			}
 		];
@@ -120,8 +114,14 @@ class RunSauceLabs {
 					console.log('${caps.browserName} ${caps.version} on ${caps.platform}:');
 					browser.init(caps, function(err) {
 						if (!handleError(err)) return;
+						browser.setAsyncScriptTimeout(30000); //10s timeout
 						browser.get("http://localhost:2000/unit-js.html", function(err) {
 							if (!handleError(err)) return;
+
+							console.log("[debug] waiting for test exit");
+							browser.waitForConditionInBrowser("try { typeof unit.Test.success === 'boolean'; } catch(e) { false; }", 3000); //3s timeout
+							console.log("[debug] test exited");
+
 							browser.text("body", function(err, re) {
 								if (!handleError(err)) return;
 								console.log(re);
@@ -135,11 +135,14 @@ class RunSauceLabs {
 									}
 								}
 								success = success && test;
+								console.log("[debug] all SauceLabs tests success: " + success);
 
 								//let saucelabs knows the result
 								browser.sauceJobUpdate({ passed: test }, function(err) {
+									console.log("[debug] job update: " + (err == null ? "ok" : err));
 									if (!handleError(err)) return;
 									browser.quit(function(err) {
+										console.log("[debug] browser quit: " + (err == null ? "ok" : err));
 										if (!handleError(err)) return;
 										testBrowsers(browsers);
 									});

+ 1 - 1
tests/unit/Test.hx

@@ -1,6 +1,6 @@
 package unit;
 
-@:expose
+@:expose("unit.Test")
 @:keepSub
 #if as3
 @:publicFields

+ 19 - 0
tests/unit/TestSpecification.hx

@@ -122,6 +122,25 @@ enum EVMTest {
 	EVMF(a:Array<EVMTest>);
 }
 
+class NonRttiClass { }
+
+@:rtti
+@:keepSub
+class RttiClass1 {
+    static var v:String;
+    public function f() {
+        return 33.0;
+    }
+}
+
+class RttiClass2 extends RttiClass1 { }
+
+class RttiClass3 extends RttiClass1 {
+	override function f():Int {
+		return 33;
+	}
+}
+
 #if !macro
 @:build(unit.UnitBuilder.build("unitstd"))
 #end

+ 56 - 0
tests/unit/issues/Issue3071.hx

@@ -0,0 +1,56 @@
+package unit.issues;
+import unit.Test;
+
+class Issue3071 extends Test {
+
+
+    function test() {
+    	// join
+    	var a : { function join (s:String):String; } = [1,2];
+    	eq("1,2", a.join(","));
+
+    	var a : Dynamic = [1,2];
+    	eq("1,2", a.join(","));
+
+    	// pop
+    	var a : { function pop ():Int; } = [1,2];
+    	a.pop();
+    	var a : Array<Int> = cast a;
+    	eq(1, a.length);
+    	eq(a[0], 1);
+
+    	var a : Dynamic = [1,2];
+    	a.pop();
+    	var a : Array<Int> = cast a;
+    	eq(1, a.length);
+    	eq(a[0], 1);
+
+    	// push
+    	var a : { function push (x:Int):Int; } = [];
+    	a.push(1);
+    	var a : Array<Int> = cast a;
+    	eq(1, a.length);
+    	eq(a[0], 1);
+
+    	var a : Dynamic = [];
+    	a.push(1);
+    	var a : Array<Int> = cast a;
+    	eq(1, a.length);
+    	eq(a[0], 1);
+
+    	// shift
+    	var a : { function shift ():Int; } = [1,2];
+    	a.shift();
+    	var a : Array<Int> = cast a;
+    	eq(1, a.length);
+    	eq(a[0], 2);
+
+    	var a : Dynamic = [1,2];
+    	a.shift();
+    	var a : Array<Int> = cast a;
+    	eq(1, a.length);
+    	eq(a[0], 2);
+
+    }
+
+}

+ 12 - 0
tests/unit/issues/Issue3110.hx

@@ -0,0 +1,12 @@
+package unit.issues;
+
+private abstract MyOpaciteInt(Int) {}
+
+class Issue3110 extends Test {
+	function test() {
+		var o:List<MyOpaciteInt> = null;
+		t(unit.TestType.typeError({
+			var u:List<UInt> = o;
+		}));
+	}
+}

+ 87 - 0
tests/unit/unitstd/haxe/ds/WeakMap.unit.hx

@@ -0,0 +1,87 @@
+#if flash
+var k1 = new IntWrap(1);
+var k2 = new IntWrap(2);
+var k3 = new IntWrap(3);
+var o = new haxe.ds.WeakMap();
+
+// non existent
+o.exists(k1) == false;
+o.exists(k2) == false;
+o.exists(k3) == false;
+o.get(k1) == null;
+o.get(k2) == null;
+o.get(k3) == null;
+
+// set + exists
+o.set(k1, "9");
+o.set(k2, "8");
+o.set(k3, "7");
+o.exists(k1) == true;
+o.exists(k2) == true;
+o.exists(k3) == true;
+
+// the __id__ field should not appear in Reflect.fields
+#if (js || flash8)
+var fields = Reflect.fields(k1);
+fields == ["i"];
+#end
+
+// get
+o.get(k3) == "7";
+o.get(k2) == "8";
+o.get(k1) == "9";
+
+// keys
+var a = [];
+for (k in o.keys())
+	a.push(k);
+a.length == 3;
+a[0] in [k1, k2, k3];
+a[1] in [k1, k2, k3];
+a[2] in [k1, k2, k3];
+o.exists(k1) == true;
+o.exists(k2) == true;
+o.exists(k3) == true;
+o.get(k3) == "7";
+o.get(k2) == "8";
+o.get(k1) == "9";
+
+// iterator
+var a:Array<String> = [];
+for (k in o) {
+	a.push(k);
+}
+a.length == 3;
+a[0] in ["9", "8", "7"];
+a[1] in ["9", "8", "7"];
+a[2] in ["9", "8", "7"];
+o.exists(k1) == true;
+o.exists(k2) == true;
+o.exists(k3) == true;
+o.get(k3) == "7";
+o.get(k2) == "8";
+o.get(k1) == "9";
+
+// remove
+o.remove(k2) == true;
+o.exists(k1) == true;
+o.exists(k2) == false;
+o.exists(k3) == true;
+o.get(k1) == "9";
+o.get(k2) == null;
+o.get(k3) == "7";
+var a = [];
+for (k in o.keys())
+	a.push(k);
+a.length == 2;
+a[0] in [k1, k3];
+a[1] in [k1, k3];
+var a:Array<String> = [];
+for (k in o.iterator()) {
+	a.push(k);
+}
+a.length == 2;
+a[0] in ["9", "7"];
+a[1] in ["9", "7"];
+o.remove(k2) == false;
+#end

+ 80 - 0
tests/unit/unitstd/haxe/rtti/Rtti.unit.hx

@@ -0,0 +1,80 @@
+haxe.rtti.Rtti.hasRtti(NonRttiClass) == false;
+haxe.rtti.Rtti.hasRtti(RttiClass1) == true;
+haxe.rtti.Rtti.hasRtti(RttiClass2) == true;
+
+var cl = haxe.rtti.Rtti.getRtti(RttiClass1);
+cl.isExtern == false;
+cl.isInterface == false;
+cl.params == [];
+cl.fields.length == 1;
+cl.superClass == null;
+cl.interfaces.length == 0;
+cl.fields.length == 1;
+cl.statics.length == 1;
+cl.tdynamic == null;
+
+var cf = cl.statics.first();
+cf.name == "v";
+haxe.rtti.CType.CTypeTools.toString(cf.type) == "String";
+cf.isPublic == false;
+cf.isOverride == false;
+cf.doc == null;
+cf.get == RNormal;
+cf.set == RNormal;
+cf.params == [];
+cf.platforms.length == 0;
+cf.meta.length == 0;
+cf.line == null;
+cf.overloads == null;
+
+var cf = cl.fields.first();
+cf.name == "f";
+haxe.rtti.CType.CTypeTools.toString(cf.type) == "Void -> Float";
+cf.isPublic == true;
+cf.isOverride == false;
+cf.doc == null;
+cf.get == RNormal;
+cf.set == RMethod;
+cf.params == [];
+cf.platforms.length == 0;
+cf.meta.length == 0;
+//cf.line == null;
+cf.overloads == null;
+
+var cl = haxe.rtti.Rtti.getRtti(RttiClass2);
+cl.isExtern == false;
+cl.isInterface == false;
+cl.params == [];
+cl.fields.length == 0;
+cl.superClass.path == "unit.RttiClass1";
+cl.superClass.params.length == 0;
+cl.interfaces.length == 0;
+cl.fields.length == 0;
+cl.statics.length == 0;
+cl.tdynamic == null;
+
+var cl = haxe.rtti.Rtti.getRtti(RttiClass3);
+cl.isExtern == false;
+cl.isInterface == false;
+cl.params == [];
+cl.fields.length == 1;
+cl.superClass.path == "unit.RttiClass1";
+cl.superClass.params.length == 0;
+cl.interfaces.length == 0;
+cl.fields.length == 1;
+cl.statics.length == 0;
+cl.tdynamic == null;
+
+var cf = cl.fields.first();
+cf.name == "f";
+haxe.rtti.CType.CTypeTools.toString(cf.type) == "Void -> Int";
+cf.isPublic == true;
+cf.isOverride == true;
+cf.doc == null;
+cf.get == RNormal;
+cf.set == RMethod;
+cf.params == [];
+cf.platforms.length == 0;
+cf.meta.length == 0;
+//cf.line == null;
+cf.overloads == null;

+ 5 - 4
type.ml

@@ -1548,11 +1548,12 @@ and unify_with_variance f t1 t2 =
 	| TAbstract(a1,tl1),TAbstract(a2,tl2) when a1 == a2 && Meta.has Meta.CoreType a1.a_meta ->
 		List.iter2 f tl1 tl2
 	| TAbstract(a1,pl1),TAbstract(a2,pl2) ->
-		let ta1 = apply_params a1.a_types pl1 a1.a_this in
-		let ta2 = apply_params a2.a_types pl2 a2.a_this in
-		if (Meta.has Meta.CoreType a1.a_meta) && (Meta.has Meta.CoreType a2.a_meta) then
+		if (Meta.has Meta.CoreType a1.a_meta) && (Meta.has Meta.CoreType a2.a_meta) then begin
+			let ta1 = apply_params a1.a_types pl1 a1.a_this in
+			let ta2 = apply_params a2.a_types pl2 a2.a_this in
 			type_eq EqStrict ta1 ta2;
-		if not (List.exists (allows_variance_to ta2) a1.a_to) && not (List.exists (allows_variance_to ta1) a2.a_from) then
+		end;
+		if not (List.exists (allows_variance_to t2) a1.a_to) && not (List.exists (allows_variance_to t1) a2.a_from) then
 			error [cannot_unify t1 t2]
 	| TAbstract(a,pl),t ->
 		type_eq EqStrict (apply_params a.a_types pl a.a_this) t;

+ 17 - 13
typer.ml

@@ -89,12 +89,12 @@ type type_class =
 	| KDyn
 	| KOther
 	| KParam of t
-	| KAbstract of tabstract
+	| KAbstract of tabstract * t list
 
 let rec classify t =
 	match follow t with
 	| TInst ({ cl_path = ([],"String") },[]) -> KString
-	| TAbstract({a_impl = Some _} as a,_) -> KAbstract a
+	| TAbstract({a_impl = Some _} as a,tl) -> KAbstract (a,tl)
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
 	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat
 	| TAbstract (a,[]) when List.exists (fun (t,_) -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KParam t
@@ -1855,16 +1855,20 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 	let tfloat = ctx.t.tfloat in
 	let tstring = ctx.t.tstring in
 	let to_string e =
-		match classify e.etype with
-		| KAbstract {a_impl = Some c} when PMap.mem "toString" c.cl_statics ->
-			call_to_string ctx c e
-		| KUnk | KDyn | KParam _ | KOther | KAbstract _ ->
-			let std = type_type ctx ([],"Std") e.epos in
-			let acc = acc_get ctx (type_field ctx std "string" e.epos MCall) e.epos in
-			ignore(follow acc.etype);
-			let acc = (match acc.eexpr with TField (e,FClosure (Some c,f)) -> { acc with eexpr = TField (e,FInstance (c,f)) } | _ -> acc) in
-			make_call ctx acc [e] ctx.t.tstring e.epos
-		| KInt | KFloat | KString -> e
+		let rec loop t = match classify t with
+			| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
+				call_to_string ctx c e
+			| KInt | KFloat | KString -> e
+			| KUnk | KDyn | KParam _ | KOther ->
+				let std = type_type ctx ([],"Std") e.epos in
+				let acc = acc_get ctx (type_field ctx std "string" e.epos MCall) e.epos in
+				ignore(follow acc.etype);
+				let acc = (match acc.eexpr with TField (e,FClosure (Some c,f)) -> { acc with eexpr = TField (e,FInstance (c,f)) } | _ -> acc) in
+				make_call ctx acc [e] ctx.t.tstring e.epos
+			| KAbstract (a,tl) ->
+				loop (Codegen.Abstract.get_underlying_type a tl)
+		in
+		loop e.etype
 	in
 	let mk_op e1 e2 t =
 		if op = OpAdd && (classify t) = KString then
@@ -2716,7 +2720,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		| WithType t | WithTypeResume t ->
 			(match follow t with
 			| TAnon a when not (PMap.is_empty a.a_fields) -> Some a
-			| TAbstract (a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
+			| TAbstract (a,tl) when not (Meta.has Meta.CoreType a.a_meta) && List.exists (fun (_,cfo) -> cfo = None) a.a_from ->
 				begin match follow (Codegen.Abstract.get_underlying_type a tl) with
 					| TAnon a when not (PMap.is_empty a.a_fields) -> Some a
 					| _ -> None