Răsfoiți Sursa

Merge pull request #2877 from HaxeFoundation/development

3.1.3
Simon Krajewski 11 ani în urmă
părinte
comite
7be30670b2

+ 7 - 1
.travis.yml

@@ -17,6 +17,11 @@ env:
     - TARGET=java
     - TARGET=java
     - TARGET=cs
     - TARGET=cs
     - TARGET=flash8
     - TARGET=flash8
+    - TARGET=polygonal-ds
+    - TARGET=flambe
+    - TARGET=hxtemplo
+    - TARGET=munit
+    - TARGET=openfl-samples
 
 
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true
@@ -35,5 +40,6 @@ script:
   - sudo make install
   - sudo make install
   - cd tests/
   - cd tests/
   - mkdir ~/haxelib && haxelib setup ~/haxelib
   - mkdir ~/haxelib && haxelib setup ~/haxelib
+  - haxelib git hx-yaml https://github.com/mikestead/hx-yaml master src
   - haxe -version
   - haxe -version
-  - haxe -main RunTravis --interp
+  - haxe -main RunTravis -lib hx-yaml --interp

+ 83 - 2
codegen.ml

@@ -770,10 +770,10 @@ module Abstract = struct
 				{e with etype = m}
 				{e with etype = m}
 			| TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->
 			| TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->
 				begin match follow e1.etype with
 				begin match follow e1.etype with
-					| TAbstract({a_impl = Some c} as a,_) ->
+					| TAbstract({a_impl = Some c} as a,tl) ->
 						begin try
 						begin try
 							let cf = PMap.find "toString" c.cl_statics in
 							let cf = PMap.find "toString" c.cl_statics in
-							make_static_call ctx c cf a [] [e1] ctx.t.tstring e.epos
+							make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos
 						with Not_found ->
 						with Not_found ->
 							e
 							e
 						end
 						end
@@ -1621,3 +1621,84 @@ module UnificationCallback = struct
 			| _ ->
 			| _ ->
 				check (Type.map_expr (run f) e)
 				check (Type.map_expr (run f) e)
 end;;
 end;;
+
+module DeprecationCheck = struct
+
+	let curclass = ref null_class
+
+	let warned_positions = Hashtbl.create 0
+
+	let print_deprecation_message com meta s p_usage =
+		let s = match meta with
+			| _,[EConst(String s),_],_ -> s
+			| _ -> Printf.sprintf "Usage of this %s is deprecated" s
+		in
+		if not (Hashtbl.mem warned_positions p_usage) then begin
+			Hashtbl.replace warned_positions p_usage true;
+			com.warning s p_usage;
+		end
+
+	let check_meta com meta s p_usage =
+		try
+			print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage;
+		with Not_found ->
+			()
+
+	let check_cf com cf p = check_meta com cf.cf_meta "field" p
+
+	let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p
+
+	let check_enum com en p = check_meta com en.e_meta "enum" p
+
+	let check_ef com ef p = check_meta com ef.ef_meta "enum field" p
+
+	let check_typedef com t p = check_meta com t.t_meta "typedef" p
+
+	let check_module_type com mt p = match mt with
+		| TClassDecl c -> check_class com c p
+		| TEnumDecl en -> check_enum com en p
+		| _ -> ()
+
+	let run com =
+		let rec expr e = match e.eexpr with
+			| TField(e1,fa) ->
+				expr e1;
+				begin match fa with
+					| FStatic(c,cf) | FInstance(c,cf) ->
+						check_class com c e.epos;
+						check_cf com cf e.epos
+					| FAnon cf ->
+						check_cf com cf e.epos
+					| FClosure(co,cf) ->
+						(match co with None -> () | Some c -> check_class com c e.epos);
+						check_cf com cf e.epos
+					| FEnum(en,ef) ->
+						check_enum com en e.epos;
+						check_ef com ef e.epos;
+					| _ ->
+						()
+				end
+			| TNew(c,_,el) ->
+				List.iter expr el;
+				check_class com c e.epos;
+				(match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos)
+			| TTypeExpr(mt) | TCast(_,Some mt) ->
+				check_module_type com mt e.epos
+			| TMeta((Meta.Deprecated,_,_) as meta,e1) ->
+				print_deprecation_message com meta "field" e1.epos;
+				expr e1;
+			| _ ->
+				Type.iter expr e
+		in
+		List.iter (fun t -> match t with
+			| TClassDecl c ->
+				curclass := c;
+				let field cf = match cf.cf_expr with None -> () | Some e -> expr e in
+				(match c.cl_constructor with None -> () | Some cf -> field cf);
+				(match c.cl_init with None -> () | Some e -> expr e);
+				List.iter field c.cl_ordered_statics;
+				List.iter field c.cl_ordered_fields;
+			| _ ->
+				()
+		) com.types
+end

+ 5 - 3
common.ml

@@ -171,7 +171,6 @@ module Define = struct
 		| Dce
 		| Dce
 		| DceDebug
 		| DceDebug
 		| Debug
 		| Debug
-		| DeprecationWarnings
 		| Display
 		| Display
 		| DllExport
 		| DllExport
 		| DllImport
 		| DllImport
@@ -201,7 +200,9 @@ module Define = struct
 		| NetTarget
 		| NetTarget
 		| NoCompilation
 		| NoCompilation
 		| NoCOpt
 		| NoCOpt
+		| NoDeprecationWarnings
 		| NoFlashOverride
 		| NoFlashOverride
+		| NoDebug
 		| NoInline
 		| NoInline
 		| NoOpt
 		| NoOpt
 		| NoPatternMatching
 		| NoPatternMatching
@@ -243,7 +244,6 @@ module Define = struct
 		| Dce -> ("dce","The current DCE mode")
 		| Dce -> ("dce","The current DCE mode")
 		| DceDebug -> ("dce_debug","Show DCE log")
 		| DceDebug -> ("dce_debug","Show DCE log")
 		| Debug -> ("debug","Activated when compiling with -debug")
 		| Debug -> ("debug","Activated when compiling with -debug")
-		| DeprecationWarnings -> ("deprecation-warnings","Warn if fields annotated with @:deprecated are used")
 		| Display -> ("display","Activated during completion")
 		| Display -> ("display","Activated during completion")
 		| DllExport -> ("dll_export", "GenCPP experimental linking")
 		| DllExport -> ("dll_export", "GenCPP experimental linking")
 		| DllImport -> ("dll_import", "GenCPP experimental linking")
 		| DllImport -> ("dll_import", "GenCPP experimental linking")
@@ -273,6 +273,8 @@ module Define = struct
 		| NetworkSandbox -> ("network-sandbox","Use local network sandbox instead of local file access one")
 		| NetworkSandbox -> ("network-sandbox","Use local network sandbox instead of local file access one")
 		| NoCompilation -> ("no-compilation","Disable CPP final compilation")
 		| NoCompilation -> ("no-compilation","Disable CPP final compilation")
 		| NoCOpt -> ("no_copt","Disable completion optimization (for debug purposes)")
 		| NoCOpt -> ("no_copt","Disable completion optimization (for debug purposes)")
+		| NoDebug -> ("no_debug","Remove all debug macros from cpp output")
+		| NoDeprecationWarnings -> ("no-deprecation-warnings","Do not warn if fields annotated with @:deprecated are used")
 		| NoFlashOverride -> ("no-flash-override", "Change overrides on some basic classes into HX suffixed methods, flash only")
 		| NoFlashOverride -> ("no-flash-override", "Change overrides on some basic classes into HX suffixed methods, flash only")
 		| NoOpt -> ("no_opt","Disable optimizations")
 		| NoOpt -> ("no_opt","Disable optimizations")
 		| NoPatternMatching -> ("no_pattern_matching","Disable pattern matching")
 		| NoPatternMatching -> ("no_pattern_matching","Disable pattern matching")
@@ -890,7 +892,7 @@ let find_file ctx f =
 		(match r with
 		(match r with
 		| None -> raise Not_found
 		| None -> raise Not_found
 		| Some f -> f)
 		| Some f -> f)
-		
+
 
 
 let get_full_path f = try Extc.get_full_path f with _ -> f
 let get_full_path f = try Extc.get_full_path f with _ -> f
 
 

+ 22 - 1
extra/CHANGES.txt

@@ -1,4 +1,25 @@
-2014-03-39: 3.1.2
+2014-04-13: 3.1.3
+
+	Bugfixes:
+
+	all : fixed handling of abstract variance
+	flash : ensure correct endianess in haxe.io.BytesBuffer
+	cpp : fixed issue involving class paths with spaces
+	php : fixed >>>
+	macro : fixed haxe.macro.Compiler.keep
+
+	General improvements and optimizations:
+
+	all : give @:deprecated warnings by default, allow -D no-deprecation-warnings
+	cpp : optimized Vector implementation
+
+	Standard Library:
+
+	all : renamed Bytes.readDouble/Float to getDouble/Float to avoid inheritance issues
+	all : deprecated Bytes.readString in favor of getString
+	all : added pretty-printing to haxe.format.JsonPrinter (and haxe.Json)
+
+2014-03-29: 3.1.2
 
 
 	Bugfixes:
 	Bugfixes:
 
 

+ 2 - 68
filters.ml

@@ -797,72 +797,6 @@ let rename_local_vars com e =
 	loop e;
 	loop e;
 	e
 	e
 
 
-let check_deprecation com =
-	let curclass = ref null_class in
-	let definition_positions = (Common.defined_value_safe com Define.DeprecationWarnings) = "def-pos" in
-	let warned_positions = Hashtbl.create 0 in
-	let get_deprecation_message meta s p_usage p_definition =
-		try
-			let s = match Meta.get Meta.Deprecated meta with
-				| _,[EConst(String s),_],_ -> s
-				| _ -> Printf.sprintf "Usage of this %s is deprecated" s
-			in
-			if not (Hashtbl.mem warned_positions p_usage) then begin
-				Hashtbl.replace warned_positions p_usage true;
-				com.warning s p_usage;
-			end;
-			if definition_positions then com.warning "Defined here" p_definition
-		with Not_found ->
-			()
-	in
-	let check_cf cf p = get_deprecation_message cf.cf_meta "field" p cf.cf_pos in
-	let check_class c p = if c != !curclass then get_deprecation_message c.cl_meta "class" p c.cl_pos in
-	let check_enum en p = get_deprecation_message en.e_meta "enum" p en.e_pos in
-	let check_ef ef p = get_deprecation_message ef.ef_meta "enum field" p ef.ef_pos in
-	let check_module_type mt p = match mt with
-		| TClassDecl c -> check_class c p
-		| TEnumDecl en -> check_enum en p
-		| _ -> ()
-	in
-	let rec expr e = match e.eexpr with
-		| TField(e1,fa) ->
-			expr e1;
-			begin match fa with
-				| FStatic(c,cf) | FInstance(c,cf) ->
-					check_class c e.epos;
-					check_cf cf e.epos
-				| FAnon cf ->
-					check_cf cf e.epos
-				| FClosure(co,cf) ->
-					(match co with None -> () | Some c -> check_class c e.epos);
-					check_cf cf e.epos
-				| FEnum(en,ef) ->
-					check_enum en e.epos;
-					check_ef ef e.epos;
-				| _ ->
-					()
-			end
-		| TNew(c,_,el) ->
-			List.iter expr el;
-			check_class c e.epos;
-			(match c.cl_constructor with None -> () | Some cf -> check_cf cf e.epos)
-		| TTypeExpr(mt) | TCast(_,Some mt) ->
-			check_module_type mt e.epos
-		| _ ->
-			Type.iter expr e
-	in
-	List.iter (fun t -> match t with
-		| TClassDecl c ->
-			curclass := c;
-			let field cf = match cf.cf_expr with None -> () | Some e -> expr e in
-			(match c.cl_constructor with None -> () | Some cf -> field cf);
-			(match c.cl_init with None -> () | Some e -> expr e);
-			List.iter field c.cl_ordered_statics;
-			List.iter field c.cl_ordered_fields;
-		| _ ->
-			()
-	) com.types
-
 let check_unification com e t =
 let check_unification com e t =
 	begin match follow e.etype,follow t with
 	begin match follow e.etype,follow t with
 		| TEnum _,TDynamic _ ->
 		| TEnum _,TDynamic _ ->
@@ -1142,8 +1076,8 @@ let post_process_end() =
 let run com tctx main =
 let run com tctx main =
 	if com.display = DMUsage then
 	if com.display = DMUsage then
 		Codegen.detect_usage com;
 		Codegen.detect_usage com;
-	if Common.defined com Define.DeprecationWarnings then
-		check_deprecation com;
+	if not (Common.defined com Define.NoDeprecationWarnings) then
+		Codegen.DeprecationCheck.run com;
 
 
 	(* PASS 1: general expression filters *)
 	(* PASS 1: general expression filters *)
  	let filters = [
  	let filters = [

+ 18 - 3
gencommon.ml

@@ -5714,6 +5714,9 @@ struct
         mk_cast to_t e)
         mk_cast to_t e)
       | TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from ->
       | TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from ->
         e
         e
+      | TAbstract _, TInst({ cl_kind = KTypeParameter _ }, _)
+      | TInst({ cl_kind = KTypeParameter _ }, _), TAbstract _ ->
+        do_unsafe_cast()
       | TAbstract _, _
       | TAbstract _, _
       | _, TAbstract _ ->
       | _, TAbstract _ ->
         (try
         (try
@@ -7358,6 +7361,14 @@ struct
         let do_field cf cf_type is_static =
         let do_field cf cf_type is_static =
           let get_field ethis = { eexpr = TField (ethis, if is_static then FStatic (cl, cf) else FInstance(cl, cf)); etype = cf_type; epos = pos } in
           let get_field ethis = { eexpr = TField (ethis, if is_static then FStatic (cl, cf) else FInstance(cl, cf)); etype = cf_type; epos = pos } in
           let this = if is_static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in
           let this = if is_static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in
+          let value_local = if is_float then match follow cf_type with
+            | TInst({ cl_kind = KTypeParameter _ }, _) ->
+              mk_cast t_dynamic value_local
+            | _ ->
+              value_local
+            else
+              value_local
+          in
 
 
           let ret =
           let ret =
           {
           {
@@ -7450,7 +7461,7 @@ struct
         let do_field cf cf_type static =
         let do_field cf cf_type static =
           let this = if static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in
           let this = if static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in
           match is_float, follow cf_type with
           match is_float, follow cf_type with
-            | true, TInst( { cl_kind = KTypeParameter _ }, [] ) ->
+            | true, TInst( { cl_kind = KTypeParameter _ }, _ ) ->
               mk_return (mk_cast basic.tfloat (mk_cast t_dynamic (get_field cf cf_type this cl cf.cf_name)))
               mk_return (mk_cast basic.tfloat (mk_cast t_dynamic (get_field cf cf_type this cl cf.cf_name)))
             | _ ->
             | _ ->
               mk_return (maybe_cast (get_field cf cf_type this cl cf.cf_name ))
               mk_return (maybe_cast (get_field cf cf_type this cl cf.cf_name ))
@@ -9154,11 +9165,15 @@ struct
               | (conds,e) :: tl ->
               | (conds,e) :: tl ->
                 { eexpr = TIf(mk_many_cond conds, run e, Some(loop tl)); etype = e.etype; epos = e.epos }
                 { eexpr = TIf(mk_many_cond conds, run e, Some(loop tl)); etype = e.etype; epos = e.epos }
               | [] -> match default with
               | [] -> match default with
-                | None -> gen.gcon.error "Empty switch" e.epos; assert false
+                | None ->
+									raise Exit
                 | Some d -> run d
                 | Some d -> run d
             in
             in
 
 
-            { e with eexpr = TBlock(fst_block @ [loop cases]) }
+						try
+							{ e with eexpr = TBlock(fst_block @ [loop cases]) }
+						with | Exit ->
+							{ e with eexpr = TBlock [] }
           end
           end
         | _ -> Type.map_expr run e
         | _ -> Type.map_expr run e
     in
     in

Fișier diff suprimat deoarece este prea mare
+ 563 - 557
gencpp.ml


+ 2 - 2
gencs.ml

@@ -1055,7 +1055,7 @@ let configure gen =
 						write w " += ";
 						write w " += ";
 						expr_s w ev
 						expr_s w ev
 					end else
 					end else
-						do_call w e []
+						do_call w e [ev]
 				| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "remove_" ->
 				| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "remove_" ->
 					let name = field_name f in
 					let name = field_name f in
 					let propname = String.sub name 7 (String.length name - 7) in
 					let propname = String.sub name 7 (String.length name - 7) in
@@ -1066,7 +1066,7 @@ let configure gen =
 						write w " -= ";
 						write w " -= ";
 						expr_s w ev
 						expr_s w ev
 					end else
 					end else
-						do_call w e []
+						do_call w e [ev]
 				| TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" ->
 				| TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" ->
 					let name = field_name f in
 					let name = field_name f in
 					let propname = String.sub name 4 (String.length name - 4) in
 					let propname = String.sub name 4 (String.length name - 4) in

+ 8 - 2
genjava.ml

@@ -1624,7 +1624,13 @@ let configure gen =
     print w "%s %s %s %s" access (String.concat " " modifiers) clt (change_clname (snd cl.cl_path));
     print w "%s %s %s %s" access (String.concat " " modifiers) clt (change_clname (snd cl.cl_path));
     (* type parameters *)
     (* type parameters *)
     let params, _ = get_string_params cl.cl_types in
     let params, _ = get_string_params cl.cl_types in
-    let cl_p_to_string (c,p) = path_param_s cl.cl_pos (TClassDecl c) c.cl_path p in
+    let cl_p_to_string (c,p) =
+      let p = List.map (fun t -> match follow t with
+        | TMono _ | TDynamic _ -> t_empty
+        | _ -> t) p
+      in
+      path_param_s cl.cl_pos (TClassDecl c) c.cl_path p
+    in
     print w "%s" params;
     print w "%s" params;
     (if is_some cl.cl_super then print w " extends %s" (cl_p_to_string (get cl.cl_super)));
     (if is_some cl.cl_super then print w " extends %s" (cl_p_to_string (get cl.cl_super)));
     (match cl.cl_implements with
     (match cl.cl_implements with
@@ -2455,7 +2461,7 @@ let convert_java_enum ctx p pe =
     ) field.jf_flags;
     ) field.jf_flags;
 
 
     List.iter (function
     List.iter (function
-      | AttrDeprecated -> cff_meta := (Meta.Deprecated, [], p) :: !cff_meta
+      | AttrDeprecated when jc.cpath <> (["java";"util"],"Date") -> cff_meta := (Meta.Deprecated, [], p) :: !cff_meta
       (* TODO: pass anotations as @:meta *)
       (* TODO: pass anotations as @:meta *)
       | AttrVisibleAnnotations ann ->
       | AttrVisibleAnnotations ann ->
         List.iter (function
         List.iter (function

+ 8 - 11
genjs.ml

@@ -1223,7 +1223,7 @@ let generate com =
 
 
 		(* Wrap output in a closure *)
 		(* Wrap output in a closure *)
 		if (anyExposed && (Common.defined com Define.ShallowExpose)) then (
 		if (anyExposed && (Common.defined com Define.ShallowExpose)) then (
-			print ctx "var $hx_exports = {}";
+			print ctx "var $hx_exports = $hx_exports || {}";
 			ctx.separator <- true;
 			ctx.separator <- true;
 			newline ctx
 			newline ctx
 		);
 		);
@@ -1231,18 +1231,15 @@ let generate com =
 		if (anyExposed && not (Common.defined com Define.ShallowExpose)) then print ctx "$hx_exports";
 		if (anyExposed && not (Common.defined com Define.ShallowExpose)) then print ctx "$hx_exports";
 		print ctx ") { \"use strict\"";
 		print ctx ") { \"use strict\"";
 		newline ctx;
 		newline ctx;
-		let rec print_obj { os_fields = fields } = (
-			print ctx "{";
-			concat ctx "," (fun ({ os_name = name } as f) -> print ctx "%s" (name ^ ":"); print_obj f) fields;
-			print ctx "}";
+		let rec print_obj f root = (
+			let path = root ^ "." ^ f.os_name in
+			print ctx "%s = %s || {}" path path;
+			ctx.separator <- true;
+			newline ctx;
+			concat ctx ";" (fun g -> print_obj g path) f.os_fields
 		)
 		)
 		in
 		in
-		List.iter (fun f ->
-			print ctx "$hx_exports.%s = " f.os_name;
-			print_obj f;
-			ctx.separator <- true;
-			newline ctx
-		) exposedObject.os_fields;
+		List.iter (fun f -> print_obj f "$hx_exports") exposedObject.os_fields;
 	end;
 	end;
 
 
 	(* TODO: fix $estr *)
 	(* TODO: fix $estr *)

+ 9 - 2
main.ml

@@ -45,7 +45,7 @@ exception Abort
 exception Completion of string
 exception Completion of string
 
 
 
 
-let version = 3102
+let version = 3103
 let version_major = version / 1000
 let version_major = version / 1000
 let version_minor = (version mod 1000) / 100
 let version_minor = (version mod 1000) / 100
 let version_revision = (version mod 100)
 let version_revision = (version mod 100)
@@ -1362,7 +1362,14 @@ try
 	if not !no_output && file_extension com.file = ext then delete_file com.file;
 	if not !no_output && file_extension com.file = ext then delete_file com.file;
 	List.iter (fun f -> f()) (List.rev (!pre_compilation));
 	List.iter (fun f -> f()) (List.rev (!pre_compilation));
 	if !classes = [([],"Std")] && not !force_typing then begin
 	if !classes = [([],"Std")] && not !force_typing then begin
-		if !cmds = [] && not !did_something then Arg.usage basic_args_spec usage;
+		let help_spec = basic_args_spec @ [
+			("-help", Arg.Unit (fun () -> ()),": show extended help information");
+			("--help", Arg.Unit (fun () -> ()),": show extended help information");
+			("--help-defines", Arg.Unit (fun () -> ()),": print help for all compiler specific defines");
+			("--help-metas", Arg.Unit (fun () -> ()),": print help for all compiler metadatas");
+			("<dot-path>", Arg.Unit (fun () -> ()),": compile the module specified by dot-path");
+		] in
+		if !cmds = [] && not !did_something then Arg.usage help_spec usage;
 	end else begin
 	end else begin
 		ctx.setup();
 		ctx.setup();
 		Common.log com ("Classpath : " ^ (String.concat ";" com.class_path));
 		Common.log com ("Classpath : " ^ (String.concat ";" com.class_path));

+ 5 - 0
optimizer.ml

@@ -507,6 +507,11 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 				let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) ctx.t.tvoid e.epos) vl in
 				let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) ctx.t.tvoid e.epos) vl in
 				mk (TBlock (el_v @ [e])) tret e.epos
 				mk (TBlock (el_v @ [e])) tret e.epos
 		) in
 		) in
+		let inline_meta e meta = match meta with
+			| Meta.Deprecated,_,_ -> mk (TMeta(meta,e)) e.etype e.epos
+			| _ -> e
+		in
+		let e = List.fold_left inline_meta e cf.cf_meta in
 		(* we need to replace type-parameters that were used in the expression *)
 		(* we need to replace type-parameters that were used in the expression *)
 		if not has_params then
 		if not has_params then
 			Some e
 			Some e

+ 29 - 0
std/cpp/NativeArray.hx

@@ -0,0 +1,29 @@
+package cpp;
+
+class NativeArray {
+
+	public static inline function blit<T>( ioDestArray:Array<T>,
+		inDestElement:Int, inSourceArray:Array<T>,
+		inSourceElement:Int, inElementCount:Int ): Void  {
+	untyped ioDestArray.blit(inDestElement, inSourceArray, inSourceElement, inElementCount);
+	};
+
+	public static inline function zero<T>( ioDestArray:Array<T>, ?inFirst:Int, ?inElements:Int ) {
+		untyped ioDestArray.zero(inFirst, inElements);
+	};
+
+	public static inline function unsafeGet<T>( inDestArray:Array<T>, inIndex:Int) : T {
+		return untyped inDestArray.__unsafe_get(inIndex);
+	}
+	public static inline function unsafeSet<T>( ioDestArray:Array<T>, inIndex:Int, inValue:T) : T {
+		return untyped ioDestArray.__unsafe_set(inIndex,inValue);
+	}
+
+	public static inline function memcmp<T>( inArrayA:Array<T>, inArrayB:Array<T>) : Int {
+		return untyped inArrayA.memcmp(inArrayB);
+	}
+
+	public static inline function setSize<T>( ioArray:Array<T>, inSize:Int) : Array<T> {
+		return untyped ioArray.__SetSizeExact(inSize);
+   }
+}

+ 3 - 1
std/cpp/vm/Debugger.hx

@@ -140,6 +140,8 @@ class Debugger
      *          - threadNumber, the thread number of the event
      *          - threadNumber, the thread number of the event
      *          - event, one of THREAD_CREATED, THREAD_TERMINATED,
      *          - event, one of THREAD_CREATED, THREAD_TERMINATED,
      *            THREAD_STARTED, or THREAD_STOPPED
      *            THREAD_STARTED, or THREAD_STOPPED
+     *          - stackFrame, the stack frame number at which the thread is stopped,
+     *            undefined if event is not THREAD_STOPPED
      *          - className, the class name at which the thread is stopped,
      *          - className, the class name at which the thread is stopped,
      *            undefined if event is not THREAD_STOPPED
      *            undefined if event is not THREAD_STOPPED
      *          - functionName, the function name at which the thread is
      *          - functionName, the function name at which the thread is
@@ -150,7 +152,7 @@ class Debugger
      *            undefined if event is not THREAD_STOPPED
      *            undefined if event is not THREAD_STOPPED
      **/
      **/
     public static function setEventNotificationHandler(
     public static function setEventNotificationHandler(
-             handler : Int -> Int -> String -> String -> String -> Int -> Void)
+             handler : Int -> Int -> Int -> String -> String -> String -> Int -> Void)
     {
     {
         untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler);
         untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler);
     }
     }

+ 1 - 1
std/flash/_std/Type.hx

@@ -162,7 +162,7 @@ enum ValueType {
 	}
 	}
 
 
 	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
 	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
-		var f = Reflect.field(e,constr);
+		var f = untyped e[constr];
 		if( f == null ) throw "No such constructor "+constr;
 		if( f == null ) throw "No such constructor "+constr;
 		if( Reflect.isFunction(f) ) {
 		if( Reflect.isFunction(f) ) {
 			if( params == null ) throw "Constructor "+constr+" need parameters";
 			if( params == null ) throw "Constructor "+constr+" need parameters";

+ 2 - 2
std/flash/_std/haxe/Json.hx

@@ -33,7 +33,7 @@ class Json {
 	}
 	}
 
 
 	#if (haxeJSON || !flash11) inline #end
 	#if (haxeJSON || !flash11) inline #end
-	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		return haxe.format.JsonPrinter.print(value, replacer);
+	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 	}
 	}
 }
 }

+ 2 - 2
std/flash/_std/haxe/ds/IntMap.hx

@@ -29,11 +29,11 @@ package haxe.ds;
 		h = new flash.utils.Dictionary();
 		h = new flash.utils.Dictionary();
 	}
 	}
 
 
-	public function set( key : Int, value : T ) : Void {
+	public inline function set( key : Int, value : T ) : Void {
 		untyped h[key] = value;
 		untyped h[key] = value;
 	}
 	}
 
 
-	public function get( key : Int ) : Null<T> {
+	public inline function get( key : Int ) : Null<T> {
 		return untyped h[key];
 		return untyped h[key];
 	}
 	}
 
 

+ 5 - 2
std/haxe/Json.hx

@@ -46,9 +46,12 @@ class Json {
 		If `replacer` is given and is not null, it is used to retrieve
 		If `replacer` is given and is not null, it is used to retrieve
 		actual object to be encoded. The `replacer` function two parameters,
 		actual object to be encoded. The `replacer` function two parameters,
 		the key and the value being encoded. Initial key value is an empty string.
 		the key and the value being encoded. Initial key value is an empty string.
+		
+		If `space` is given and is not null, the result will be pretty-printed.
+		Successive levels will be indented by this string.
 	**/
 	**/
-	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		return haxe.format.JsonPrinter.print(value, replacer);
+	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 	}
 	}
 
 
 }
 }

+ 28 - 10
std/haxe/ds/Vector.hx

@@ -21,6 +21,10 @@
  */
  */
 package haxe.ds;
 package haxe.ds;
 
 
+#if cpp
+using cpp.NativeArray;
+#end
+
 private typedef VectorData<T> = #if flash10
 private typedef VectorData<T> = #if flash10
 	flash.Vector<T>
 	flash.Vector<T>
 #elseif neko
 #elseif neko
@@ -75,7 +79,11 @@ abstract Vector<T>(VectorData<T>) {
 		unspecified.
 		unspecified.
 	**/
 	**/
 	@:arrayAccess public inline function get(index:Int):Null<T> {
 	@:arrayAccess public inline function get(index:Int):Null<T> {
+		#if cpp
+		return this.unsafeGet(index);
+		#else
 		return this[index];
 		return this[index];
+		#end
 	}
 	}
 
 
 	/**
 	/**
@@ -85,7 +93,11 @@ abstract Vector<T>(VectorData<T>) {
 		unspecified.
 		unspecified.
 	**/
 	**/
 	@:arrayAccess public inline function set(index:Int, val:T):T {
 	@:arrayAccess public inline function set(index:Int, val:T):T {
+		#if cpp
+		return this.unsafeSet(index,val);
+		#else
 		return this[index] = val;
 		return this[index] = val;
+		#end
 	}
 	}
 
 
 	/**
 	/**
@@ -112,7 +124,7 @@ abstract Vector<T>(VectorData<T>) {
 		The results are unspecified if `length` results in out-of-bounds access,
 		The results are unspecified if `length` results in out-of-bounds access,
 		or if `src` or `dest` are null
 		or if `src` or `dest` are null
 	**/
 	**/
-	public static #if (cs || java || neko) inline #end function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void
+	public static #if (cs || java || neko || cpp) inline #end function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void
 	{
 	{
 		#if neko
 		#if neko
 			untyped __dollar__ablit(dest,destPos,src,srcPos,len);
 			untyped __dollar__ablit(dest,destPos,src,srcPos,len);
@@ -120,6 +132,8 @@ abstract Vector<T>(VectorData<T>) {
 			java.lang.System.arraycopy(src, srcPos, dest, destPos, len);
 			java.lang.System.arraycopy(src, srcPos, dest, destPos, len);
 		#elseif cs
 		#elseif cs
 			cs.system.Array.Copy(cast src, srcPos,cast dest, destPos, len);
 			cs.system.Array.Copy(cast src, srcPos,cast dest, destPos, len);
+		#elseif cpp
+			dest.toData().blit(destPos,src.toData(), srcPos,len);
 		#else
 		#else
 			for (i in 0...len)
 			for (i in 0...len)
 			{
 			{
@@ -131,16 +145,20 @@ abstract Vector<T>(VectorData<T>) {
 	/**
 	/**
 		Creates a new Array, copy the content from the Vector to it, and returns it.
 		Creates a new Array, copy the content from the Vector to it, and returns it.
 	**/
 	**/
-	public #if flash inline #end function toArray():Array<T> {
-		var a = new Array();
-		var len = length;
-		#if (cpp || neko)
-		// prealloc good size
-		if( len > 0 ) a[len - 1] = get(0);
+	public #if (flash || cpp) inline #end function toArray():Array<T> {
+		#if cpp
+			return this.copy();
+		#else
+			var a = new Array();
+			var len = length;
+			#if (neko)
+			// prealloc good size
+			if( len > 0 ) a[len - 1] = get(0);
+			#end
+			for( i in 0...len )
+				a[i] = get(i);
+			return a;
 		#end
 		#end
-		for( i in 0...len )
-			a[i] = get(i);
-		return a;
 	}
 	}
 
 
 	/**
 	/**

+ 45 - 13
std/haxe/format/JsonPrinter.hx

@@ -2,17 +2,23 @@ package haxe.format;
 
 
 class JsonPrinter {
 class JsonPrinter {
 
 
-	static public function print(o:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic) : String {
-		var printer = new JsonPrinter(replacer);
+	static public function print(o:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String) : String {
+		var printer = new JsonPrinter(replacer, space);
 		printer.write("", o);
 		printer.write("", o);
 		return printer.buf.toString();
 		return printer.buf.toString();
 	}
 	}
 
 
 	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
 	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
 	var replacer : Dynamic -> Dynamic -> Dynamic;
 	var replacer : Dynamic -> Dynamic -> Dynamic;
-
-	function new(replacer:Dynamic -> Dynamic -> Dynamic) {
+	var indent:String;
+	var pretty:Bool;
+	var nind:Int;
+	
+	function new(replacer:Dynamic -> Dynamic -> Dynamic, space:String) {
 		this.replacer = replacer;
 		this.replacer = replacer;
+		this.indent = space;
+		this.pretty = space != null;
+		this.nind = 0;
 
 
 		#if flash9
 		#if flash9
 		buf = new flash.utils.ByteArray();
 		buf = new flash.utils.ByteArray();
@@ -22,6 +28,14 @@ class JsonPrinter {
 		buf = new StringBuf();
 		buf = new StringBuf();
 		#end
 		#end
 	}
 	}
+	
+	inline function ipad ():Void {
+		if (pretty) add(StringTools.lpad('', indent, nind * indent.length));
+	}
+	
+	inline function newl ():Void {
+		if (pretty) addChar('\n'.code);
+	}
 
 
 	function write(k:Dynamic, v:Dynamic) {
 	function write(k:Dynamic, v:Dynamic) {
 		if (replacer != null) v = replacer(k, v);
 		if (replacer != null) v = replacer(k, v);
@@ -42,13 +56,20 @@ class JsonPrinter {
 			else if( c == Array ) {
 			else if( c == Array ) {
 				var v : Array<Dynamic> = v;
 				var v : Array<Dynamic> = v;
 				addChar('['.code);
 				addChar('['.code);
+
 				var len = v.length;
 				var len = v.length;
-				if( len > 0 ) {
-					write(0, v[0]);
-					var i = 1;
-					while( i < len ) {
-						addChar(','.code);
-						write(i, v[i++]);
+				var last = len - 1;
+				for (i in 0...len)
+				{
+					if (i > 0) addChar(','.code) else nind++;
+					newl();
+					ipad();
+					write(i, v[i]);
+					if (i == last)
+					{
+						nind--;
+						newl();
+						ipad();
 					}
 					}
 				}
 				}
 				addChar(']'.code);
 				addChar(']'.code);
@@ -105,15 +126,26 @@ class JsonPrinter {
 	}
 	}
 
 
 	function fieldsString( v : Dynamic, fields : Array<String> ) {
 	function fieldsString( v : Dynamic, fields : Array<String> ) {
-		var first = true;
 		addChar('{'.code);
 		addChar('{'.code);
-		for( f in fields ) {
+		var len = fields.length;
+		var last = len - 1;
+		for( i in 0...len ) {
+			var f = fields[i];
 			var value = Reflect.field(v,f);
 			var value = Reflect.field(v,f);
 			if( Reflect.isFunction(value) ) continue;
 			if( Reflect.isFunction(value) ) continue;
-			if( first ) first = false else addChar(','.code);
+			if( i > 0 ) addChar(','.code) else nind++;
+			newl();
+			ipad();
 			quote(f);
 			quote(f);
 			addChar(':'.code);
 			addChar(':'.code);
+			if (pretty) addChar(' '.code);
 			write(f, value);
 			write(f, value);
+			if (i == last)
+			{
+				nind--;
+				newl();
+				ipad();
+			}
 		}
 		}
 		addChar('}'.code);
 		addChar('}'.code);
 	}
 	}

+ 70 - 7
std/haxe/io/Bytes.hx

@@ -21,6 +21,10 @@
  */
  */
 package haxe.io;
 package haxe.io;
 
 
+#if cpp
+using cpp.NativeArray;
+#end
+
 class Bytes {
 class Bytes {
 
 
 	public var length(default,null) : Int;
 	public var length(default,null) : Int;
@@ -29,6 +33,9 @@ class Bytes {
 	function new(length,b) {
 	function new(length,b) {
 		this.length = length;
 		this.length = length;
 		this.b = b;
 		this.b = b;
+		#if flash9
+		b.endian = flash.utils.Endian.LITTLE_ENDIAN;
+		#end
 	}
 	}
 
 
 	public inline function get( pos : Int ) : Int {
 	public inline function get( pos : Int ) : Int {
@@ -80,6 +87,8 @@ class Bytes {
 		java.lang.System.arraycopy(src.b, srcpos, b, pos, len);
 		java.lang.System.arraycopy(src.b, srcpos, b, pos, len);
 		#elseif cs
 		#elseif cs
 		cs.system.Array.Copy(src.b, srcpos, b, pos, len);
 		cs.system.Array.Copy(src.b, srcpos, b, pos, len);
+		#elseif cpp
+		b.blit(pos, src.b, srcpos, len);
 		#else
 		#else
 		var b1 = b;
 		var b1 = b;
 		var b2 = src.b;
 		var b2 = src.b;
@@ -107,6 +116,8 @@ class Bytes {
 		pos += len&~3;
 		pos += len&~3;
 		for( i in 0...len&3 )
 		for( i in 0...len&3 )
 			set(pos++,value);
 			set(pos++,value);
+		#elseif cpp
+		untyped __global__.__hxcpp_memory_memset(b,pos,len,value);
 		#else
 		#else
 		for( i in 0...len )
 		for( i in 0...len )
 			set(pos++, value);
 			set(pos++, value);
@@ -148,20 +159,32 @@ class Bytes {
 		var b2 = other.b;
 		var b2 = other.b;
 		b1.position = 0;
 		b1.position = 0;
 		b2.position = 0;
 		b2.position = 0;
+		b1.endian = flash.utils.Endian.BIG_ENDIAN;
+		b2.endian = flash.utils.Endian.BIG_ENDIAN;
 		for( i in 0...len>>2 )
 		for( i in 0...len>>2 )
 			if( b1.readUnsignedInt() != b2.readUnsignedInt() ) {
 			if( b1.readUnsignedInt() != b2.readUnsignedInt() ) {
 				b1.position -= 4;
 				b1.position -= 4;
 				b2.position -= 4;
 				b2.position -= 4;
-				return b1.readUnsignedInt() - b2.readUnsignedInt();
+				var d = b1.readUnsignedInt() - b2.readUnsignedInt();
+				b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
+				b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
+				return d;
 			}
 			}
 		for( i in 0...len & 3 )
 		for( i in 0...len & 3 )
-			if( b1.readUnsignedByte() != b2.readUnsignedByte() )
+			if( b1.readUnsignedByte() != b2.readUnsignedByte() ) {
+				b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
+				b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
 				return b1[b1.position-1] - b2[b2.position-1];
 				return b1[b1.position-1] - b2[b2.position-1];
+			}
+		b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
+		b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
 		return length - other.length;
 		return length - other.length;
 		#elseif php
 		#elseif php
 		return untyped __php__("$this->b < $other->b ? -1 : ($this->b == $other->b ? 0 : 1)");
 		return untyped __php__("$this->b < $other->b ? -1 : ($this->b == $other->b ? 0 : 1)");
 		//#elseif cs
 		//#elseif cs
 		//TODO: memcmp if unsafe flag is on
 		//TODO: memcmp if unsafe flag is on
+		#elseif cpp
+		return b.memcmp(other.b);
 		#else
 		#else
 		var b1 = b;
 		var b1 = b;
 		var b2 = other.b;
 		var b2 = other.b;
@@ -177,31 +200,65 @@ class Bytes {
 		#end
 		#end
 	}
 	}
 
 
-	public function readDouble( pos : Int ) : Float {
+	public function getDouble( pos : Int ) : Float {
 		#if neko
 		#if neko
 		return untyped Input._double_of_bytes(sub(pos,8).b,false);
 		return untyped Input._double_of_bytes(sub(pos,8).b,false);
 		#elseif flash9
 		#elseif flash9
 		b.position = pos;
 		b.position = pos;
 		return b.readDouble();
 		return b.readDouble();
+		#elseif cpp
+		if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds;
+		return untyped __global__.__hxcpp_memory_get_double(b,pos);
 		#else
 		#else
 		var b = new haxe.io.BytesInput(this,pos,8);
 		var b = new haxe.io.BytesInput(this,pos,8);
 		return b.readDouble();
 		return b.readDouble();
 		#end
 		#end
 	}
 	}
 
 
-	public function readFloat( pos : Int ) : Float {
+	public function getFloat( pos : Int ) : Float {
 		#if neko
 		#if neko
 		return untyped Input._float_of_bytes(sub(pos,4).b,false);
 		return untyped Input._float_of_bytes(sub(pos,4).b,false);
 		#elseif flash9
 		#elseif flash9
 		b.position = pos;
 		b.position = pos;
 		return b.readFloat();
 		return b.readFloat();
+		#elseif cpp
+		if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds;
+		return untyped __global__.__hxcpp_memory_get_float(b,pos);
 		#else
 		#else
 		var b = new haxe.io.BytesInput(this,pos,4);
 		var b = new haxe.io.BytesInput(this,pos,4);
 		return b.readFloat();
 		return b.readFloat();
 		#end
 		#end
 	}
 	}
 
 
-	public function readString( pos : Int, len : Int ) : String {
+	public function setDouble( pos : Int, v : Float ) : Void {
+		#if neko
+		untyped $sblit(b, pos, Output._double_bytes(v,false), 0, 8);
+		#elseif flash9
+		b.position = pos;
+		b.writeDouble(v);
+		#elseif cpp
+		if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds;
+		untyped __global__.__hxcpp_memory_set_double(b,pos,v);
+		#else
+		throw "Not supported";
+		#end
+	}
+
+	public function setFloat( pos : Int, v : Float ) : Void {
+		#if neko
+		untyped $sblit(b, pos, Output._float_bytes(v,false), 0, 4);
+		#elseif flash9
+		b.position = pos;
+		b.writeFloat(v);
+		#elseif cpp
+		if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds;
+		untyped __global__.__hxcpp_memory_set_float(b,pos,v);
+		#else
+		throw "Not supported";
+		#end
+	}
+
+	public function getString( pos : Int, len : Int ) : String {
 		#if !neko
 		#if !neko
 		if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds;
 		if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds;
 		#end
 		#end
@@ -252,6 +309,12 @@ class Bytes {
 		#end
 		#end
 	}
 	}
 
 
+	@:deprecated("readString is deprecated, use getString instead")
+	@:noCompletion
+	public inline function readString(pos:Int, len:Int):String {
+		return getString(pos, len);
+	}
+
 	public function toString() : String {
 	public function toString() : String {
 		#if neko
 		#if neko
 		return new String(untyped __dollar__ssub(b,0,length));
 		return new String(untyped __dollar__ssub(b,0,length));
@@ -269,7 +332,7 @@ class Bytes {
 		}
 		}
 		catch (e:Dynamic) throw e;
 		catch (e:Dynamic) throw e;
 		#else
 		#else
-		return readString(0,length);
+		return getString(0,length);
 		#end
 		#end
 	}
 	}
 
 
@@ -395,7 +458,7 @@ class Bytes {
 		#elseif php
 		#elseif php
 		return untyped __call__("ord", b[pos]);
 		return untyped __call__("ord", b[pos]);
 		#elseif cpp
 		#elseif cpp
-		return untyped b[pos];
+		return untyped b.unsafeGet(pos);
 		#elseif java
 		#elseif java
 		return untyped b[pos] & 0xFF;
 		return untyped b[pos] & 0xFF;
 		#else
 		#else

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

@@ -47,6 +47,7 @@ class BytesBuffer {
 		b = untyped StringBuf.__make();
 		b = untyped StringBuf.__make();
 		#elseif flash9
 		#elseif flash9
 		b = new flash.utils.ByteArray();
 		b = new flash.utils.ByteArray();
+		b.endian = flash.utils.Endian.LITTLE_ENDIAN;
 		#elseif php
 		#elseif php
 		b = "";
 		b = "";
 		#elseif cpp
 		#elseif cpp

+ 83 - 29
std/haxe/macro/Compiler.hx

@@ -90,7 +90,15 @@ class Compiler {
 	}
 	}
 
 
 	/**
 	/**
-		Include for compilation all classes defined in the given package excluding the ones referenced in the ignore list.
+		Includes all modules in package `pack` in the compilation.
+
+		In order to include single modules, their paths can be listed directly
+		on command line: `haxe ... ModuleName pack.ModuleName`.
+
+		@param rec If true, recursively adds all sub-packages.
+		@param ignore Array of module names to ignore for inclusion.
+		@param classPaths Array of additional class paths to check. This can be
+		    used to add packages outside the usual class paths.
 	**/
 	**/
 	public static function include( pack : String, ?rec = true, ?ignore : Array<String>, ?classPaths : Array<String> ) {
 	public static function include( pack : String, ?rec = true, ?ignore : Array<String>, ?classPaths : Array<String> ) {
 		var skip = if( ignore == null ) {
 		var skip = if( ignore == null ) {
@@ -232,46 +240,92 @@ class Compiler {
 	}
 	}
 
 
 	/**
 	/**
-		Mark a class (or array of classes) with the metadata @:keep.
+		Marks types or packages to be kept by DCE and includes them for
+		compilation.
+
+		This also extends to the sub-types of resolved modules.
 
 
-		Note that this does not imply inclusion of the class(es): If a class is
-		neither referenced nor added via [Compiler.include], it will not be part
-		of the output even if @:keep was added.
+		In order to include module sub-types directly, their full dot path
+		including the containing module has to be used
+		(e.g. msignal.Signal.Signal0).
+
+		@param path A package, module or sub-type dot path to keep.
+		@param paths An Array of package, module or sub-type dot paths to keep.
+		@param recursive If true, recurses into sub-packages for package paths.
 	**/
 	**/
-	public static function keep(?path : String, ?paths : Array<String>, rec = false)
+	public static function keep(?path : String, ?paths : Array<String>, ?recursive:Bool = true)
 	{
 	{
 		if (null == paths)
 		if (null == paths)
 			paths = [];
 			paths = [];
 		if (null != path)
 		if (null != path)
 			paths.push(path);
 			paths.push(path);
-		for (path in paths)
-		{
-			for ( p in Context.getClassPath() ) {
-				var p = p + path.split(".").join("/");
-				if (sys.FileSystem.exists(p) && sys.FileSystem.isDirectory(p))
-				{
-					for( file in sys.FileSystem.readDirectory(p) ) {
+		for (path in paths) {
+			var found:Bool = false;
+			var moduleRoot = (path.indexOf(".") < 0)?"":path.substring(0, path.lastIndexOf("."));
+
+			for ( classPath in Context.getClassPath() ) {
+				var moduleRootPath = (moduleRoot == "")?"":(classPath + moduleRoot.split(".").join("/") + ".hx");
+				var fullPath = classPath + path.split(".").join("/");
+				var isValidDirectory:Bool = (sys.FileSystem.exists(fullPath) && sys.FileSystem.isDirectory(fullPath));
+				var isValidModule:Bool = !isValidDirectory && sys.FileSystem.exists(fullPath + ".hx");
+				var isValidSubType:Bool = !isValidModule && (moduleRootPath != "" && sys.FileSystem.exists(moduleRootPath));
+				if ( !isValidDirectory && !isValidModule && !isValidSubType)
+					continue;
+				else
+					found = true;
+
+				if(isValidDirectory) {
+					for( file in sys.FileSystem.readDirectory(fullPath) ) {
 						if( StringTools.endsWith(file, ".hx") ) {
 						if( StringTools.endsWith(file, ".hx") ) {
 							var module = path + "." + file.substr(0, file.length - 3);
 							var module = path + "." + file.substr(0, file.length - 3);
-							var types = Context.getModule(module);
-							for (type in types)
-							{
-								switch(type)
-								{
-									case TInst(cls, _):
-										addMetadata("@:keep", cls.toString());
-									default:
-										//
-								}
-							}
-						} else if( rec && sys.FileSystem.isDirectory(p + "/" + file) )
+							keepModule(module);
+						} else if( recursive && sys.FileSystem.isDirectory(fullPath + "/" + file) )
 							keep(path + "." + file, true);
 							keep(path + "." + file, true);
 					}
 					}
-				} else {
-					addMetadata("@:keep", path);
-					break;
+				} else if(isValidModule){
+					keepModule(path);
+				} else if(isValidSubType){
+					keepSubType(path);
 				}
 				}
 			}
 			}
+
+			if (!found)
+				Context.warning("file or directory not found, can't keep: "+path, Context.currentPos());
+		}
+	}
+
+	private static function keepSubType( path : String )
+	{
+		var module = path.substring(0, path.lastIndexOf("."));
+		var subType = module.substring(0, module.lastIndexOf(".")) + "." + path.substring(path.lastIndexOf(".") + 1);
+		var types = Context.getModule(module);
+		var found:Bool = false;
+		for (type in types) {
+			switch(type) {
+				case TInst(cls, _):
+					if (cls.toString() == subType) {
+						found = true;
+						cls.get().meta.add(":keep", [], cls.get().pos);
+					}
+				default:
+					//
+			}
+		}
+
+		if (!found)
+			Context.warning("subtype not found, can't keep: "+path, Context.currentPos());
+	}
+
+	private static function keepModule( path : String )
+	{
+		var types = Context.getModule(path);
+		for (type in types) {
+			switch(type) {
+				case TInst(cls, _):
+					cls.get().meta.add(":keep", [], cls.get().pos);
+				default:
+					//
+			}
 		}
 		}
 	}
 	}
 
 
@@ -312,4 +366,4 @@ class Compiler {
 	}
 	}
 	#end
 	#end
 
 
-}
+}

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

@@ -415,7 +415,7 @@ class XmlParser {
 			doc : doc,
 			doc : doc,
 			get : if( x.has.get ) mkRights(x.att.get) else RNormal,
 			get : if( x.has.get ) mkRights(x.att.get) else RNormal,
 			set : if( x.has.set ) mkRights(x.att.set) else RNormal,
 			set : if( x.has.set ) mkRights(x.att.set) else RNormal,
-			params : if( x.has.params ) mkTypeParams(x.att.params) else null,
+			params : if( x.has.params ) mkTypeParams(x.att.params) else [],
 			platforms : defplat(),
 			platforms : defplat(),
 			meta : meta,
 			meta : meta,
 			overloads: overloads
 			overloads: overloads

+ 2 - 2
std/js/_std/haxe/Json.hx

@@ -33,8 +33,8 @@ class Json {
 	}
 	}
 
 
 	#if haxeJSON inline #end
 	#if haxeJSON inline #end
-	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		return haxe.format.JsonPrinter.print(value, replacer);
+	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 	}
 	}
 
 
 	#if (!haxeJSON && old_browser)
 	#if (!haxeJSON && old_browser)

+ 3 - 3
std/neko/net/ThreadRemotingServer.hx

@@ -70,7 +70,7 @@ class ThreadRemotingServer extends ThreadServer<haxe.remoting.SocketConnection,S
 		var msgLen = cnx.getProtocol().messageLength(buf.get(pos),buf.get(pos+1));
 		var msgLen = cnx.getProtocol().messageLength(buf.get(pos),buf.get(pos+1));
 		if( msgLen == null ) {
 		if( msgLen == null ) {
 			if( buf.get(pos) != 60 )
 			if( buf.get(pos) != 60 )
-				throw "Invalid remoting message '"+buf.readString(pos,len)+"'";
+				throw "Invalid remoting message '"+buf.getString(pos,len)+"'";
 			var p = pos;
 			var p = pos;
 			while( p < len ) {
 			while( p < len ) {
 				if( buf.get(p) == 0 )
 				if( buf.get(p) == 0 )
@@ -81,7 +81,7 @@ class ThreadRemotingServer extends ThreadServer<haxe.remoting.SocketConnection,S
 				return null;
 				return null;
 			p -= pos;
 			p -= pos;
 			return {
 			return {
-				msg : buf.readString(pos,p),
+				msg : buf.getString(pos,p),
 				bytes : p + 1,
 				bytes : p + 1,
 			};
 			};
 		}
 		}
@@ -90,7 +90,7 @@ class ThreadRemotingServer extends ThreadServer<haxe.remoting.SocketConnection,S
 		if( buf.get(pos + msgLen-1) != 0 )
 		if( buf.get(pos + msgLen-1) != 0 )
 			throw "Truncated message";
 			throw "Truncated message";
 		return {
 		return {
-			msg : buf.readString(pos+2,msgLen-3),
+			msg : buf.getString(pos+2,msgLen-3),
 			bytes : msgLen,
 			bytes : msgLen,
 		};
 		};
 	}
 	}

+ 1 - 1
std/php/Boot.hx

@@ -554,7 +554,7 @@ function _hx_set_method($o, $field, $func) {
 }
 }
 
 
 function _hx_shift_right($v, $n) {
 function _hx_shift_right($v, $n) {
-	return ($v >> $n) & (0x7fffffff >> ($n-1));
+	return ($v >= 0) ? ($v >> $n) : ($v >> $n) & (0x7fffffff >> ($n-1));
 }
 }
 
 
 function _hx_string_call($s, $method, $params) {
 function _hx_string_call($s, $method, $params) {

+ 6 - 6
std/php/_std/haxe/Json.hx

@@ -32,11 +32,11 @@ class Json {
 		#end
 		#end
 	}
 	}
 
 
-	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
+	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
 		#if !haxeJSON
 		#if !haxeJSON
-		return phpJsonEncode(value, replacer);
+		return phpJsonEncode(value, replacer, space);
 		#else
 		#else
-		return haxe.format.JsonPrinter.print(value, replacer);
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 		#end
 		#end
 	}
 	}
 
 
@@ -59,9 +59,9 @@ class Json {
 			return val;
 			return val;
 	}
 	}
 
 
-	static function phpJsonEncode(val:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic):String {
-		if(null != replacer)
-			return haxe.format.JsonPrinter.print(val, replacer);
+	static function phpJsonEncode(val:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String):String {
+		if(null != replacer || null != space)
+			return haxe.format.JsonPrinter.print(val, replacer, space);
 		var json = untyped __call__("json_encode", convertBeforeEncode(val));
 		var json = untyped __call__("json_encode", convertBeforeEncode(val));
 		if (untyped __physeq__(json, false))
 		if (untyped __physeq__(json, false))
 			return throw "invalid json";
 			return throw "invalid json";

+ 1 - 1
std/php/_std/sys/io/FileOutput.hx

@@ -35,7 +35,7 @@ class FileOutput extends haxe.io.Output {
 	}
 	}
 
 
 	public override function writeBytes( b : haxe.io.Bytes, p : Int, l : Int ) : Int {
 	public override function writeBytes( b : haxe.io.Bytes, p : Int, l : Int ) : Int {
-		var s = b.readString(p, l);
+		var s = b.getString(p, l);
 		if(untyped __call__('feof', __f)) return throw new haxe.io.Eof();
 		if(untyped __call__('feof', __f)) return throw new haxe.io.Eof();
 		var r = untyped __call__('fwrite', __f, s, l);
 		var r = untyped __call__('fwrite', __f, s, l);
 		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
 		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');

+ 1 - 1
std/php/_std/sys/io/Process.hx

@@ -42,7 +42,7 @@ private class Stdin extends haxe.io.Output {
 	}
 	}
 
 
 	public override function writeBytes( b : haxe.io.Bytes, pos : Int, l : Int ) : Int {
 	public override function writeBytes( b : haxe.io.Bytes, pos : Int, l : Int ) : Int {
-		var s = b.readString(pos, l);
+		var s = b.getString(pos, l);
 		if(untyped __call__('feof', p)) return throw new haxe.io.Eof();
 		if(untyped __call__('feof', p)) return throw new haxe.io.Eof();
 		var r = untyped __call__('fwrite', p, s, l);
 		var r = untyped __call__('fwrite', p, s, l);
 		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
 		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');

+ 183 - 14
tests/RunTravis.hx

@@ -1,6 +1,15 @@
+using StringTools;
+
+import yaml.*;
+
 import sys.*;
 import sys.*;
 import sys.io.*;
 import sys.io.*;
 
 
+private typedef TravisConfig = {
+	before_install: Array<String>,
+	script: Array<String>
+}
+
 /**
 /**
 	Will be run by TravisCI.
 	Will be run by TravisCI.
 	See ".travis.yml" at project root for TravisCI settings.
 	See ".travis.yml" at project root for TravisCI settings.
@@ -32,6 +41,30 @@ class RunTravis {
 		Sys.exit(exitCode);
 		Sys.exit(exitCode);
 	}
 	}
 
 
+	static function getHaxelibPath(libName:String) {
+		var proc = new sys.io.Process("haxelib", ["path", libName]);
+		var result;
+		var code = proc.exitCode();
+		while(true) {
+			result = proc.stdout.readLine();
+			if (!result.startsWith("-L")) {
+				break;
+			}
+		}
+		proc.close();
+		if (code != 0) {
+			Sys.println(result);
+			Sys.exit(code);
+		}
+		trace('Haxelib path for $libName: $result');
+		return result;
+	}
+
+	static function changeDirectory(path:String) {
+		Sys.println('Changing directory to $path');
+		Sys.setCwd(path);
+	}
+
 	static function setupFlashPlayerDebugger():Void {
 	static function setupFlashPlayerDebugger():Void {
 		Sys.putEnv("DISPLAY", ":99.0");
 		Sys.putEnv("DISPLAY", ":99.0");
 		runCommand("sh", ["-e", "/etc/init.d/xvfb", "start"]);
 		runCommand("sh", ["-e", "/etc/init.d/xvfb", "start"]);
@@ -73,6 +106,93 @@ class RunTravis {
 		Sys.exit(1);
 		Sys.exit(1);
 	}
 	}
 
 
+	static function parseCommand(cmd:String) {
+		var args = [];
+		var offset = 0;
+		var cur = new StringBuf();
+		var inString = false;
+
+		while(true) {
+			switch(cmd.fastCodeAt(offset++)) {
+				case '"'.code:
+					inString = !inString;
+				case ' '.code if (!inString):
+					if (cur.length > 0) {
+						args.push(cur.toString());
+						cur = new StringBuf();
+					}
+				case '\\'.code:
+					cur.addChar(cmd.fastCodeAt(offset++));
+				case "$".code:
+					switch (cmd.fastCodeAt(offset)) {
+						case '('.code:
+							++offset;
+							var env = new StringBuf();
+							while(true) {
+								switch(cmd.fastCodeAt(offset++)) {
+									case ')'.code:
+										break;
+									case c:
+										env.addChar(c);
+								}
+							}
+							cur.add(Sys.getEnv(env.toString()));
+						case _:
+							cur.addChar("$".code);
+					}
+				case c:
+					cur.addChar(c);
+			}
+			if (offset == cmd.length) {
+				break;
+			}
+		}
+		if (cur.length > 0) {
+			args.push(cur.toString());
+		}
+		return args;
+	}
+
+	static function parseTravisFile(path:String, ignoreBeforeInstall = false) {
+		var yaml:TravisConfig = yaml.Yaml.read(path, Parser.options().useObjects());
+		if (!ignoreBeforeInstall) {
+			for (code in yaml.before_install) {
+				var args = parseCommand(code);
+				var cmd = args.shift();
+				runCommand(cmd, args);
+			}
+		}
+		for (code in yaml.script) {
+			var args = parseCommand(code);
+			var cmd = args.shift();
+			runCommand(cmd, args);
+		}
+	}
+
+	static function getPhpDependencies() {
+		runCommand("sudo", ["apt-get", "install", "php5", "-y"], true);
+	}
+
+	static function getCppDependencies(unitDir:String) {
+		//hxcpp dependencies
+		runCommand("sudo", ["apt-get", "install", "gcc-multilib", "g++-multilib", "-y"], true);
+
+		//install and build hxcpp
+		runCommand("haxelib", ["git", "hxcpp", "https://github.com/HaxeFoundation/hxcpp.git"], true);
+		Sys.setCwd(Sys.getEnv("HOME") + "/haxelib/hxcpp/git/project/");
+		runCommand("neko", ["build.n"]);
+		Sys.setCwd(unitDir);
+	}
+
+	static function getJavaDependencies() {
+		runCommand("haxelib", ["git", "hxjava", "https://github.com/HaxeFoundation/hxjava.git"], true);
+	}
+
+	static function getCsDependencies() {
+		runCommand("sudo", ["apt-get", "install", "mono-devel", "mono-mcs", "-y"], true);
+		runCommand("haxelib", ["git", "hxcs", "https://github.com/HaxeFoundation/hxcs.git"], true);
+	}
+
 	static function main():Void {
 	static function main():Void {
 		var cwd = Sys.getCwd();
 		var cwd = Sys.getCwd();
 		var unitDir = cwd + "unit/";
 		var unitDir = cwd + "unit/";
@@ -83,7 +203,6 @@ class RunTravis {
 			case "macro", null:
 			case "macro", null:
 				runCommand("haxe", ["compile-macro.hxml"]);
 				runCommand("haxe", ["compile-macro.hxml"]);
 
 
-
 				//generate documentation
 				//generate documentation
 				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "src"], true);
 				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "src"], true);
 				runCommand("haxelib", ["git", "hxtemplo", "https://github.com/Simn/hxtemplo", "master", "src"], true);
 				runCommand("haxelib", ["git", "hxtemplo", "https://github.com/Simn/hxtemplo", "master", "src"], true);
@@ -103,19 +222,11 @@ class RunTravis {
 				runCommand("haxe", ["compile-neko.hxml"]);
 				runCommand("haxe", ["compile-neko.hxml"]);
 				runCommand("neko", ["unit.n"]);
 				runCommand("neko", ["unit.n"]);
 			case "php":
 			case "php":
-				runCommand("sudo", ["apt-get", "install", "php5", "-y"], true);
+				getPhpDependencies();
 				runCommand("haxe", ["compile-php.hxml"]);
 				runCommand("haxe", ["compile-php.hxml"]);
 				runCommand("php", ["php/index.php"]);
 				runCommand("php", ["php/index.php"]);
 			case "cpp":
 			case "cpp":
-				//hxcpp dependencies
-				runCommand("sudo", ["apt-get", "install", "gcc-multilib", "g++-multilib", "-y"], true);
-
-				//install and build hxcpp
-				runCommand("haxelib", ["git", "hxcpp", "https://github.com/HaxeFoundation/hxcpp.git"], true);
-				Sys.setCwd(Sys.getEnv("HOME") + "/haxelib/hxcpp/git/project/");
-				runCommand("neko", ["build.n"]);
-				Sys.setCwd(unitDir);
-
+				getCppDependencies(unitDir);
 				runCommand("haxe", ["compile-cpp.hxml"]);
 				runCommand("haxe", ["compile-cpp.hxml"]);
 				runCommand("./cpp/Test-debug", []);
 				runCommand("./cpp/Test-debug", []);
 
 
@@ -141,12 +252,11 @@ class RunTravis {
 				Sys.setCwd(optDir);
 				Sys.setCwd(optDir);
 				runCommand("haxe", ["run.hxml"]);
 				runCommand("haxe", ["run.hxml"]);
 			case "java":
 			case "java":
-				runCommand("haxelib", ["git", "hxjava", "https://github.com/HaxeFoundation/hxjava.git"], true);
+				getJavaDependencies();
 				runCommand("haxe", ["compile-java.hxml"]);
 				runCommand("haxe", ["compile-java.hxml"]);
 				runCommand("java", ["-jar", "java/Test-Debug.jar"]);
 				runCommand("java", ["-jar", "java/Test-Debug.jar"]);
 			case "cs":
 			case "cs":
-				runCommand("sudo", ["apt-get", "install", "mono-devel", "mono-mcs", "-y"], true);
-				runCommand("haxelib", ["git", "hxcs", "https://github.com/HaxeFoundation/hxcs.git"], true);
+				getCsDependencies();
 
 
 				runCommand("haxe", ["compile-cs.hxml"]);
 				runCommand("haxe", ["compile-cs.hxml"]);
 				runCommand("mono", ["cs/bin/Test-Debug.exe"]);
 				runCommand("mono", ["cs/bin/Test-Debug.exe"]);
@@ -177,6 +287,65 @@ class RunTravis {
 
 
 				runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
 				runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
 				runFlash("unit9_as3.swf");
 				runFlash("unit9_as3.swf");
+			case "openfl-samples":
+				getCppDependencies(unitDir);
+				runCommand("haxelib", ["git", "hxlibc", "https://github.com/openfl/hxlibc"]);
+				runCommand("haxelib", ["git", "actuate", "https://github.com/jgranick/actuate"]);
+				runCommand("haxelib", ["git", "box2d", "https://github.com/jgranick/box2d"]);
+				runCommand("haxelib", ["git", "swf", "https://github.com/openfl/swf"]);
+				runCommand("haxelib", ["git", "layout", "https://github.com/jgranick/layout"]);
+				runCommand("haxelib", ["git", "format", "https://github.com/HaxeFoundation/format"]);
+				runCommand("haxelib", ["git", "svg", "https://github.com/openfl/svg"]);
+				runCommand("haxelib", ["git", "lime", "https://github.com/openfl/lime"]);
+				runCommand("haxelib", ["git", "lime-build", "https://github.com/openfl/lime-build"]);
+				runCommand("haxelib", ["git", "lime-tools", "https://github.com/openfl/lime-tools"]);
+				runCommand("haxelib", ["git", "openfl-native", "https://github.com/openfl/openfl-native"]);
+				runCommand("haxelib", ["git", "openfl", "https://github.com/openfl/openfl"]);
+				runCommand("haxelib", ["git", "openfl-samples", "https://github.com/Simn/openfl-samples"]);
+				runCommand("haxelib", ["run", "openfl", "rebuild", "linux"]);
+				runCommand("haxelib", ["run", "openfl", "rebuild", "tools"]);
+				var path = getHaxelibPath("openfl-samples");
+				var old = Sys.getEnv("pwd");
+				Sys.putEnv("pwd", path);
+				parseTravisFile(haxe.io.Path.join([path, ".travis.yml"]), true);
+				if (old != null) {
+					Sys.putEnv("pwd", old);
+				}
+			case "polygonal-ds":
+				runCommand("haxelib", ["git", "polygonal-ds", "https://github.com/Simn/ds"]);
+				runCommand("haxelib", ["git", "polygonal-core", "https://github.com/polygonal/core", "master", "src"]);
+				runCommand("haxelib", ["git", "polygonal-printf", "https://github.com/polygonal/printf", "master", "src"]);
+				changeDirectory(getHaxelibPath("polygonal-ds"));
+				runCommand("haxe", ["-cp", "src", "-cp", "test", "-lib", "polygonal-core", "-lib", "polygonal-printf", "-main", "UnitTest", "-js", "unit.js"]);
+				runCommand("node", ["unit.js"]);
+			case "flambe":
+				runCommand("git", ["clone", "https://github.com/aduros/flambe"]);
+				runCommand("sh", ["flambe/bin/run-travis"]);
+			case "hxtemplo":
+				getJavaDependencies();
+				getPhpDependencies();
+				getCppDependencies(unitDir);
+				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "src"]);
+				runCommand("haxelib", ["git", "hxtemplo", "https://github.com/Simn/hxtemplo"]);
+
+				changeDirectory(getHaxelibPath("hxtemplo"));
+				runCommand("haxe", ["build.hxml"]);
+
+				runCommand("node", ["bin/hxtemplo.js"]);
+				runCommand("neko", ["bin/hxtemplo.n"]);
+				runCommand("java", ["-jar", "bin/java/Test.jar"]);
+				runCommand("php", ["bin/php/index.php"]);
+				runCommand("./bin/cpp/Test", []);
+			case "munit":
+				runCommand("haxelib", ["git", "mconsole", "https://github.com/massiveinteractive/mconsole", "master", "src"]);
+				runCommand("haxelib", ["git", "mcover", "https://github.com/massiveinteractive/MassiveCover", "master", "src"]);
+				runCommand("haxelib", ["git", "mlib", "https://github.com/massiveinteractive/MassiveLib", "master", "src"]);
+				runCommand("haxelib", ["git", "munit", "https://github.com/massiveinteractive/MassiveUnit", "master", "src"]);
+				changeDirectory(haxe.io.Path.join([getHaxelibPath("munit"), "..", "tool"]));
+				runCommand("haxe", ["build.hxml"]);
+				runCommand("haxelib", ["run", "munit", "test", "-result-exit-code", "-neko"]);
+				changeDirectory("../");
+				runCommand("haxelib", ["run", "munit", "test", "-result-exit-code", "-neko"]);
 			case target:
 			case target:
 				throw "unknown target: " + target;
 				throw "unknown target: " + target;
 		}
 		}

+ 7 - 7
tests/unit/TestBytes.hx

@@ -60,13 +60,13 @@ class TestBytes extends Test {
 		// readString
 		// readString
 		var bs = haxe.io.Bytes.ofString("One é accent");
 		var bs = haxe.io.Bytes.ofString("One é accent");
 		bs.set(3,0); // cut betwen "One" and "é"
 		bs.set(3,0); // cut betwen "One" and "é"
-		eq(bs.readString(0,3),"One");
-		eq(bs.readString(4,bs.length-4),"é accent");
-		eq(bs.readString(4,2),"é");
-		exc(function() bs.readString(-1,1));
-		exc(function() bs.readString(1,20));
-		unspec(function() bs.readString(4,1)); // might not allow to cut UTF8 char
-		unspec(function() bs.readString(1,5)); // the handling of \0 might vary
+		eq(bs.getString(0,3),"One");
+		eq(bs.getString(4,bs.length-4),"é accent");
+		eq(bs.getString(4,2),"é");
+		exc(function() bs.getString(-1,1));
+		exc(function() bs.getString(1,20));
+		unspec(function() bs.getString(4,1)); // might not allow to cut UTF8 char
+		unspec(function() bs.getString(1,5)); // the handling of \0 might vary
 		/**
 		/**
 		 	HANDLING of 0x00 in string :
 		 	HANDLING of 0x00 in string :
 				Flash8 : ignore
 				Flash8 : ignore

+ 1 - 0
tests/unit/compile-each.hxml

@@ -1,6 +1,7 @@
 -D macro-times
 -D macro-times
 -debug
 -debug
 -cp ..
 -cp ..
+-cp "C:\Program Files\The Haxe Effect\src/dev/null"
 -resource res1.txt
 -resource res1.txt
 -resource res2.bin
 -resource res2.bin
 -dce full
 -dce full

+ 1 - 1
tests/unit/issues/Issue2619.hx

@@ -1,7 +1,7 @@
 package unit.issues;
 package unit.issues;
 import unit.Test;
 import unit.Test;
 
 
-private abstract A(String) {
+private abstract A(String) to String {
 	public function new(s) this = s;
 	public function new(s) this = s;
 }
 }
 
 

+ 0 - 0
tests/unit/issues/Issue2718.hx → tests/unit/issues/Issue2718.hx.disabled


+ 22 - 0
tests/unit/issues/Issue2823.hx

@@ -0,0 +1,22 @@
+package unit.issues;
+import unit.Test;
+
+private abstract MyAbstract(Int) {
+	public inline function new() {
+		this = 1;
+	}
+
+	public function test() {
+		var f = function() return get();
+		return f;
+	}
+
+	function get() return this;
+}
+
+class Issue2823 extends Test {
+	function test() {
+		var a = new MyAbstract();
+		eq(1, a.test()());
+	}
+}

+ 33 - 0
tests/unit/issues/Issue2828.hx

@@ -0,0 +1,33 @@
+package unit.issues;
+
+class Issue2828 extends unit.Test
+{
+	public function test()
+	{
+		var u:T1<Dynamic> = new U1();
+		u.foo(1,1);
+		t(u.call());
+	}
+}
+
+private interface T1<X>
+{
+  public function foo <A>(a:X, c:A):Void;
+	public function call():Bool;
+}
+
+private class U1 implements T1<Dynamic>
+{
+  public function new () {}
+	public var didCall:Bool = false;
+
+	public function call()
+	{
+		return didCall;
+	}
+
+  public function foo <A>(a:Dynamic, c:A):Void
+	{
+		didCall = true;
+	}
+}

+ 37 - 0
tests/unit/issues/Issue2835.hx

@@ -0,0 +1,37 @@
+package unit.issues;
+
+class Issue2835 extends unit.Test
+{
+	private function test()
+	{
+		var t = new Test(42);
+		eq(42,t.get());
+		t.fromFloat(12);
+		eq(12,t.get());
+		eq(12.0,t.toFloat());
+	}
+}
+
+private class Test<T:(Float)>
+{
+	public var value:T;
+	public function new(value)
+	{
+		this.value = value;
+	}
+
+	public function toFloat():Float
+	{
+		return value;
+	}
+
+	public function fromFloat(v:Float)
+	{
+		this.value = cast v;
+	}
+
+	public function get():T
+	{
+		return value;
+	}
+}

+ 11 - 0
tests/unit/issues/Issue2844.hx

@@ -0,0 +1,11 @@
+package unit.issues;
+import unit.Test;
+
+class Issue2844 extends Test {
+	function test() {
+		t(unit.TestType.typeError({
+			var a:Array<Int> = [];
+			var b:Array<Float> = a;
+		}));
+	}
+}

+ 9 - 0
tests/unit/issues/Issue2845.hx

@@ -0,0 +1,9 @@
+package unit.issues;
+import unit.Test;
+
+class Issue2845 extends Test {
+	function test() {
+		var c = 0;
+		eq(4, (36 >>> c) & ((1 << 4) - 1));
+	}
+}

+ 20 - 0
tests/unit/issues/Issue2859.hx

@@ -0,0 +1,20 @@
+package unit.issues;
+
+private abstract Error(String) {
+    public function new(message:String) {
+        this = message;
+    }
+}
+
+class Issue2859 extends Test {
+	function test() {
+        try {
+            throw new Error("hello");
+        } catch (e:Error) {
+			unit.TestType.typedAs(e, (null:Error));
+            func(e);
+        }
+    }
+
+    static function func(e:Error) { }
+}

+ 44 - 0
tests/unit/issues/Issue2874.hx

@@ -0,0 +1,44 @@
+package unit.issues;
+
+class Issue2874 extends unit.Test
+{
+	private function test()
+	{
+		var a = new Arr(["1","2"]);
+		var a2 = a.map(function(v) return Std.parseInt(v));
+		eq(1,a2[0]);
+		eq(2,a2[1]);
+		// var a3:Arr<Int> = a.map(function(v) return Std.parseInt(v));
+		// eq(1,a3[0]);
+		// eq(2,a3[1]);
+	}
+
+	private function testArray()
+	{
+		var a = ["1","2"];
+		var a2 = a.map(function(v) return Std.parseInt(v));
+		eq(1,a2[0]);
+		eq(2,a2[1]);
+		// var a3:Array<Int> = a.map(function(v) return Std.parseInt(v));
+		// eq(1,a3[0]);
+		// eq(2,a3[1]);
+	}
+}
+
+@:arrayAccess abstract Arr<T>(Array<T>)
+{
+	@:extern inline public function new(a)
+	{
+		this = a;
+	}
+
+	@:extern inline public function map<X>(fn:T->X):Arr<X>
+	{
+		var arr2 = [];
+		for (v in this)
+		{
+			arr2.push(fn(v));
+		}
+		return new Arr(arr2);
+	}
+}

+ 2 - 0
tests/unit/unit.hxproj

@@ -21,6 +21,7 @@
   <build>
   <build>
     <option directives="" />
     <option directives="" />
     <option flashStrict="False" />
     <option flashStrict="False" />
+    <option noInlineOnDebug="False" />
     <option mainClass="unit.Test" />
     <option mainClass="unit.Test" />
     <option enabledebug="False" />
     <option enabledebug="False" />
     <option additional="" />
     <option additional="" />
@@ -58,6 +59,7 @@
     <hidden path="runexe.n" />
     <hidden path="runexe.n" />
     <hidden path="runjava.n" />
     <hidden path="runjava.n" />
     <hidden path="server.bat" />
     <hidden path="server.bat" />
+    <hidden path="obj" />
   </hiddenPaths>
   </hiddenPaths>
   <!-- Executed before build -->
   <!-- Executed before build -->
   <preBuildCommand>"$(CompilerPath)/haxe" compile.hxml</preBuildCommand>
   <preBuildCommand>"$(CompilerPath)/haxe" compile.hxml</preBuildCommand>

+ 1 - 1
type.ml

@@ -1254,7 +1254,7 @@ and unify_with_variance t1 t2 =
 	| TAbstract(a1,pl1),TAbstract(a2,pl2) ->
 	| TAbstract(a1,pl1),TAbstract(a2,pl2) ->
 		let ta1 = apply_params a1.a_types pl1 a1.a_this in
 		let ta1 = apply_params a1.a_types pl1 a1.a_this in
 		let ta2 = apply_params a2.a_types pl2 a2.a_this in
 		let ta2 = apply_params a2.a_types pl2 a2.a_this in
-		if not (Meta.has Meta.CoreType a1.a_meta) && not (Meta.has Meta.CoreType a2.a_meta) then
+		if (Meta.has Meta.CoreType a1.a_meta) && (Meta.has Meta.CoreType a2.a_meta) then
 			type_eq EqStrict ta1 ta2;
 			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
 		if not (List.exists (allows_variance_to ta2) a1.a_to) && not (List.exists (allows_variance_to ta1) a2.a_from) then
 			error [cannot_unify t1 t2]
 			error [cannot_unify t1 t2]

+ 2 - 1
typecore.ml

@@ -39,8 +39,9 @@ type current_fun =
 	| FunMember
 	| FunMember
 	| FunStatic
 	| FunStatic
 	| FunConstructor
 	| FunConstructor
-	| FunMemberLocal
 	| FunMemberAbstract
 	| FunMemberAbstract
+	| FunMemberClassLocal
+	| FunMemberAbstractLocal
 
 
 type macro_mode =
 type macro_mode =
 	| MExpr
 	| MExpr

+ 1 - 1
typeload.ml

@@ -1099,7 +1099,7 @@ let set_heritance ctx c herits p =
 				intf.cl_build();
 				intf.cl_build();
 				if is_parent c intf then error "Recursive class" p;
 				if is_parent c intf then error "Recursive class" p;
 				if c.cl_interface then error "Interfaces cannot implement another interface (use extends instead)" p;
 				if c.cl_interface then error "Interfaces cannot implement another interface (use extends instead)" p;
-				if not intf.cl_interface then error "You can only implements an interface" p;
+				if not intf.cl_interface then error "You can only implement an interface" p;
 				process_meta intf;
 				process_meta intf;
 				c.cl_implements <- (intf, params) :: c.cl_implements;
 				c.cl_implements <- (intf, params) :: c.cl_implements;
 				if not !has_interf then begin
 				if not !has_interf then begin

+ 29 - 13
typer.ml

@@ -635,6 +635,7 @@ let rec type_module_type ctx t tparams p =
 		mk (TTypeExpr (TEnumDecl e)) (TType (e.e_type,types)) p
 		mk (TTypeExpr (TEnumDecl e)) (TType (e.e_type,types)) p
 	| TTypeDecl s ->
 	| TTypeDecl s ->
 		let t = apply_params s.t_types (List.map (fun _ -> mk_mono()) s.t_types) s.t_type in
 		let t = apply_params s.t_types (List.map (fun _ -> mk_mono()) s.t_types) s.t_type in
+		Codegen.DeprecationCheck.check_typedef ctx.com s p;
 		(match follow t with
 		(match follow t with
 		| TEnum (e,params) ->
 		| TEnum (e,params) ->
 			type_module_type ctx (TEnumDecl e) (Some params) p
 			type_module_type ctx (TEnumDecl e) (Some params) p
@@ -697,7 +698,8 @@ let make_call ctx e params t p =
 				begin match t with
 				begin match t with
 					| TAbstract(a,pl) ->
 					| TAbstract(a,pl) ->
 						let has_params = a.a_types <> [] || f.cf_params <> [] in
 						let has_params = a.a_types <> [] || f.cf_params <> [] in
-						let map_type = fun t -> apply_params a.a_types pl (monomorphs f.cf_params t) in
+						let monos = List.map (fun _ -> mk_mono()) f.cf_params in
+						let map_type = fun t -> apply_params a.a_types pl (apply_params f.cf_params monos t) in
 						Some (has_params,map_type)
 						Some (has_params,map_type)
 					| _ ->
 					| _ ->
 						None
 						None
@@ -798,17 +800,20 @@ let get_this ctx p =
 	match ctx.curfun with
 	match ctx.curfun with
 	| FunStatic ->
 	| FunStatic ->
 		error "Cannot access this from a static function" p
 		error "Cannot access this from a static function" p
-	| FunMemberLocal ->
-		let v = (match ctx.vthis with
+	| FunMemberClassLocal | FunMemberAbstractLocal ->
+		let v = match ctx.vthis with
 			| None ->
 			| None ->
-				(* we might be in a closure of an abstract member, so check for local "this" first *)
-				let v = try PMap.find "this" ctx.locals with Not_found -> gen_local ctx ctx.tthis in
+				let v = if ctx.curfun = FunMemberAbstractLocal then
+					PMap.find "this" ctx.locals
+				else
+					gen_local ctx ctx.tthis
+				in
 				ctx.vthis <- Some v;
 				ctx.vthis <- Some v;
 				v
 				v
 			| Some v ->
 			| Some v ->
 				ctx.locals <- PMap.add v.v_name v ctx.locals;
 				ctx.locals <- PMap.add v.v_name v ctx.locals;
 				v
 				v
-		) in
+		in
 		mk (TLocal v) ctx.tthis p
 		mk (TLocal v) ctx.tthis p
 	| FunMemberAbstract ->
 	| FunMemberAbstract ->
 		let v = (try PMap.find "this" ctx.locals with Not_found -> assert false) in
 		let v = (try PMap.find "this" ctx.locals with Not_found -> assert false) in
@@ -832,8 +837,8 @@ let field_access ctx mode f fmode t e p =
 	match f.cf_kind with
 	match f.cf_kind with
 	| Method m ->
 	| Method m ->
 		if mode = MSet && m <> MethDynamic && not ctx.untyped then error "Cannot rebind this method : please use 'dynamic' before method declaration" p;
 		if mode = MSet && m <> MethDynamic && not ctx.untyped then error "Cannot rebind this method : please use 'dynamic' before method declaration" p;
-		begin match e.eexpr with
-		| TTypeExpr(TClassDecl ({cl_kind = KAbstractImpl a} as c)) when c == ctx.curclass && ctx.curfun = FunMemberAbstract && Meta.has Meta.Impl f.cf_meta ->
+		begin match ctx.curfun,e.eexpr with
+		| (FunMemberAbstract | FunMemberAbstractLocal),TTypeExpr(TClassDecl ({cl_kind = KAbstractImpl a} as c)) when c == ctx.curclass && Meta.has Meta.Impl f.cf_meta ->
 			let e = mk (TField(e,fmode)) t p in
 			let e = mk (TField(e,fmode)) t p in
 			let ethis = get_this ctx p in
 			let ethis = get_this ctx p in
 			let ethis = {ethis with etype = TAbstract(a,List.map (fun _ -> mk_mono()) a.a_types)} in
 			let ethis = {ethis with etype = TAbstract(a,List.map (fun _ -> mk_mono()) a.a_types)} in
@@ -1003,7 +1008,7 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode =
 		| FunMember | FunConstructor -> ()
 		| FunMember | FunConstructor -> ()
 		| FunMemberAbstract -> error "Cannot access super inside an abstract function" p
 		| FunMemberAbstract -> error "Cannot access super inside an abstract function" p
 		| FunStatic -> error "Cannot access super inside a static function" p;
 		| FunStatic -> error "Cannot access super inside a static function" p;
-		| FunMemberLocal -> error "Cannot access super inside a local function" p);
+		| FunMemberClassLocal | FunMemberAbstractLocal -> error "Cannot access super inside a local function" p);
 		if mode <> MSet && ctx.in_super_call then ctx.in_super_call <- false;
 		if mode <> MSet && ctx.in_super_call then ctx.in_super_call <- false;
 		AKExpr (mk (TConst TSuper) t p)
 		AKExpr (mk (TConst TSuper) t p)
 	| "null" ->
 	| "null" ->
@@ -2819,12 +2824,13 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				| TDynamic _ -> "",t
 				| TDynamic _ -> "",t
 				| _ -> error "Catch type must be a class, an enum or Dynamic" (pos e)
 				| _ -> error "Catch type must be a class, an enum or Dynamic" (pos e)
 			in
 			in
-			let name,t = loop t in
+			let name,t2 = loop t in
 			if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p;
 			if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p;
-			check_unreachable acc t (pos e);
+			check_unreachable acc t2 (pos e);
 			let locals = save_locals ctx in
 			let locals = save_locals ctx in
 			let v = add_local ctx v t in
 			let v = add_local ctx v t in
 			let e = type_expr ctx e with_type in
 			let e = type_expr ctx e with_type in
+			v.v_type <- t2;
 			locals();
 			locals();
 			if with_type <> NoValue then unify ctx e.etype e1.etype e.epos;
 			if with_type <> NoValue then unify ctx e.etype e1.etype e.epos;
 			if PMap.mem name ctx.locals then error ("Local variable " ^ name ^ " is preventing usage of this type here") e.epos;
 			if PMap.mem name ctx.locals then error ("Local variable " ^ name ^ " is preventing usage of this type here") e.epos;
@@ -2978,7 +2984,12 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				if v.[0] = '$' then display_error ctx "Variable names starting with a dollar are not allowed" p;
 				if v.[0] = '$' then display_error ctx "Variable names starting with a dollar are not allowed" p;
 				Some (add_local ctx v ft)
 				Some (add_local ctx v ft)
 		) in
 		) in
-		let e , fargs = Typeload.type_function ctx args rt (match ctx.curfun with FunStatic -> FunStatic | _ -> FunMemberLocal) f false p in
+		let curfun = match ctx.curfun with
+			| FunStatic -> FunStatic
+			| FunMemberAbstract -> FunMemberAbstractLocal
+			| _ -> FunMemberClassLocal
+		in
+		let e , fargs = Typeload.type_function ctx args rt curfun f false p in
 		ctx.type_params <- old;
 		ctx.type_params <- old;
 		let f = {
 		let f = {
 			tf_args = fargs;
 			tf_args = fargs;
@@ -3281,7 +3292,12 @@ and type_expr ctx (e,p) (with_type:with_type) =
 					| TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx c e
 					| TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx c e
 					| _ -> e)
 					| _ -> e)
 			| (Meta.This,_,_) ->
 			| (Meta.This,_,_) ->
-				List.hd ctx.this_stack
+				let e = List.hd ctx.this_stack in
+				let rec loop e = match e.eexpr with
+					| TConst TThis -> get_this ctx e.epos
+					| _ -> Type.map_expr loop e
+				in
+				loop e
 			| _ -> e()
 			| _ -> e()
 		in
 		in
 		ctx.meta <- old;
 		ctx.meta <- old;

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff