2
0
Эх сурвалжийг харах

Merge pull request #2877 from HaxeFoundation/development

3.1.3
Simon Krajewski 11 жил өмнө
parent
commit
7be30670b2
47 өөрчлөгдсөн 1419 нэмэгдсэн , 772 устгасан
  1. 7 1
      .travis.yml
  2. 83 2
      codegen.ml
  3. 5 3
      common.ml
  4. 22 1
      extra/CHANGES.txt
  5. 2 68
      filters.ml
  6. 18 3
      gencommon.ml
  7. 563 557
      gencpp.ml
  8. 2 2
      gencs.ml
  9. 8 2
      genjava.ml
  10. 8 11
      genjs.ml
  11. 9 2
      main.ml
  12. 5 0
      optimizer.ml
  13. 29 0
      std/cpp/NativeArray.hx
  14. 3 1
      std/cpp/vm/Debugger.hx
  15. 1 1
      std/flash/_std/Type.hx
  16. 2 2
      std/flash/_std/haxe/Json.hx
  17. 2 2
      std/flash/_std/haxe/ds/IntMap.hx
  18. 5 2
      std/haxe/Json.hx
  19. 28 10
      std/haxe/ds/Vector.hx
  20. 45 13
      std/haxe/format/JsonPrinter.hx
  21. 70 7
      std/haxe/io/Bytes.hx
  22. 1 0
      std/haxe/io/BytesBuffer.hx
  23. 83 29
      std/haxe/macro/Compiler.hx
  24. 1 1
      std/haxe/rtti/XmlParser.hx
  25. 2 2
      std/js/_std/haxe/Json.hx
  26. 3 3
      std/neko/net/ThreadRemotingServer.hx
  27. 1 1
      std/php/Boot.hx
  28. 6 6
      std/php/_std/haxe/Json.hx
  29. 1 1
      std/php/_std/sys/io/FileOutput.hx
  30. 1 1
      std/php/_std/sys/io/Process.hx
  31. 183 14
      tests/RunTravis.hx
  32. 7 7
      tests/unit/TestBytes.hx
  33. 1 0
      tests/unit/compile-each.hxml
  34. 1 1
      tests/unit/issues/Issue2619.hx
  35. 0 0
      tests/unit/issues/Issue2718.hx.disabled
  36. 22 0
      tests/unit/issues/Issue2823.hx
  37. 33 0
      tests/unit/issues/Issue2828.hx
  38. 37 0
      tests/unit/issues/Issue2835.hx
  39. 11 0
      tests/unit/issues/Issue2844.hx
  40. 9 0
      tests/unit/issues/Issue2845.hx
  41. 20 0
      tests/unit/issues/Issue2859.hx
  42. 44 0
      tests/unit/issues/Issue2874.hx
  43. 2 0
      tests/unit/unit.hxproj
  44. 1 1
      type.ml
  45. 2 1
      typecore.ml
  46. 1 1
      typeload.ml
  47. 29 13
      typer.ml

+ 7 - 1
.travis.yml

@@ -17,6 +17,11 @@ env:
     - TARGET=java
     - TARGET=cs
     - TARGET=flash8
+    - TARGET=polygonal-ds
+    - TARGET=flambe
+    - TARGET=hxtemplo
+    - TARGET=munit
+    - TARGET=openfl-samples
 
 matrix:
   fast_finish: true
@@ -35,5 +40,6 @@ script:
   - sudo make install
   - cd tests/
   - mkdir ~/haxelib && haxelib setup ~/haxelib
+  - haxelib git hx-yaml https://github.com/mikestead/hx-yaml master src
   - 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}
 			| 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
-					| TAbstract({a_impl = Some c} as a,_) ->
+					| TAbstract({a_impl = Some c} as a,tl) ->
 						begin try
 							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 ->
 							e
 						end
@@ -1621,3 +1621,84 @@ module UnificationCallback = struct
 			| _ ->
 				check (Type.map_expr (run f) e)
 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
 		| DceDebug
 		| Debug
-		| DeprecationWarnings
 		| Display
 		| DllExport
 		| DllImport
@@ -201,7 +200,9 @@ module Define = struct
 		| NetTarget
 		| NoCompilation
 		| NoCOpt
+		| NoDeprecationWarnings
 		| NoFlashOverride
+		| NoDebug
 		| NoInline
 		| NoOpt
 		| NoPatternMatching
@@ -243,7 +244,6 @@ module Define = struct
 		| Dce -> ("dce","The current DCE mode")
 		| DceDebug -> ("dce_debug","Show DCE log")
 		| Debug -> ("debug","Activated when compiling with -debug")
-		| DeprecationWarnings -> ("deprecation-warnings","Warn if fields annotated with @:deprecated are used")
 		| Display -> ("display","Activated during completion")
 		| DllExport -> ("dll_export", "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")
 		| NoCompilation -> ("no-compilation","Disable CPP final compilation")
 		| 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")
 		| NoOpt -> ("no_opt","Disable optimizations")
 		| NoPatternMatching -> ("no_pattern_matching","Disable pattern matching")
@@ -890,7 +892,7 @@ let find_file ctx f =
 		(match r with
 		| None -> raise Not_found
 		| Some f -> 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:
 

+ 2 - 68
filters.ml

@@ -797,72 +797,6 @@ let rename_local_vars com e =
 	loop 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 =
 	begin match follow e.etype,follow t with
 		| TEnum _,TDynamic _ ->
@@ -1142,8 +1076,8 @@ let post_process_end() =
 let run com tctx main =
 	if com.display = DMUsage then
 		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 *)
  	let filters = [

+ 18 - 3
gencommon.ml

@@ -5714,6 +5714,9 @@ struct
         mk_cast to_t e)
       | TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from ->
         e
+      | TAbstract _, TInst({ cl_kind = KTypeParameter _ }, _)
+      | TInst({ cl_kind = KTypeParameter _ }, _), TAbstract _ ->
+        do_unsafe_cast()
       | TAbstract _, _
       | _, TAbstract _ ->
         (try
@@ -7358,6 +7361,14 @@ struct
         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 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 =
           {
@@ -7450,7 +7461,7 @@ struct
         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
           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 (maybe_cast (get_field cf cf_type this cl cf.cf_name ))
@@ -9154,11 +9165,15 @@ struct
               | (conds,e) :: tl ->
                 { eexpr = TIf(mk_many_cond conds, run e, Some(loop tl)); etype = e.etype; epos = e.epos }
               | [] -> match default with
-                | None -> gen.gcon.error "Empty switch" e.epos; assert false
+                | None ->
+									raise Exit
                 | Some d -> run d
             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
         | _ -> Type.map_expr run e
     in

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 563 - 557
gencpp.ml


+ 2 - 2
gencs.ml

@@ -1055,7 +1055,7 @@ let configure gen =
 						write w " += ";
 						expr_s w ev
 					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_" ->
 					let name = field_name f in
 					let propname = String.sub name 7 (String.length name - 7) in
@@ -1066,7 +1066,7 @@ let configure gen =
 						write w " -= ";
 						expr_s w ev
 					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_" ->
 					let name = field_name f 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));
     (* type parameters *)
     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;
     (if is_some cl.cl_super then print w " extends %s" (cl_p_to_string (get cl.cl_super)));
     (match cl.cl_implements with
@@ -2455,7 +2461,7 @@ let convert_java_enum ctx p pe =
     ) field.jf_flags;
 
     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 *)
       | AttrVisibleAnnotations ann ->
         List.iter (function

+ 8 - 11
genjs.ml

@@ -1223,7 +1223,7 @@ let generate com =
 
 		(* Wrap output in a closure *)
 		if (anyExposed && (Common.defined com Define.ShallowExpose)) then (
-			print ctx "var $hx_exports = {}";
+			print ctx "var $hx_exports = $hx_exports || {}";
 			ctx.separator <- true;
 			newline ctx
 		);
@@ -1231,18 +1231,15 @@ let generate com =
 		if (anyExposed && not (Common.defined com Define.ShallowExpose)) then print ctx "$hx_exports";
 		print ctx ") { \"use strict\"";
 		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
-		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;
 
 	(* TODO: fix $estr *)

+ 9 - 2
main.ml

@@ -45,7 +45,7 @@ exception Abort
 exception Completion of string
 
 
-let version = 3102
+let version = 3103
 let version_major = version / 1000
 let version_minor = (version mod 1000) / 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;
 	List.iter (fun f -> f()) (List.rev (!pre_compilation));
 	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
 		ctx.setup();
 		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
 				mk (TBlock (el_v @ [e])) tret e.epos
 		) 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 *)
 		if not has_params then
 			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
      *          - event, one of THREAD_CREATED, THREAD_TERMINATED,
      *            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,
      *            undefined if event is not THREAD_STOPPED
      *          - functionName, the function name at which the thread is
@@ -150,7 +152,7 @@ class Debugger
      *            undefined if event is not THREAD_STOPPED
      **/
     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);
     }

+ 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 {
-		var f = Reflect.field(e,constr);
+		var f = untyped e[constr];
 		if( f == null ) throw "No such constructor "+constr;
 		if( Reflect.isFunction(f) ) {
 			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
-	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();
 	}
 
-	public function set( key : Int, value : T ) : Void {
+	public inline function set( key : Int, value : T ) : Void {
 		untyped h[key] = value;
 	}
 
-	public function get( key : Int ) : Null<T> {
+	public inline function get( key : Int ) : Null<T> {
 		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
 		actual object to be encoded. The `replacer` function two parameters,
 		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;
 
+#if cpp
+using cpp.NativeArray;
+#end
+
 private typedef VectorData<T> = #if flash10
 	flash.Vector<T>
 #elseif neko
@@ -75,7 +79,11 @@ abstract Vector<T>(VectorData<T>) {
 		unspecified.
 	**/
 	@:arrayAccess public inline function get(index:Int):Null<T> {
+		#if cpp
+		return this.unsafeGet(index);
+		#else
 		return this[index];
+		#end
 	}
 
 	/**
@@ -85,7 +93,11 @@ abstract Vector<T>(VectorData<T>) {
 		unspecified.
 	**/
 	@:arrayAccess public inline function set(index:Int, val:T):T {
+		#if cpp
+		return this.unsafeSet(index,val);
+		#else
 		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,
 		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
 			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);
 		#elseif cs
 			cs.system.Array.Copy(cast src, srcPos,cast dest, destPos, len);
+		#elseif cpp
+			dest.toData().blit(destPos,src.toData(), srcPos,len);
 		#else
 			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.
 	**/
-	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
-		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 {
 
-	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);
 		return printer.buf.toString();
 	}
 
 	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
 	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.indent = space;
+		this.pretty = space != null;
+		this.nind = 0;
 
 		#if flash9
 		buf = new flash.utils.ByteArray();
@@ -22,6 +28,14 @@ class JsonPrinter {
 		buf = new StringBuf();
 		#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) {
 		if (replacer != null) v = replacer(k, v);
@@ -42,13 +56,20 @@ class JsonPrinter {
 			else if( c == Array ) {
 				var v : Array<Dynamic> = v;
 				addChar('['.code);
+
 				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);
@@ -105,15 +126,26 @@ class JsonPrinter {
 	}
 
 	function fieldsString( v : Dynamic, fields : Array<String> ) {
-		var first = true;
 		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);
 			if( Reflect.isFunction(value) ) continue;
-			if( first ) first = false else addChar(','.code);
+			if( i > 0 ) addChar(','.code) else nind++;
+			newl();
+			ipad();
 			quote(f);
 			addChar(':'.code);
+			if (pretty) addChar(' '.code);
 			write(f, value);
+			if (i == last)
+			{
+				nind--;
+				newl();
+				ipad();
+			}
 		}
 		addChar('}'.code);
 	}

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

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

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

@@ -47,6 +47,7 @@ class BytesBuffer {
 		b = untyped StringBuf.__make();
 		#elseif flash9
 		b = new flash.utils.ByteArray();
+		b.endian = flash.utils.Endian.LITTLE_ENDIAN;
 		#elseif php
 		b = "";
 		#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> ) {
 		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)
 			paths = [];
 		if (null != 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") ) {
 							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);
 					}
-				} 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
 
-}
+}

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

@@ -415,7 +415,7 @@ class XmlParser {
 			doc : doc,
 			get : if( x.has.get ) mkRights(x.att.get) 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(),
 			meta : meta,
 			overloads: overloads

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

@@ -33,8 +33,8 @@ class Json {
 	}
 
 	#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)

+ 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));
 		if( msgLen == null ) {
 			if( buf.get(pos) != 60 )
-				throw "Invalid remoting message '"+buf.readString(pos,len)+"'";
+				throw "Invalid remoting message '"+buf.getString(pos,len)+"'";
 			var p = pos;
 			while( p < len ) {
 				if( buf.get(p) == 0 )
@@ -81,7 +81,7 @@ class ThreadRemotingServer extends ThreadServer<haxe.remoting.SocketConnection,S
 				return null;
 			p -= pos;
 			return {
-				msg : buf.readString(pos,p),
+				msg : buf.getString(pos,p),
 				bytes : p + 1,
 			};
 		}
@@ -90,7 +90,7 @@ class ThreadRemotingServer extends ThreadServer<haxe.remoting.SocketConnection,S
 		if( buf.get(pos + msgLen-1) != 0 )
 			throw "Truncated message";
 		return {
-			msg : buf.readString(pos+2,msgLen-3),
+			msg : buf.getString(pos+2,msgLen-3),
 			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) {
-	return ($v >> $n) & (0x7fffffff >> ($n-1));
+	return ($v >= 0) ? ($v >> $n) : ($v >> $n) & (0x7fffffff >> ($n-1));
 }
 
 function _hx_string_call($s, $method, $params) {

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

@@ -32,11 +32,11 @@ class Json {
 		#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
-		return phpJsonEncode(value, replacer);
+		return phpJsonEncode(value, replacer, space);
 		#else
-		return haxe.format.JsonPrinter.print(value, replacer);
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 		#end
 	}
 
@@ -59,9 +59,9 @@ class Json {
 			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));
 		if (untyped __physeq__(json, false))
 			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 {
-		var s = b.readString(p, l);
+		var s = b.getString(p, l);
 		if(untyped __call__('feof', __f)) return throw new haxe.io.Eof();
 		var r = untyped __call__('fwrite', __f, s, l);
 		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 {
-		var s = b.readString(pos, l);
+		var s = b.getString(pos, l);
 		if(untyped __call__('feof', p)) return throw new haxe.io.Eof();
 		var r = untyped __call__('fwrite', p, s, l);
 		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.io.*;
 
+private typedef TravisConfig = {
+	before_install: Array<String>,
+	script: Array<String>
+}
+
 /**
 	Will be run by TravisCI.
 	See ".travis.yml" at project root for TravisCI settings.
@@ -32,6 +41,30 @@ class RunTravis {
 		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 {
 		Sys.putEnv("DISPLAY", ":99.0");
 		runCommand("sh", ["-e", "/etc/init.d/xvfb", "start"]);
@@ -73,6 +106,93 @@ class RunTravis {
 		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 {
 		var cwd = Sys.getCwd();
 		var unitDir = cwd + "unit/";
@@ -83,7 +203,6 @@ class RunTravis {
 			case "macro", null:
 				runCommand("haxe", ["compile-macro.hxml"]);
 
-
 				//generate documentation
 				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "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("neko", ["unit.n"]);
 			case "php":
-				runCommand("sudo", ["apt-get", "install", "php5", "-y"], true);
+				getPhpDependencies();
 				runCommand("haxe", ["compile-php.hxml"]);
 				runCommand("php", ["php/index.php"]);
 			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("./cpp/Test-debug", []);
 
@@ -141,12 +252,11 @@ class RunTravis {
 				Sys.setCwd(optDir);
 				runCommand("haxe", ["run.hxml"]);
 			case "java":
-				runCommand("haxelib", ["git", "hxjava", "https://github.com/HaxeFoundation/hxjava.git"], true);
+				getJavaDependencies();
 				runCommand("haxe", ["compile-java.hxml"]);
 				runCommand("java", ["-jar", "java/Test-Debug.jar"]);
 			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("mono", ["cs/bin/Test-Debug.exe"]);
@@ -177,6 +287,65 @@ class RunTravis {
 
 				runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
 				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:
 				throw "unknown target: " + target;
 		}

+ 7 - 7
tests/unit/TestBytes.hx

@@ -60,13 +60,13 @@ class TestBytes extends Test {
 		// readString
 		var bs = haxe.io.Bytes.ofString("One é accent");
 		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 :
 				Flash8 : ignore

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

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

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

@@ -1,7 +1,7 @@
 package unit.issues;
 import unit.Test;
 
-private abstract A(String) {
+private abstract A(String) to String {
 	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>
     <option directives="" />
     <option flashStrict="False" />
+    <option noInlineOnDebug="False" />
     <option mainClass="unit.Test" />
     <option enabledebug="False" />
     <option additional="" />
@@ -58,6 +59,7 @@
     <hidden path="runexe.n" />
     <hidden path="runjava.n" />
     <hidden path="server.bat" />
+    <hidden path="obj" />
   </hiddenPaths>
   <!-- Executed before build -->
   <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) ->
 		let ta1 = apply_params a1.a_types pl1 a1.a_this in
 		let ta2 = apply_params a2.a_types pl2 a2.a_this in
-		if 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;
 		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]

+ 2 - 1
typecore.ml

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

+ 1 - 1
typeload.ml

@@ -1099,7 +1099,7 @@ let set_heritance ctx c herits p =
 				intf.cl_build();
 				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 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;
 				c.cl_implements <- (intf, params) :: c.cl_implements;
 				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
 	| TTypeDecl s ->
 		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
 		| TEnum (e,params) ->
 			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
 					| TAbstract(a,pl) ->
 						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)
 					| _ ->
 						None
@@ -798,17 +800,20 @@ let get_this ctx p =
 	match ctx.curfun with
 	| FunStatic ->
 		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 ->
-				(* 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;
 				v
 			| Some v ->
 				ctx.locals <- PMap.add v.v_name v ctx.locals;
 				v
-		) in
+		in
 		mk (TLocal v) ctx.tthis p
 	| FunMemberAbstract ->
 		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
 	| Method m ->
 		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 ethis = get_this ctx p 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 -> ()
 		| FunMemberAbstract -> error "Cannot access super inside an abstract 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;
 		AKExpr (mk (TConst TSuper) t p)
 	| "null" ->
@@ -2819,12 +2824,13 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				| TDynamic _ -> "",t
 				| _ -> error "Catch type must be a class, an enum or Dynamic" (pos e)
 			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;
-			check_unreachable acc t (pos e);
+			check_unreachable acc t2 (pos e);
 			let locals = save_locals ctx in
 			let v = add_local ctx v t in
 			let e = type_expr ctx e with_type in
+			v.v_type <- t2;
 			locals();
 			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;
@@ -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;
 				Some (add_local ctx v ft)
 		) 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;
 		let f = {
 			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
 					| _ -> e)
 			| (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()
 		in
 		ctx.meta <- old;

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно