Selaa lähdekoodia

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

Nicolas Cannasse 9 vuotta sitten
vanhempi
commit
62f1a6f2ab

+ 2 - 2
.gitignore

@@ -74,5 +74,5 @@ tests/unit/bin/
 tests/*.n
 tests/*.n
 tests/misc/projects/Issue3756/cpp/
 tests/misc/projects/Issue3756/cpp/
 tests/misc/projects/Issue4070/cpp/
 tests/misc/projects/Issue4070/cpp/
-/tests/unit/unit_hl.hxml
-/*.manifest
+
+/*.manifest

+ 68 - 2
.travis.yml

@@ -37,7 +37,71 @@ matrix:
     # linux #
     # linux #
     #########
     #########
     - os: linux
     - os: linux
-      env: TEST=hl
+      env: TEST=third-party
+      language: php
+      php: 5.4
+      addons: {apt: {packages: [*apt_cpp, *apt_cs, *apt_python]}}
+    - os: linux
+      env: TEST=macro
+      addons: {apt: {packages: [*apt_cs, *apt_python]}}
+    - os: linux
+      env:
+        - TEST=neko
+        - BINTRAY=1
+    - os: linux
+      env:
+        - TEST=js
+        - SAUCE=1
+      addons: {apt: {packages: *apt_common}, sauce_connect: true}
+    - os: linux
+      env: TEST=php
+      language: php
+      php: 5.4
+    - os: linux
+      env: TEST=cpp
+      addons: {apt: {packages: *apt_cpp}}
+    - os: linux
+      env: TEST=flash9
+      addons: {apt: {packages: *apt_flash}}
+    - os: linux
+      env: TEST=as3
+      addons: {apt: {packages: *apt_flash}}
+    - os: linux
+      env: TEST=java
+    - os: linux
+      env: TEST=cs
+      addons: {apt: {packages: *apt_cs}}
+    - os: linux
+      env: TEST=python
+      addons: {apt: {packages: *apt_python}}
+
+    #######
+    # osx #
+    #######
+    - os: osx
+      env: TEST=third-party
+    - os: osx
+      env: TEST=macro
+    - os: osx
+      env:
+        - TEST=neko
+        - BINTRAY=1
+    - os: osx
+      env: TEST=js
+    - os: osx
+      env: TEST=php
+    - os: osx
+      env: TEST=cpp
+    - os: osx
+      env: TEST=flash9
+    - os: osx
+      env: TEST=as3
+    - os: osx
+      env: TEST=java
+    - os: osx
+      env: TEST=cs
+    - os: osx
+      env: TEST=python
 
 
 install:
 install:
   # Install haxe and neko dependencies
   # Install haxe and neko dependencies
@@ -62,8 +126,10 @@ before_script:
   - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
   - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
     travis_retry brew install mysql &&
     travis_retry brew install mysql &&
     mysql.server start;
     mysql.server start;
+    mysql -u root -e "create user if not exists travis@localhost identified by '';";
     fi
     fi
-  - mysql -u root -e "CREATE DATABASE haxe_test;";
+  - mysql -u root -e "CREATE DATABASE haxe_test;"
+  - mysql -u root -e "grant all on haxe_test.* to travis@localhost;"
 
 
 script:
 script:
   - make package_src -s
   - make package_src -s

+ 15 - 6
analyzer.ml

@@ -591,6 +591,11 @@ module Fusion = struct
 							change_num_uses v2 (-1);
 							change_num_uses v2 (-1);
 							let e = (f {e1 with eexpr = TUnop(op,Postfix,ev)}) in
 							let e = (f {e1 with eexpr = TUnop(op,Postfix,ev)}) in
 							fuse (e :: acc) el
 							fuse (e :: acc) el
+						| TLocal v2 when v == v2 ->
+							changed := true;
+							change_num_uses v2 (-1);
+							let e = (f {e1 with eexpr = TUnop(op,Prefix,ev)}) in
+							fuse (e :: acc) el
 						| _ ->
 						| _ ->
 							raise Exit
 							raise Exit
 					end
 					end
@@ -683,8 +688,8 @@ module BasicBlock = struct
 		bb_kind : block_kind;                 (* The block kind *)
 		bb_kind : block_kind;                 (* The block kind *)
 		mutable bb_closed : bool;             (* Whether or not the block has been closed *)
 		mutable bb_closed : bool;             (* Whether or not the block has been closed *)
 		(* elements *)
 		(* elements *)
-		bb_el : texpr DynArray.t;     (* The block expressions *)
-		bb_phi : texpr DynArray.t;    (* SSA-phi expressions *)
+		bb_el : texpr DynArray.t;             (* The block expressions *)
+		bb_phi : texpr DynArray.t;            (* SSA-phi expressions *)
 		(* relations *)
 		(* relations *)
 		mutable bb_outgoing : cfg_edge list;  (* Outgoing edges *)
 		mutable bb_outgoing : cfg_edge list;  (* Outgoing edges *)
 		mutable bb_incoming : cfg_edge list;  (* Incoming edges *)
 		mutable bb_incoming : cfg_edge list;  (* Incoming edges *)
@@ -751,7 +756,7 @@ module Graph = struct
 		mutable g_functions : tfunc_info IntMap.t; (* A map of functions, indexed by their block IDs *)
 		mutable g_functions : tfunc_info IntMap.t; (* A map of functions, indexed by their block IDs *)
 		mutable g_nodes : BasicBlock.t IntMap.t;   (* A map of all blocks *)
 		mutable g_nodes : BasicBlock.t IntMap.t;   (* A map of all blocks *)
 		mutable g_cfg_edges : cfg_edge list;       (* A list of all CFG edges *)
 		mutable g_cfg_edges : cfg_edge list;       (* A list of all CFG edges *)
-		g_var_infos : var_info DynArray.t; (* A map of variable information *)
+		g_var_infos : var_info DynArray.t;         (* A map of variable information *)
 		mutable g_loops : BasicBlock.t IntMap.t;   (* A map containing loop information *)
 		mutable g_loops : BasicBlock.t IntMap.t;   (* A map containing loop information *)
 	}
 	}
 
 
@@ -900,6 +905,7 @@ type analyzer_context = {
 	com : Common.context;
 	com : Common.context;
 	config : Config.t;
 	config : Config.t;
 	graph : Graph.t;
 	graph : Graph.t;
+	temp_var_name : string;
 	mutable entry : BasicBlock.t;
 	mutable entry : BasicBlock.t;
 	mutable has_unbound : bool;
 	mutable has_unbound : bool;
 	mutable loop_counter : int;
 	mutable loop_counter : int;
@@ -1085,7 +1091,7 @@ module TexprTransformer = struct
 					fl,e
 					fl,e
 			in
 			in
 			let fl,e = loop [] e in
 			let fl,e = loop [] e in
-			let v = alloc_var "tmp" e.etype in
+			let v = alloc_var ctx.temp_var_name e.etype in
 			begin match ctx.com.platform with
 			begin match ctx.com.platform with
 				| Cpp when sequential && not (Common.defined ctx.com Define.Cppia) -> ()
 				| Cpp when sequential && not (Common.defined ctx.com Define.Cppia) -> ()
 				| _ -> v.v_meta <- [Meta.CompilerGenerated,[],e.epos];
 				| _ -> v.v_meta <- [Meta.CompilerGenerated,[],e.epos];
@@ -1447,6 +1453,9 @@ module TexprTransformer = struct
 			com = com;
 			com = com;
 			config = config;
 			config = config;
 			graph = g;
 			graph = g;
+			(* For CPP we want to use variable names which are "probably" not used by users in order to
+			   avoid problems with the debugger, see https://github.com/HaxeFoundation/hxcpp/issues/365 *)
+			temp_var_name = (match com.platform with Cpp -> "_hx_tmp" | _ -> "tmp");
 			entry = g.g_unreachable;
 			entry = g.g_unreachable;
 			has_unbound = false;
 			has_unbound = false;
 			loop_counter = 0;
 			loop_counter = 0;
@@ -2229,7 +2238,7 @@ module CodeMotion = DataFlow(struct
 					let v' = if decl then begin
 					let v' = if decl then begin
 						v
 						v
 					end else begin
 					end else begin
-						let v' = alloc_var "tmp" v.v_type in
+						let v' = alloc_var ctx.temp_var_name v.v_type in
 						declare_var ctx.graph v';
 						declare_var ctx.graph v';
 						v'.v_meta <- [Meta.CompilerGenerated,[],p];
 						v'.v_meta <- [Meta.CompilerGenerated,[],p];
 						v'
 						v'
@@ -2702,8 +2711,8 @@ module Purity = struct
 			taint node
 			taint node
 		| Some e ->
 		| Some e ->
 			try
 			try
-				if is_pure c cf then raise Exit;
 				if (Meta.has (Meta.Custom ":impure")) cf.cf_meta then taint_raise node;
 				if (Meta.has (Meta.Custom ":impure")) cf.cf_meta then taint_raise node;
+				if is_pure c cf then raise Exit;
 				loop e;
 				loop e;
 				node.pn_purity <- Pure;
 				node.pn_purity <- Pure;
 			with Exit ->
 			with Exit ->

+ 11 - 0
appveyor.yml

@@ -14,10 +14,16 @@ environment:
         WODI: wodi32
         WODI: wodi32
         ADD_REVISION: 1
         ADD_REVISION: 1
         OCAMLOPT: ocamlopt.opt
         OCAMLOPT: ocamlopt.opt
+        MYSQL_PATH: C:\Program Files\MySQL\MySQL Server 5.6
+        MYSQL_USER: root
+        MYSQL_PASSWORD: Password12!
     matrix:
     matrix:
         - TEST: "neko,python,cs,java,macro"
         - TEST: "neko,python,cs,java,macro"
         - TEST: "cpp"
         - TEST: "cpp"
 
 
+services:
+    - mysql
+
 skip_tags: true
 skip_tags: true
 
 
 install:
 install:
@@ -60,6 +66,11 @@ build_script:
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - mkdir "%HAXELIB_ROOT%"
     - mkdir "%HAXELIB_ROOT%"
     - haxelib setup "%HAXELIB_ROOT%"
     - haxelib setup "%HAXELIB_ROOT%"
+    # setup mysql for testing
+    - set PATH=%MYSQL_PATH%\bin;%PATH%
+    - mysql --user=%MYSQL_USER% --password=%MYSQL_PASSWORD% -e "create user 'travis'@'localhost';"
+    - mysql --user=%MYSQL_USER% --password=%MYSQL_PASSWORD% -e "create database haxe_test;"
+    - mysql --user=%MYSQL_USER% --password=%MYSQL_PASSWORD% -e "grant all on haxe_test.* to 'travis'@'localhost';"
 
 
 test_script:
 test_script:
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - cd %APPVEYOR_BUILD_FOLDER%/tests/

+ 7 - 0
filters.ml

@@ -540,6 +540,13 @@ let rename_local_vars ctx e =
 		while PMap.mem (v.v_name ^ string_of_int !count) vars do
 		while PMap.mem (v.v_name ^ string_of_int !count) vars do
 			incr count;
 			incr count;
 		done;
 		done;
+		begin match ctx.com.platform with
+			| Cpp ->
+				if not (Meta.has Meta.RealPath v.v_meta) then
+					v.v_meta <- (Meta.RealPath,[EConst (String v.v_name),e.epos],e.epos) :: v.v_meta
+			| _ ->
+				()
+		end;
 		v.v_name <- v.v_name ^ string_of_int !count;
 		v.v_name <- v.v_name ^ string_of_int !count;
 	in
 	in
 	let declare v p =
 	let declare v p =

+ 36 - 17
gencpp.ml

@@ -60,6 +60,7 @@ let is_internal_class = function
    |  (["cpp"],"Pointer") | (["cpp"],"ConstPointer")
    |  (["cpp"],"Pointer") | (["cpp"],"ConstPointer")
    |  (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer")
    |  (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer")
    |  (["cpp"],"Function") -> true
    |  (["cpp"],"Function") -> true
+   |  (["cpp"],"VirtualArray") -> true
    |  ([],"Math") | (["haxe";"io"], "Unsigned_char__") -> true
    |  ([],"Math") | (["haxe";"io"], "Unsigned_char__") -> true
    |  (["cpp"],"Int8") | (["cpp"],"UInt8") | (["cpp"],"Char")
    |  (["cpp"],"Int8") | (["cpp"],"UInt8") | (["cpp"],"Char")
    |  (["cpp"],"Int16") | (["cpp"],"UInt16")
    |  (["cpp"],"Int16") | (["cpp"],"UInt16")
@@ -626,7 +627,8 @@ let rec class_string klass suffix params remap =
    (match klass.cl_path with
    (match klass.cl_path with
    (* Array class *)
    (* Array class *)
    |  ([],"Array") when is_dynamic_array_param (List.hd params) ->
    |  ([],"Array") when is_dynamic_array_param (List.hd params) ->
-           "cpp::ArrayBase" ^ suffix (* "Dynamic" *)
+           "cpp::ArrayBase" ^ suffix
+           (* "cpp::VirtualArray" ^ suffix *)
    |  ([],"Array") -> (snd klass.cl_path) ^ suffix ^ "< " ^ (String.concat ","
    |  ([],"Array") -> (snd klass.cl_path) ^ suffix ^ "< " ^ (String.concat ","
                (List.map array_element_type params) ) ^ " >"
                (List.map array_element_type params) ) ^ " >"
    (* FastIterator class *)
    (* FastIterator class *)
@@ -1317,6 +1319,7 @@ let find_undeclared_variables_ctx ctx undeclared declarations this_suffix allow_
    find_undeclared_variables undeclared declarations this_suffix allow_this expression
    find_undeclared_variables undeclared declarations this_suffix allow_this expression
 ;;
 ;;
 
 
+let is_virtual_array expr = (type_string expr.etype="cpp::VirtualArray") ;;
 
 
 let rec is_dynamic_in_cpp ctx expr =
 let rec is_dynamic_in_cpp ctx expr =
    let expr_type = type_string ( match follow expr.etype with TFun (args,ret) -> ret | _ -> expr.etype) in
    let expr_type = type_string ( match follow expr.etype with TFun (args,ret) -> ret | _ -> expr.etype) in
@@ -1348,7 +1351,7 @@ let rec is_dynamic_in_cpp ctx expr =
             )
             )
       | TConst TThis when ((not ctx.ctx_real_this_ptr) && ctx.ctx_dynamic_this_ptr) ->
       | TConst TThis when ((not ctx.ctx_real_this_ptr) && ctx.ctx_dynamic_this_ptr) ->
             ctx.ctx_dbgout ("/* dthis */"); true
             ctx.ctx_dbgout ("/* dthis */"); true
-      | TArray (obj,index) -> let dyn = is_dynamic_in_cpp ctx obj in
+      | TArray (obj,index) -> let dyn = (is_dynamic_in_cpp ctx obj || is_virtual_array obj) in
             ctx.ctx_dbgout ("/* aidr:" ^ (if dyn then "Dyn" else "Not") ^ " */");
             ctx.ctx_dbgout ("/* aidr:" ^ (if dyn then "Dyn" else "Not") ^ " */");
             dyn;
             dyn;
       | TTypeExpr _ -> false
       | TTypeExpr _ -> false
@@ -1399,18 +1402,20 @@ and is_dynamic_member_return_in_cpp ctx field_object field =
    | TTypeExpr t ->
    | TTypeExpr t ->
          let full_name = "::" ^ (join_class_path (t_path t) "::" ) ^ "." ^ member in
          let full_name = "::" ^ (join_class_path (t_path t) "::" ) ^ "." ^ member in
          ctx.ctx_dbgout ("/*static:"^ full_name^"*/");
          ctx.ctx_dbgout ("/*static:"^ full_name^"*/");
-         ( try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in mem_type="Dynamic"||mem_type="cpp::ArrayBase" )
+         ( try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in
+             mem_type="Dynamic" || mem_type="cpp::ArrayBase" || mem_type="cpp::VirtualArray" )
          with Not_found -> true )
          with Not_found -> true )
    | _ ->
    | _ ->
       let tstr = type_string field_object.etype in
       let tstr = type_string field_object.etype in
       (match tstr with
       (match tstr with
          (* Internal classes have no dynamic members *)
          (* Internal classes have no dynamic members *)
          | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math" | "::ArrayAccess" -> false
          | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math" | "::ArrayAccess" -> false
-         | "Dynamic" | "cpp::ArrayBase" -> ctx.ctx_dbgout "/*D*/"; true
+         | "Dynamic" | "cpp::ArrayBase" | "cpp::VirtualArray" -> ctx.ctx_dbgout "/*D*/"; true
          | name ->
          | name ->
                let full_name = name ^ "." ^ member in
                let full_name = name ^ "." ^ member in
                ctx.ctx_dbgout ("/*R:"^full_name^"*/");
                ctx.ctx_dbgout ("/*R:"^full_name^"*/");
-               try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in mem_type="Dynamic"||mem_type="cpp::ArrayBase" )
+               try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in
+                  mem_type="Dynamic" || mem_type="cpp::ArrayBase" || mem_type="cpp::VirtualArray" )
                with Not_found -> true )
                with Not_found -> true )
 ;;
 ;;
 
 
@@ -1950,10 +1955,14 @@ let gen_expression_tree ctx retval expression_tree set_var tail_code =
                output ( "." ^ remap_name )
                output ( "." ^ remap_name )
             else begin
             else begin
                cast_if_required ctx field_object (type_string field_object.etype);
                cast_if_required ctx field_object (type_string field_object.etype);
-               let remap_name = if (type_string field_object.etype)="cpp::ArrayBase" then
-                   match remap_name with
-                   | "length" -> remap_name
-                   | _ -> "__" ^ remap_name
+               let field_type = type_string field_object.etype in
+               let remap_name = if remap_name="length" then begin
+                  if field_type="cpp::VirtualArray" then
+                     "__length()"
+                  else
+                     remap_name
+               end else if field_type="cpp::ArrayBase" then
+                  "__" ^ remap_name
                else
                else
                   remap_name
                   remap_name
                in
                in
@@ -2072,7 +2081,7 @@ let gen_expression_tree ctx retval expression_tree set_var tail_code =
          let cpp_type = member_type ctx obj field.cf_name in
          let cpp_type = member_type ctx obj field.cf_name in
          (not (is_scalar cpp_type)) && (
          (not (is_scalar cpp_type)) && (
             let fixed = (cpp_type<>"?") && (expr_type<>"Dynamic") && (cpp_type<>"Dynamic") &&
             let fixed = (cpp_type<>"?") && (expr_type<>"Dynamic") && (cpp_type<>"Dynamic") &&
-               (cpp_type<>expr_type) && (expr_type<>"Void") && (cpp_type<>"cpp::ArrayBase") in
+               (cpp_type<>expr_type) && (expr_type<>"Void") && (cpp_type<>"cpp::ArrayBase") && (cpp_type<>"cpp::VirtualArray") in
             if (fixed && (ctx.ctx_debug_level>1) ) then begin
             if (fixed && (ctx.ctx_debug_level>1) ) then begin
                output ("/* " ^ (cpp_type) ^ " != " ^ expr_type ^ " -> cast */");
                output ("/* " ^ (cpp_type) ^ " != " ^ expr_type ^ " -> cast */");
             end;
             end;
@@ -2117,7 +2126,7 @@ let gen_expression_tree ctx retval expression_tree set_var tail_code =
 
 
       if (cast_result) then output (")");
       if (cast_result) then output (")");
       if ( (is_variable func) && (not (is_cpp_function_member func) ) &&
       if ( (is_variable func) && (not (is_cpp_function_member func) ) &&
-           (expr_type<>"Dynamic" && expr_type<>"cpp::ArrayBase" ) && (not is_super)  ) then
+           (expr_type<>"Dynamic" && expr_type<>"cpp::ArrayBase" && expr_type<>"cpp::VirtualArray" ) && (not is_super)  ) then
          ctx.ctx_output (".Cast< " ^ expr_type ^ " >()" );
          ctx.ctx_output (".Cast< " ^ expr_type ^ " >()" );
 
 
       let rec cast_array_output func =
       let rec cast_array_output func =
@@ -2201,7 +2210,9 @@ let gen_expression_tree ctx retval expression_tree set_var tail_code =
    | TLocal v -> output (keyword_remap v.v_name);
    | TLocal v -> output (keyword_remap v.v_name);
    | TArray (array_expr,_) when (is_null array_expr) -> output "Dynamic()"
    | TArray (array_expr,_) when (is_null array_expr) -> output "Dynamic()"
    | TArray (array_expr,index) ->
    | TArray (array_expr,index) ->
-      let dynamic =  is_dynamic_in_cpp ctx array_expr || (type_string array_expr.etype) = "cpp::ArrayBase" in
+      let dynamic =  (is_dynamic_in_cpp ctx array_expr) ||
+                     (type_string array_expr.etype) = "cpp::ArrayBase" ||
+                     (is_virtual_array array_expr) in
       if ( assigning && (not dynamic) ) then begin
       if ( assigning && (not dynamic) ) then begin
          if (is_array_implementer array_expr.etype) then begin
          if (is_array_implementer array_expr.etype) then begin
             output "hx::__ArrayImplRef(";
             output "hx::__ArrayImplRef(";
@@ -2331,8 +2342,16 @@ let gen_expression_tree ctx retval expression_tree set_var tail_code =
          | None -> ()
          | None -> ()
          | Some expression -> output " = "; gen_expression true expression);
          | Some expression -> output " = "; gen_expression true expression);
          count := !count -1;
          count := !count -1;
+      let get_var_name v =
+         let rec loop meta = match meta with
+            | (Meta.RealPath,[EConst (String s),_],_) :: _ -> s
+            | _ :: meta -> loop meta
+            | [] -> v.v_name
+         in
+         loop v.v_meta
+      in
       if (ctx.ctx_debug_level>0) then
       if (ctx.ctx_debug_level>0) then
-            output (";\t\tHX_STACK_VAR(" ^name ^",\""^ tvar.v_name ^"\")");
+            output (";\t\tHX_STACK_VAR(" ^name ^",\""^ (get_var_name tvar) ^"\")");
          if (!count > 0) then begin output ";\n"; output_i "" end
          if (!count > 0) then begin output ";\n"; output_i "" end
       end
       end
    | TFor (tvar, init, loop) ->
    | TFor (tvar, init, loop) ->
@@ -2790,10 +2809,10 @@ let gen_member_def ctx class_def is_static is_interface field =
             end
             end
          end else begin
          end else begin
             let return_type = (type_string function_def.tf_type) in
             let return_type = (type_string function_def.tf_type) in
-   
+
             if ( not is_static && not nonVirtual ) then output "virtual ";
             if ( not is_static && not nonVirtual ) then output "virtual ";
             output (if return_type="Void" && (has_meta_key field.cf_meta Meta.Void) then "void" else return_type );
             output (if return_type="Void" && (has_meta_key field.cf_meta Meta.Void) then "void" else return_type );
-   
+
             output (" " ^ remap_name ^ "(" );
             output (" " ^ remap_name ^ "(" );
             output (gen_arg_list function_def.tf_args "" );
             output (gen_arg_list function_def.tf_args "" );
             output ");\n";
             output ");\n";
@@ -2810,7 +2829,7 @@ let gen_member_def ctx class_def is_static is_interface field =
          (* Variable access *)
          (* Variable access *)
          gen_type ctx field.cf_type;
          gen_type ctx field.cf_type;
          output (" " ^ remap_name ^ ";\n" );
          output (" " ^ remap_name ^ ";\n" );
-   
+
          (* Add a "dyn" function for variable to unify variable/function access *)
          (* Add a "dyn" function for variable to unify variable/function access *)
          (match follow field.cf_type with
          (match follow field.cf_type with
          | _ when nativeGen  -> ()
          | _ when nativeGen  -> ()
@@ -5097,7 +5116,7 @@ class script_writer common_ctx ctx filename asciiOut =
             | "::String"  -> ArrayData "String"
             | "::String"  -> ArrayData "String"
             | "int" | "Float" | "bool" | "String" | "unsigned char" ->
             | "int" | "Float" | "bool" | "String" | "unsigned char" ->
                ArrayData typeName
                ArrayData typeName
-            | "cpp::ArrayBase" | "Dynamic" -> ArrayAny
+            | "cpp::ArrayBase" | "cpp::VirtualArray" | "Dynamic" -> ArrayAny
             | _ when is_interface_type param -> ArrayInterface (this#typeId (script_type_string param))
             | _ when is_interface_type param -> ArrayInterface (this#typeId (script_type_string param))
             | _ -> ArrayObject
             | _ -> ArrayObject
             )
             )

+ 3 - 1
genphp.ml

@@ -68,6 +68,8 @@ type context = {
 	mutable lib_path : string;
 	mutable lib_path : string;
 }
 }
 
 
+let follow = Abstract.follow_with_abstracts
+
 let join_class_path path separator =
 let join_class_path path separator =
 	let result = match fst path, snd path with
 	let result = match fst path, snd path with
 	| [], s -> s
 	| [], s -> s
@@ -307,7 +309,7 @@ let is_keyword n =
 	| "clone" | "instanceof" | "break" | "case" | "class" | "continue" | "default"
 	| "clone" | "instanceof" | "break" | "case" | "class" | "continue" | "default"
 	| "do" | "else" | "extends" | "for" | "function" | "if" | "new" | "return"
 	| "do" | "else" | "extends" | "for" | "function" | "if" | "new" | "return"
 	| "static" | "switch" | "var" | "while" | "interface" | "implements" | "public"
 	| "static" | "switch" | "var" | "while" | "interface" | "implements" | "public"
-	| "private" | "try" | "catch" | "throw" | "goto"
+	| "private" | "try" | "catch" | "throw" | "goto" | "yield"
 		-> true
 		-> true
 	| _ -> false
 	| _ -> false
 
 

+ 9 - 0
genswf9.ml

@@ -2017,7 +2017,16 @@ let check_constructor ctx c f =
 			error "You cannot assign some super class vars before calling super() in flash, this will reset them to default value" e.epos
 			error "You cannot assign some super class vars before calling super() in flash, this will reset them to default value" e.epos
 		| _ -> ()
 		| _ -> ()
 	in
 	in
+	(* only do so if we have a call to super() *)
+	let rec has_super e =
+		Type.iter has_super e;
+		match e.eexpr with
+		| TCall ({ eexpr = TConst TSuper },_) -> raise Exit
+		| _ -> ()
+	in
 	try
 	try
+		has_super f.tf_expr
+	with Exit -> try
 		loop f.tf_expr
 		loop f.tf_expr
 	with Exit ->
 	with Exit ->
 		()
 		()

+ 1 - 7
main.ml

@@ -980,7 +980,7 @@ and do_connect host port args =
 
 
 and init ctx =
 and init ctx =
 	let usage = Printf.sprintf
 	let usage = Printf.sprintf
-		"Haxe Compiler %s - (C)2005-2016 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3|-cs|-java|-python|-hl] <output> [options]\n Options :"
+		"Haxe Compiler %s - (C)2005-2016 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3|-cs|-java|-python] <output> [options]\n Options :"
 		s_version (if Sys.os_type = "Win32" then ".exe" else "")
 		s_version (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	in
 	let com = ctx.com in
 	let com = ctx.com in
@@ -1078,7 +1078,6 @@ try
 		("-python",Arg.String (fun dir ->
 		("-python",Arg.String (fun dir ->
 			set_platform Python dir;
 			set_platform Python dir;
 		),"<file> : generate Python code as target file");
 		),"<file> : generate Python code as target file");
-		("-hl", Arg.String (set_platform Hl),"<file> : compile code to HL binary");
 		("-xml",Arg.String (fun file ->
 		("-xml",Arg.String (fun file ->
 			Parser.use_doc := true;
 			Parser.use_doc := true;
 			xml_out := Some file
 			xml_out := Some file
@@ -1473,9 +1472,6 @@ try
 		| Python ->
 		| Python ->
 			add_std "python";
 			add_std "python";
 			"python"
 			"python"
-		| Hl ->
-			add_std "hl";
-			"hl"
 	) in
 	) in
 	(* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *)
 	(* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *)
 	begin match com.display with
 	begin match com.display with
@@ -1573,8 +1569,6 @@ try
 					Genjava.generate,"java"
 					Genjava.generate,"java"
 				| Python ->
 				| Python ->
 					Genpy.generate,"python"
 					Genpy.generate,"python"
-				| Hl ->
-					Genhl.generate,"hl"
 				| Cross ->
 				| Cross ->
 					assert false
 					assert false
 				in
 				in

+ 4 - 1
optimizer.ml

@@ -633,7 +633,10 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 		in
 		in
 		let e = (match e.eexpr, init with
 		let e = (match e.eexpr, init with
 			| _, None when not !has_return_value ->
 			| _, None when not !has_return_value ->
-				{e with etype = tret}
+				begin match e.eexpr with
+					| TBlock _ -> {e with etype = tret}
+					| _ -> mk (TBlock [e]) tret e.epos
+				end
 			| TBlock [e] , None -> wrap e
 			| TBlock [e] , None -> wrap e
 			| _ , None -> wrap e
 			| _ , None -> wrap e
 			| TBlock l, Some vl ->
 			| TBlock l, Some vl ->

+ 2 - 4
std/StringTools.hx

@@ -388,8 +388,6 @@ class StringTools {
 		return (untyped s).charCodeAt(index);
 		return (untyped s).charCodeAt(index);
 		#elseif python
 		#elseif python
 		return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index));
 		return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index));
-		#elseif hl
-		return @:privateAccess s.bytes.getUI16(index<<1);
 		#else
 		#else
 		return untyped s.cca(index);
 		return untyped s.cca(index);
 		#end
 		#end
@@ -399,7 +397,7 @@ class StringTools {
 		Tells if `c` represents the end-of-file (EOF) character.
 		Tells if `c` represents the end-of-file (EOF) character.
 	*/
 	*/
 	@:noUsing public static inline function isEof( c : Int ) : Bool {
 	@:noUsing public static inline function isEof( c : Int ) : Bool {
-		#if (flash || cpp || hl)
+		#if (flash || cpp)
 		return c == 0;
 		return c == 0;
 		#elseif js
 		#elseif js
 		return c != c; // fast NaN
 		return c != c; // fast NaN
@@ -457,7 +455,7 @@ class StringTools {
 	public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String {
 	public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String {
 		// If there is no space, tab, back-slash, or double-quotes, and it is not an empty string.
 		// If there is no space, tab, back-slash, or double-quotes, and it is not an empty string.
 		if (!~/^[^ \t\\"]+$/.match(argument)) {
 		if (!~/^[^ \t\\"]+$/.match(argument)) {
-
+			
 			// Based on cpython's subprocess.list2cmdline().
 			// Based on cpython's subprocess.list2cmdline().
 			// https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620
 			// https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620
 
 

+ 68 - 22
std/cpp/VirtualArray.hx

@@ -1,30 +1,76 @@
 package cpp;
 package cpp;
 
 
-extern class VirtualArray
+@:native("cpp::VirtualArray")
+@:coreType extern class NativeVirtualArray implements ArrayAccess<Dynamic>
 {
 {
-   function new() : Void;
-   var length(get,null) : Int;
+   public function new() : Void;
+   public var length(get,null) : Int;
    // concat<T>( a:Array<T> ) : Array<T> ?
    // concat<T>( a:Array<T> ) : Array<T> ?
-   function concat( a : VirtualArray ) : VirtualArray;
-   function join( sep : String ) : String;
-   function pop() : Dynamic;
-   function push(x : Dynamic) : Int;
-   function reverse() : Void;
-   function shift() : Dynamic;
-   function slice( pos : Int, ?end : Int ) : VirtualArray;
-   function sort( f : Dynamic -> Dynamic -> Int ) : Void;
-   function splice( pos : Int, len : Int ) : VirtualArray;
-   function toString() : String;
-   function unshift( x : Dynamic ) : Void;
-   function insert( pos : Int, x : Dynamic ) : Void;
-   function remove( x : Dynamic ) : Bool;
-   function indexOf( x : Dynamic, ?fromIndex:Int ) : Int;
-   function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int;
-   function copy() : VirtualArray;
-   function iterator() : Iterator<Dynamic>;
-   function map<S>( f : Dynamic -> S ) : VirtualArray;
-   function filter( f : Dynamic -> Bool ) : VirtualArray;
+   public function concat( a : VirtualArray ) : VirtualArray;
+   public function join( sep : String ) : String;
+   public function pop() : Dynamic;
+   public function push(x : Dynamic) : Int;
+   public function reverse() : Void;
+   public function shift() : Dynamic;
+   public function slice( pos : Int, ?end : Int ) : VirtualArray;
+   public function sort( f : Dynamic -> Dynamic -> Int ) : Void;
+   public function splice( pos : Int, len : Int ) : VirtualArray;
+   public function toString() : String;
+   public function unshift( x : Dynamic ) : Void;
+   public function insert( pos : Int, x : Dynamic ) : Void;
+   public function remove( x : Dynamic ) : Bool;
+   public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int;
+   public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int;
+   public function copy() : VirtualArray;
+   public function iterator() : Iterator<Dynamic>;
+   public function map<S>( f : Dynamic -> S ) : VirtualArray;
+   public function filter( f : Dynamic -> Bool ) : VirtualArray;
 }
 }
 
 
 
 
+abstract VirtualArray(NativeVirtualArray)
+{
+   // Add these two functions...
+   @:from @:extern inline static public function fromArray<T>(a:Array<T>) : VirtualArray
+      return untyped a;
+   @:to @:extern inline public function toArray<T>() : Array<T>
+      return untyped this;
+
+
+
+
+   // The rest is just boiler-plate
+   inline public function new() this=new NativeVirtualArray();
+
+   @:extern @:arrayAccess inline function get(idx:Int) : Dynamic
+      return untyped this[idx];
+
+   @:extern @:arrayAccess inline function set<T>(pos:Int, value:T ) : T
+      return untyped this[idx] = value;
+
+   public var length(get,never) : Int;
+   @:extern inline public function get_length() : Int return this.length;
+
+
+
+   // concat<T>( a:Array<T> ) : Array<T> ?
+   @:extern inline public function concat( a : VirtualArray ) : VirtualArray return this.concat(a);
+   @:extern inline public function join( sep : String ) : String return this.join(sep);
+   @:extern inline public function pop() : Dynamic return this.pop();
+   @:extern inline public function push(x : Dynamic) : Int return this.push(x);
+   @:extern inline public function reverse() : Void this.reverse();
+   @:extern inline public function shift() : Dynamic return this.shift();
+   @:extern inline public function slice( pos : Int, ?end : Int ) : VirtualArray return this.slice(pos,end);
+   @:extern inline public function sort( f : Dynamic -> Dynamic -> Int ) : Void this.sort(f);
+   @:extern inline public function splice( pos : Int, len : Int ) : VirtualArray return this.slice(pos,len);
+   @:extern inline public function unshift( x : Dynamic ) : Void this.unshift(x);
+   @:extern inline public function insert( pos : Int, x : Dynamic ) : Void this.insert(pos,x);
+   @:extern inline public function remove( x : Dynamic ) : Bool return this.remove(x);
+   @:extern inline public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int return this.indexOf(x,fromIndex);
+   @:extern inline public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int return this.lastIndexOf(x,fromIndex);
+   @:extern inline public function copy() : VirtualArray return this.copy();
+   @:extern inline public function iterator() : Iterator<Dynamic> return this.iterator();
+   @:extern inline public function map<S>( f : Dynamic -> S ) : VirtualArray return this.map(f);
+   @:extern inline public function filter( f : Dynamic -> Bool ) : VirtualArray return this.filter(f);
+}
 
 

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

@@ -479,6 +479,7 @@ class Bytes {
 		#end
 		#end
 	}
 	}
 
 
+	@:pure
 	public static function ofString( s : String ) : Bytes {
 	public static function ofString( s : String ) : Bytes {
 		#if neko
 		#if neko
 		return new Bytes(s.length,untyped __dollar__ssub(s.__s,0,s.length));
 		return new Bytes(s.length,untyped __dollar__ssub(s.__s,0,s.length));

+ 7 - 7
std/js/Boot.hx

@@ -27,7 +27,7 @@ class ArrayBuffer {
 
 
 	public var byteLength : Int;
 	public var byteLength : Int;
 	var a : Array<Int>;
 	var a : Array<Int>;
-	
+
 	public function new( ?a : Dynamic ) {
 	public function new( ?a : Dynamic ) {
 		if( Std.is(a,Array) ) {
 		if( Std.is(a,Array) ) {
 			this.a = a;
 			this.a = a;
@@ -40,17 +40,17 @@ class ArrayBuffer {
 			byteLength = len;
 			byteLength = len;
 		}
 		}
 	}
 	}
-	
+
 	public function slice(begin,?end) {
 	public function slice(begin,?end) {
 		return new ArrayBuffer(a.slice(begin,end));
 		return new ArrayBuffer(a.slice(begin,end));
 	}
 	}
-	
+
 	static function sliceImpl(begin,?end) {
 	static function sliceImpl(begin,?end) {
-		var u = new js.html.Uint8Array(untyped __js__('this'), begin, end == null ? null : end - begin);
-        var result = new js.html.ArrayBuffer(u.byteLength);
-        var resultArray = new js.html.Uint8Array(result);
+		var u = new js.html.Uint8Array(js.Lib.nativeThis, begin, end == null ? null : end - begin);
+		var result = new js.html.ArrayBuffer(u.byteLength);
+		var resultArray = new js.html.Uint8Array(result);
 		resultArray.set(u);
 		resultArray.set(u);
-        return result;
+		return result;
 	}
 	}
 
 
 	static function __init__() untyped {
 	static function __init__() untyped {

+ 8 - 8
std/js/html/compat/Float32Array.hx

@@ -22,6 +22,8 @@
 package js.html.compat;
 package js.html.compat;
 
 
 #if !nodejs
 #if !nodejs
+import js.Lib.nativeThis;
+
 @:keep
 @:keep
 class Float32Array {
 class Float32Array {
 
 
@@ -45,7 +47,7 @@ class Float32Array {
 			arr = [];
 			arr = [];
 			// decode buffer
 			// decode buffer
 			for( i in 0...length ) {
 			for( i in 0...length ) {
-				var val = untyped buffer.a[offset++] | (buffer.a[offset++] << 8) | (buffer.a[offset++] << 16) | (buffer.a[offset++] << 24);  
+				var val = untyped buffer.a[offset++] | (buffer.a[offset++] << 8) | (buffer.a[offset++] << 16) | (buffer.a[offset++] << 24);
 				arr.push(haxe.io.FPHelper.i32ToFloat(val));
 				arr.push(haxe.io.FPHelper.i32ToFloat(val));
 			}
 			}
 			untyped {
 			untyped {
@@ -79,26 +81,24 @@ class Float32Array {
 	}
 	}
 
 
 	static function _set( ?arg : Dynamic, ?offset : Int ) {
 	static function _set( ?arg : Dynamic, ?offset : Int ) {
-		var t : Dynamic = untyped __js__("this");
 		if( Std.is(arg.buffer,ArrayBuffer) ) {
 		if( Std.is(arg.buffer,ArrayBuffer) ) {
 			var a : Array<Int> = arg;
 			var a : Array<Int> = arg;
-			if( arg.byteLength + offset > t.byteLength )
+			if( arg.byteLength + offset > nativeThis.byteLength )
 				throw "set() outside of range";
 				throw "set() outside of range";
 			for( i in 0...arg.byteLength )
 			for( i in 0...arg.byteLength )
-				t[i + offset] = a[i];
+				nativeThis[i + offset] = a[i];
 		} else if( Std.is(arg,Array) ) {
 		} else if( Std.is(arg,Array) ) {
 			var a : Array<Int> = arg;
 			var a : Array<Int> = arg;
-			if( a.length + offset > t.byteLength )
+			if( a.length + offset > nativeThis.byteLength )
 				throw "set() outside of range";
 				throw "set() outside of range";
 			for( i in 0...a.length )
 			for( i in 0...a.length )
-				t[i + offset] = a[i];
+				nativeThis[i + offset] = a[i];
 		} else
 		} else
 			throw "TODO";
 			throw "TODO";
 	}
 	}
 
 
 	static function _subarray( start : Int, ?end : Int ) {
 	static function _subarray( start : Int, ?end : Int ) {
-		var t : Dynamic = untyped __js__("this");
-		var a = _new(t.slice(start,end));
+		var a = _new(nativeThis.slice(start,end));
 		a.byteOffset = start * 4;
 		a.byteOffset = start * 4;
 		return a;
 		return a;
 	}
 	}

+ 7 - 7
std/js/html/compat/Float64Array.hx

@@ -22,6 +22,8 @@
 package js.html.compat;
 package js.html.compat;
 
 
 #if !nodejs
 #if !nodejs
+import js.Lib.nativeThis;
+
 @:keep
 @:keep
 class Float64Array {
 class Float64Array {
 
 
@@ -86,26 +88,24 @@ class Float64Array {
 	}
 	}
 
 
 	static function _set( ?arg : Dynamic, ?offset : Int ) {
 	static function _set( ?arg : Dynamic, ?offset : Int ) {
-		var t : Dynamic = untyped __js__("this");
 		if( Std.is(arg.buffer,ArrayBuffer) ) {
 		if( Std.is(arg.buffer,ArrayBuffer) ) {
 			var a : Array<Int> = arg;
 			var a : Array<Int> = arg;
-			if( arg.byteLength + offset > t.byteLength )
+			if( arg.byteLength + offset > nativeThis.byteLength )
 				throw "set() outside of range";
 				throw "set() outside of range";
 			for( i in 0...arg.byteLength )
 			for( i in 0...arg.byteLength )
-				t[i + offset] = a[i];
+				nativeThis[i + offset] = a[i];
 		} else if( Std.is(arg,Array) ) {
 		} else if( Std.is(arg,Array) ) {
 			var a : Array<Int> = arg;
 			var a : Array<Int> = arg;
-			if( a.length + offset > t.byteLength )
+			if( a.length + offset > nativeThis.byteLength )
 				throw "set() outside of range";
 				throw "set() outside of range";
 			for( i in 0...a.length )
 			for( i in 0...a.length )
-				t[i + offset] = a[i];
+				nativeThis[i + offset] = a[i];
 		} else
 		} else
 			throw "TODO";
 			throw "TODO";
 	}
 	}
 
 
 	static function _subarray( start : Int, ?end : Int ) {
 	static function _subarray( start : Int, ?end : Int ) {
-		var t : Dynamic = untyped __js__("this");
-		var a = _new(t.slice(start,end));
+		var a = _new(nativeThis.slice(start,end));
 		a.byteOffset = start * 8;
 		a.byteOffset = start * 8;
 		return a;
 		return a;
 	}
 	}

+ 7 - 7
std/js/html/compat/Uint8Array.hx

@@ -22,6 +22,8 @@
 package js.html.compat;
 package js.html.compat;
 
 
 #if !nodejs
 #if !nodejs
+import js.Lib.nativeThis;
+
 @:keep
 @:keep
 class Uint8Array {
 class Uint8Array {
 
 
@@ -70,26 +72,24 @@ class Uint8Array {
 	}
 	}
 
 
 	static function _set( ?arg : Dynamic, ?offset : Int ) {
 	static function _set( ?arg : Dynamic, ?offset : Int ) {
-		var t : Dynamic = untyped __js__("this");
 		if( Std.is(arg.buffer,ArrayBuffer) ) {
 		if( Std.is(arg.buffer,ArrayBuffer) ) {
 			var a : Array<Int> = arg;
 			var a : Array<Int> = arg;
-			if( arg.byteLength + offset > t.byteLength )
+			if( arg.byteLength + offset > nativeThis.byteLength )
 				throw "set() outside of range";
 				throw "set() outside of range";
 			for( i in 0...arg.byteLength )
 			for( i in 0...arg.byteLength )
-				t[i + offset] = a[i];
+				nativeThis[i + offset] = a[i];
 		} else if( Std.is(arg,Array) ) {
 		} else if( Std.is(arg,Array) ) {
 			var a : Array<Int> = arg;
 			var a : Array<Int> = arg;
-			if( a.length + offset > t.byteLength )
+			if( a.length + offset > nativeThis.byteLength )
 				throw "set() outside of range";
 				throw "set() outside of range";
 			for( i in 0...a.length )
 			for( i in 0...a.length )
-				t[i + offset] = a[i];
+				nativeThis[i + offset] = a[i];
 		} else
 		} else
 			throw "TODO";
 			throw "TODO";
 	}
 	}
 
 
 	static function _subarray( start : Int, ?end : Int ) {
 	static function _subarray( start : Int, ?end : Int ) {
-		var t : Dynamic = untyped __js__("this");
-		var a = _new(t.slice(start,end));
+		var a = _new(nativeThis.slice(start,end));
 		a.byteOffset = start;
 		a.byteOffset = start;
 		return a;
 		return a;
 	}
 	}

+ 19 - 19
std/php/_std/haxe/ds/StringMap.hx

@@ -26,7 +26,6 @@ private typedef TravisConfig = {
 	var Java = "java";
 	var Java = "java";
 	var Cs = "cs";
 	var Cs = "cs";
 	var Python = "python";
 	var Python = "python";
-	var Hl = "hl";
 	var ThirdParty = "third-party";
 	var ThirdParty = "third-party";
 }
 }
 
 
@@ -778,9 +777,18 @@ class RunCi {
 		for (test in tests) {
 		for (test in tests) {
 			infoMsg('Now test $test');
 			infoMsg('Now test $test');
 			changeDirectory(unitDir);
 			changeDirectory(unitDir);
+
+			var args = switch (ci) {
+				case TravisCI:
+					["-D","travis"];
+				case AppVeyor:
+					["-D","appveyor"];
+				case _:
+					[];
+			}
 			switch (test) {
 			switch (test) {
 				case Macro:
 				case Macro:
-					runCommand("haxe", ["compile-macro.hxml"]);
+					runCommand("haxe", ["compile-macro.hxml"].concat(args));
 
 
 					changeDirectory(miscDir);
 					changeDirectory(miscDir);
 					getCsDependencies();
 					getCsDependencies();
@@ -809,7 +817,7 @@ class RunCi {
 							// runCommand("haxe", ["compile-macro.hxml"]);
 							// runCommand("haxe", ["compile-macro.hxml"]);
 					}
 					}
 				case Neko:
 				case Neko:
-					runCommand("haxe", ["compile-neko.hxml", "-D", "dump", "-D", "dump_ignore_var_ids"]);
+					runCommand("haxe", ["compile-neko.hxml", "-D", "dump", "-D", "dump_ignore_var_ids"].concat(args));
 					runCommand("neko", ["bin/unit.n"]);
 					runCommand("neko", ["bin/unit.n"]);
 
 
 					changeDirectory(sysDir);
 					changeDirectory(sysDir);
@@ -817,12 +825,6 @@ class RunCi {
 					runCommand("neko", ["bin/neko/sys.n"]);
 					runCommand("neko", ["bin/neko/sys.n"]);
 				case Php:
 				case Php:
 					getPhpDependencies();
 					getPhpDependencies();
-					var args = switch (ci) {
-						case TravisCI:
-							["-D","travis"];
-						case _:
-							[];
-					}
 					runCommand("haxe", ["compile-php.hxml"].concat(args));
 					runCommand("haxe", ["compile-php.hxml"].concat(args));
 					runCommand("php", ["bin/php/index.php"]);
 					runCommand("php", ["bin/php/index.php"]);
 
 
@@ -832,7 +834,7 @@ class RunCi {
 				case Python:
 				case Python:
 					var pys = getPythonDependencies();
 					var pys = getPythonDependencies();
 
 
-					runCommand("haxe", ["compile-python.hxml"]);
+					runCommand("haxe", ["compile-python.hxml"].concat(args));
 					for (py in pys) {
 					for (py in pys) {
 						runCommand(py, ["bin/unit.py"]);
 						runCommand(py, ["bin/unit.py"]);
 					}
 					}
@@ -850,7 +852,7 @@ class RunCi {
 					}
 					}
 				case Cpp:
 				case Cpp:
 					getCppDependencies();
 					getCppDependencies();
-					runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M32"]);
+					runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M32"].concat(args));
 					runCpp("bin/cpp/Test-debug", []);
 					runCpp("bin/cpp/Test-debug", []);
 
 
 					switch (ci) {
 					switch (ci) {
@@ -858,7 +860,7 @@ class RunCi {
 							//save time...
 							//save time...
 						case _:
 						case _:
 							runCommand("rm", ["-rf", "cpp"]);
 							runCommand("rm", ["-rf", "cpp"]);
-							runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M64"]);
+							runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M64"].concat(args));
 							runCpp("bin/cpp/Test-debug", []);
 							runCpp("bin/cpp/Test-debug", []);
 					}
 					}
 
 
@@ -880,7 +882,7 @@ class RunCi {
 						for (unflatten in [[], ["-D", "js-unflatten"]])
 						for (unflatten in [[], ["-D", "js-unflatten"]])
 						for (classic in   [[], ["-D", "js-classic"]])
 						for (classic in   [[], ["-D", "js-classic"]])
 						{
 						{
-							var extras = [].concat(es5).concat(unflatten).concat(classic);
+							var extras = args.concat(es5).concat(unflatten).concat(classic);
 
 
 							runCommand("haxe", ["compile-js.hxml"].concat(extras));
 							runCommand("haxe", ["compile-js.hxml"].concat(extras));
 
 
@@ -937,10 +939,10 @@ class RunCi {
 					runCommand("haxe", ["run.hxml"]);
 					runCommand("haxe", ["run.hxml"]);
 				case Java:
 				case Java:
 					getJavaDependencies();
 					getJavaDependencies();
-					runCommand("haxe", ["compile-java.hxml"]);
+					runCommand("haxe", ["compile-java.hxml"].concat(args));
 					runCommand("java", ["-jar", "bin/java/Test-Debug.jar"]);
 					runCommand("java", ["-jar", "bin/java/Test-Debug.jar"]);
 
 
-					runCommand("haxe", ["compile-java.hxml","-dce","no"]);
+					runCommand("haxe", ["compile-java.hxml","-dce","no"].concat(args));
 					runCommand("java", ["-jar", "bin/java/Test-Debug.jar"]);
 					runCommand("java", ["-jar", "bin/java/Test-Debug.jar"]);
 
 
 					changeDirectory(sysDir);
 					changeDirectory(sysDir);
@@ -1006,7 +1008,7 @@ class RunCi {
 
 
 				case Flash9:
 				case Flash9:
 					setupFlashPlayerDebugger();
 					setupFlashPlayerDebugger();
-					runCommand("haxe", ["compile-flash9.hxml", "-D", "fdb", "-D", "dump", "-D", "dump_ignore_var_ids"]);
+					runCommand("haxe", ["compile-flash9.hxml", "-D", "fdb", "-D", "dump", "-D", "dump_ignore_var_ids"].concat(args));
 					var success = runFlash("bin/unit9.swf");
 					var success = runFlash("bin/unit9.swf");
 					if (!success)
 					if (!success)
 						Sys.exit(1);
 						Sys.exit(1);
@@ -1029,12 +1031,10 @@ class RunCi {
 						runCommand("mxmlc", ["--version"]);
 						runCommand("mxmlc", ["--version"]);
 					}
 					}
 
 
-					runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
+					runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"].concat(args));
 					var success = runFlash("bin/unit9_as3.swf");
 					var success = runFlash("bin/unit9_as3.swf");
 					if (!success)
 					if (!success)
 						Sys.exit(1);
 						Sys.exit(1);
-				case Hl:
-					runCommand("haxe", ["compile-hl.hxml"]);
 				case ThirdParty:
 				case ThirdParty:
 					getPhpDependencies();
 					getPhpDependencies();
 					getJavaDependencies();
 					getJavaDependencies();

+ 1 - 0
tests/misc/projects/Issue3361/compile1-fail.hxml.stderr

@@ -1,3 +1,4 @@
 Main.hx:5: lines 5-8 : Field v has different type than in I
 Main.hx:5: lines 5-8 : Field v has different type than in I
+Main.hx:2: characters 8-28 : Interface field is defined here
 Main.hx:5: lines 5-8 : String -> Void should be Dynamic -> Void
 Main.hx:5: lines 5-8 : String -> Void should be Dynamic -> Void
 Main.hx:5: lines 5-8 : String should be Dynamic
 Main.hx:5: lines 5-8 : String should be Dynamic

+ 1 - 0
tests/misc/projects/Issue3361/compile2-fail.hxml.stderr

@@ -1,3 +1,4 @@
 Main2.hx:6: characters 16-45 : Field f has different type than in I
 Main2.hx:6: characters 16-45 : Field f has different type than in I
+Main2.hx:2: characters 16-43 : Interface field is defined here
 Main2.hx:6: characters 16-45 : s : String -> Void should be d : Dynamic -> Void
 Main2.hx:6: characters 16-45 : s : String -> Void should be d : Dynamic -> Void
 Main2.hx:6: characters 16-45 : String should be Dynamic
 Main2.hx:6: characters 16-45 : String should be Dynamic

+ 2 - 1
tests/misc/projects/Issue3417/compile-fail.hxml.stderr

@@ -1,2 +1,3 @@
 Main.hx:6: characters 11-26 : Field f has different type than in I
 Main.hx:6: characters 11-26 : Field f has different type than in I
-Main.hx:6: characters 11-26 : Different number of function arguments
+Main.hx:2: characters 4-27 : Interface field is defined here
+Main.hx:6: characters 11-26 : Different number of function arguments

+ 1 - 0
tests/misc/projects/Issue4378/compile-fail.hxml.stderr

@@ -1,3 +1,4 @@
 Main.hx:5: lines 5-7 : Field test has different type than in I
 Main.hx:5: lines 5-7 : Field test has different type than in I
+Main.hx:16: characters 1-31 : Interface field is defined here
 Main.hx:5: lines 5-7 : s : String -> Void should be s : Dynamic -> Void
 Main.hx:5: lines 5-7 : s : String -> Void should be s : Dynamic -> Void
 Main.hx:5: lines 5-7 : String should be Dynamic
 Main.hx:5: lines 5-7 : String should be Dynamic

+ 9 - 0
tests/optimization/src/TestJs.hx

@@ -548,6 +548,15 @@ class TestJs {
 		a[i++] = i++;
 		a[i++] = i++;
 	}
 	}
 
 
+	@:js('
+		var i = 5;
+		while(--i >= 0) TestJs["use"](i);
+	')
+	static function testPrefixRebuilding() {
+		var i:Int = 5;
+		while (--i >= 0) use(i);
+	}
+
 	static inline function inlineCall<S, T>(d1:S, d2:T) {
 	static inline function inlineCall<S, T>(d1:S, d2:T) {
 		return call(d2, d1);
 		return call(d2, d1);
 	}
 	}

+ 9 - 12
tests/unit/src/unit/Test.hx

@@ -252,7 +252,7 @@ class Test {
 	}
 	}
 
 
 	static function resetTimer() {
 	static function resetTimer() {
-		#if (neko || php || cpp || java || cs || python || hl)
+		#if (neko || php || cpp || java || cs || python)
 		#else
 		#else
 		if( timer != null ) timer.stop();
 		if( timer != null ) timer.stop();
 		timer = new haxe.Timer(30000);
 		timer = new haxe.Timer(30000);
@@ -355,17 +355,14 @@ class Test {
 		#end
 		#end
 
 
 		// SPOD tests
 		// SPOD tests
-		#if ( (neko || (php && (travis || php_sqlite)) || java || cpp || (cs && travis)) && !macro && !interp)
-		#if ( travis && !(cpp || cs) )
-		if (Sys.getEnv("CI") != null && switch (Sys.systemName()) { case "Linux"|"Mac": true; case _: false; })
-		{
-			classes.push(new TestSpod(sys.db.Mysql.connect({
-				host : "localhost",
-				user : "travis",
-				pass : "",
-				port : 3306,
-				database : "haxe_test" })));
-		}
+		#if ( (neko || (php && (travis || appveyor || php_sqlite)) || java || cpp || (cs && (travis || appveyor))) && !macro && !interp)
+		#if ( (travis || appveyor) && !(cpp || cs) )
+		classes.push(new TestSpod(sys.db.Mysql.connect({
+			host : "localhost",
+			user : "travis",
+			pass : "",
+			port : 3306,
+			database : "haxe_test" })));
 		#end
 		#end
 		if (verbose)
 		if (verbose)
 			logVerbose("Setup sqlite");
 			logVerbose("Setup sqlite");

+ 4 - 4
tests/unit/src/unit/issues/Issue4695.hx

@@ -5,16 +5,16 @@ class Issue4695 extends unit.Test {
 	function eqCheck<T>(v1:T, v2:T) {
 	function eqCheck<T>(v1:T, v2:T) {
 		return v1 == v2;
 		return v1 == v2;
 	}
 	}
-
+	
 	public function testNull() {
 	public function testNull() {
 		f("" == null);
 		f("" == null);
 		f(eqCheck("", null));
 		f(eqCheck("", null));
-		#if !(cpp || flash9 || as3 || java || cs || hl)
+		#if !(cpp || flash9 || as3 || java || cs)
 		f(false == null);
 		f(false == null);
 		f(eqCheck(false, null));
 		f(eqCheck(false, null));
 		#end
 		#end
 	}
 	}
-
+	
 	#if php
 	#if php
 	public function testNativeArray() {
 	public function testNativeArray() {
 		var a1 = (untyped __php__)('array("f1" => 1, "f2" => 2, "f3" => 3)');
 		var a1 = (untyped __php__)('array("f1" => 1, "f2" => 2, "f3" => 3)');
@@ -23,5 +23,5 @@ class Issue4695 extends unit.Test {
 		f(eqCheck(a1, a2));
 		f(eqCheck(a1, a2));
 	}
 	}
 	#end
 	#end
-
+	
 }
 }

+ 18 - 0
tests/unit/src/unit/issues/Issue4798.hx

@@ -0,0 +1,18 @@
+package unit.issues;
+
+private abstract Lazy<T>(Void->T) {
+	inline function new(r) this = r;
+
+	@:to public inline function get():T
+		return (this)();
+
+	@:from static inline function ofConst<T>(c:T)
+		return new Lazy(function () return c);
+}
+
+class Issue4798 extends Test {
+	public static var INIT: Lazy<String> = 'b';
+	function test() {
+		eq("b", (INIT: String));
+	}
+}

+ 17 - 1
tests/unit/src/unitstd/EvaluationOrder.unit.hx

@@ -129,4 +129,20 @@ function f2() {
 
 
 var end = begin();
 var end = begin();
 f1()(f2());
 f1()(f2());
-eq(end(), "1_2");
+eq(end(), "1_2");
+
+var d:Dynamic = { f1: f1 };
+
+function f3() {
+	buf.push(3);
+	d.f1 = function(i) {
+		buf.push(4);
+		return 4;
+	}
+	return 3;
+}
+
+var end = begin();
+d.f1()(f3());
+d.f1(f2());
+eq(end(), "1_3_2_4");

+ 2 - 0
typeload.ml

@@ -888,6 +888,7 @@ let check_overriding ctx c =
 				with
 				with
 					Unify_error l ->
 					Unify_error l ->
 						display_error ctx ("Field " ^ i ^ " overloads parent class with different or incomplete type") p;
 						display_error ctx ("Field " ^ i ^ " overloads parent class with different or incomplete type") p;
+						display_error ctx ("Base field is defined here") f2.cf_pos;
 						display_error ctx (error_msg (Unify l)) p;
 						display_error ctx (error_msg (Unify l)) p;
 			with
 			with
 				Not_found ->
 				Not_found ->
@@ -973,6 +974,7 @@ let rec check_interface ctx c intf params =
 				Unify_error l ->
 				Unify_error l ->
 					if not (Meta.has Meta.CsNative c.cl_meta && c.cl_extern) then begin
 					if not (Meta.has Meta.CsNative c.cl_meta && c.cl_extern) then begin
 						display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p;
 						display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p;
+						display_error ctx ("Interface field is defined here") f.cf_pos;
 						display_error ctx (error_msg (Unify l)) p;
 						display_error ctx (error_msg (Unify l)) p;
 					end
 					end
 		with
 		with

+ 3 - 19
typer.ml

@@ -671,7 +671,6 @@ let rec unify_call_args' ctx el args r callp inline force_inline =
 	let in_call_args = ctx.in_call_args in
 	let in_call_args = ctx.in_call_args in
 	ctx.in_call_args <- true;
 	ctx.in_call_args <- true;
 	let call_error err p =
 	let call_error err p =
-		ctx.in_call_args <- in_call_args;
 		raise (Error (Call_error err,p))
 		raise (Error (Call_error err,p))
 	in
 	in
 	let arg_error ul name opt p =
 	let arg_error ul name opt p =
@@ -698,7 +697,7 @@ let rec unify_call_args' ctx el args r callp inline force_inline =
 	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in *)
 	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in *)
 	let type_against t e =
 	let type_against t e =
 		let e = type_expr ctx e (WithType t) in
 		let e = type_expr ctx e (WithType t) in
-		(try Codegen.AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> ctx.in_call_args <- in_call_args; raise (WithTypeError (l,p)))
+		(try Codegen.AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> raise (WithTypeError (l,p)))
 	in
 	in
 	let rec loop el args = match el,args with
 	let rec loop el args = match el,args with
 		| [],[] ->
 		| [],[] ->
@@ -739,7 +738,7 @@ let rec unify_call_args' ctx el args r callp inline force_inline =
 						arg_error ul name false p
 						arg_error ul name false p
 			end
 			end
 	in
 	in
-	let el = loop el args in
+	let el = try loop el args with exc -> ctx.in_call_args <- in_call_args; raise exc; in
 	ctx.in_call_args <- in_call_args;
 	ctx.in_call_args <- in_call_args;
 	el,TFun(args,r)
 	el,TFun(args,r)
 
 
@@ -3267,22 +3266,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 					)
 					)
 				) in
 				) in
 				let e2 = type_expr ctx e2 NoValue in
 				let e2 = type_expr ctx e2 NoValue in
-				(try
-					Optimizer.optimize_for_loop_iterator ctx i e1 e2 p
-				with Exit ->
-					if ctx.com.config.pf_for_to_while then begin
-						let v = gen_local ctx e1.etype in
-						mk (TBlock [
-							mk (TVar (v,Some e1)) ctx.t.tvoid p;
-							mk (TWhile (build_call ctx (type_field ctx (mk (TLocal v) v.v_type p) "hasNext" p MCall) [] Value p,
-								mk (TBlock [
-									mk (TVar (i, Some (build_call ctx (type_field ctx (mk (TLocal v) v.v_type p) "next" p MCall) [] Value p))) ctx.t.tvoid p;
-									e2
-								]) ctx.t.tvoid p
- 							,NormalWhile)) ctx.t.tvoid p;
-						]) ctx.t.tvoid p
-					end else
-						mk (TFor (i,e1,e2)) ctx.t.tvoid p)
+				(try Optimizer.optimize_for_loop_iterator ctx i e1 e2 p with Exit -> mk (TFor (i,e1,e2)) ctx.t.tvoid p)
 		) in
 		) in
 		ctx.in_loop <- old_loop;
 		ctx.in_loop <- old_loop;
 		old_locals();
 		old_locals();