ソースを参照

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

Nicolas Cannasse 9 年 前
コミット
d9f61a4498
100 ファイル変更2585 行追加483 行削除
  1. 2 0
      .gitignore
  2. 89 8
      .travis.yml
  3. 114 64
      analyzer.ml
  4. 1 0
      ast.ml
  5. 25 10
      codegen.ml
  6. 7 39
      common.ml
  7. 17 18
      dce.ml
  8. BIN
      extra/haxeci_sec.gpg.enc
  9. BIN
      extra/haxeci_ssh.enc
  10. 1 1
      extra/release-checklist.txt
  11. 65 116
      filters.ml
  12. 1 4
      genas3.ml
  13. 1396 14
      gencpp.ml
  14. 2 2
      genjs.ml
  15. 5 2
      genswf9.ml
  16. 2 2
      interp.ml
  17. 2 2
      main.ml
  18. 17 26
      matcher.ml
  19. 30 26
      optimizer.ml
  20. 3 4
      parser.ml
  21. 1 1
      std/Map.hx
  22. 23 23
      std/StdTypes.hx
  23. 10 10
      std/Xml.hx
  24. 3 1
      std/cpp/_std/Reflect.hx
  25. 3 1
      std/cpp/_std/haxe/Int64.hx
  26. 12 0
      std/cpp/_std/sys/net/Socket.hx
  27. 2 2
      std/cs/io/NativeInput.hx
  28. 3 2
      std/cs/io/NativeOutput.hx
  29. 4 0
      std/flash/Boot.hx
  30. 74 0
      std/flash/_std/haxe/ds/IntMap.hx
  31. 75 0
      std/flash/_std/haxe/ds/UnsafeStringMap.hx
  32. 3 2
      std/haxe/Template.hx
  33. 1 1
      std/haxe/Timer.hx
  34. 11 10
      std/haxe/ds/Vector.hx
  35. 6 6
      std/haxe/macro/Context.hx
  36. 0 1
      std/js/_std/Type.hx
  37. 2 0
      std/js/html/ArrayBuffer.hx
  38. 2 0
      std/js/html/DataView.hx
  39. 4 2
      std/js/html/Float32Array.hx
  40. 4 2
      std/js/html/Float64Array.hx
  41. 4 2
      std/js/html/Uint8Array.hx
  42. 1 1
      std/js/html/compat/ArrayBuffer.hx
  43. 1 1
      std/js/html/compat/DataView.hx
  44. 1 1
      std/js/html/compat/Float32Array.hx
  45. 1 1
      std/js/html/compat/Float64Array.hx
  46. 1 1
      std/js/html/compat/Uint8Array.hx
  47. 1 1
      std/js/jquery/Helper.hx
  48. 7 3
      std/js/jquery/JQuery.hx
  49. 0 1
      std/js/jquery/jquery-1.11.3.min.js
  50. 1 0
      std/js/jquery/jquery-1.12.1.min.js
  51. 0 1
      std/neko/_std/String.hx
  52. 2 2
      std/neko/_std/Type.hx
  53. 12 0
      std/neko/_std/sys/net/Socket.hx
  54. 5 16
      std/python/io/NativeInput.hx
  55. 2 6
      std/python/io/NativeOutput.hx
  56. 90 23
      tests/RunCi.hx
  57. 11 0
      tests/misc/projects/Issue2148/Main1.hx
  58. 2 0
      tests/misc/projects/Issue2148/compile1-fail.hxml
  59. 1 0
      tests/misc/projects/Issue2148/compile1-fail.hxml.stderr
  60. 8 0
      tests/misc/projects/Issue2232/Main1.hx
  61. 8 0
      tests/misc/projects/Issue2232/Main2.hx
  62. 3 0
      tests/misc/projects/Issue2232/compile1-fail.hxml
  63. 2 0
      tests/misc/projects/Issue2232/compile1-fail.hxml.stderr
  64. 3 0
      tests/misc/projects/Issue2232/compile2-fail.hxml
  65. 1 0
      tests/misc/projects/Issue2232/compile2-fail.hxml.stderr
  66. 0 0
      tests/misc/projects/Issue2278/compile.hxml.disabled
  67. 5 0
      tests/misc/projects/Issue3192/Main1.hx
  68. 2 0
      tests/misc/projects/Issue3192/compile1-fail.hxml
  69. 1 0
      tests/misc/projects/Issue3192/compile1-fail.hxml.stderr
  70. 0 2
      tests/misc/projects/Issue3782/compile-fail.hxml
  71. 3 0
      tests/misc/projects/Issue3782/compile-fail.hxml.disabled
  72. 21 0
      tests/misc/projects/Issue4448/Main1.hx
  73. 2 0
      tests/misc/projects/Issue4448/compile1-fail.hxml
  74. 3 0
      tests/misc/projects/Issue4448/compile1-fail.hxml.stderr
  75. 6 0
      tests/misc/projects/Issue4671/Main1.hx
  76. 6 0
      tests/misc/projects/Issue4671/Main2.hx
  77. 2 0
      tests/misc/projects/Issue4671/compile1-fail.hxml
  78. 1 0
      tests/misc/projects/Issue4671/compile1-fail.hxml.stderr
  79. 2 0
      tests/misc/projects/Issue4671/compile2-fail.hxml
  80. 1 0
      tests/misc/projects/Issue4671/compile2-fail.hxml.stderr
  81. 6 0
      tests/misc/projects/Issue4816/Main1.hx
  82. 2 0
      tests/misc/projects/Issue4816/compile1-fail.hxml
  83. 1 0
      tests/misc/projects/Issue4816/compile1-fail.hxml.stderr
  84. 13 7
      tests/optimization/src/TestJs.hx
  85. 2 2
      tests/unit/compile-hl.hxml
  86. 30 0
      tests/unit/issues/Issue3762.hx
  87. 17 0
      tests/unit/src/unit/issues/Issue3192.hx
  88. 23 0
      tests/unit/src/unit/issues/Issue3528.hx
  89. 21 0
      tests/unit/src/unit/issues/Issue4121.hx
  90. 68 0
      tests/unit/src/unit/issues/Issue4526.hx
  91. 11 0
      tests/unit/src/unit/issues/Issue4777.hx
  92. 13 0
      tests/unit/src/unit/issues/Issue4843.hx
  93. 28 0
      tests/unit/src/unit/issues/Issue4862.hx
  94. 21 0
      tests/unit/src/unit/issues/Issue4867.hx
  95. 23 0
      tests/unit/src/unit/issues/Issue4885.hx
  96. 22 0
      tests/unit/src/unit/issues/Issue4886.hx
  97. 12 0
      tests/unit/src/unit/issues/Issue4889.hx
  98. 14 0
      tests/unit/src/unit/issues/misc/Issue4121Macro.hx
  99. 12 9
      tests/unit/src/unitstd/haxe/ds/Vector.unit.hx
  100. 1 1
      tests/unit/unit-js.html

+ 2 - 0
.gitignore

@@ -14,6 +14,8 @@
 /extra/bintray.json
 /extra/git-archive-all
 /extra/deploy_key
+/extra/*_sec.gpg
+/extra/*_ssh
 
 /version.ml
 /haxe

+ 89 - 8
.travis.yml

@@ -15,9 +15,14 @@ env:
     - secure: "VBJDQNJ9uvdt0aszo7oU3txuRvjkuLmuHZGOkrd4wE/5B4sX5jzx/+dnrKcNTXJCmQ/rVLuMu9GyxqVjNHlzce678voxdQNOtNkNgpkr1qN9/A9rRnCp77hH27ErdthpWxbmcnE62hAJ83TIKSvn//5lAkx4sMCKS1NXEWQ5qec="
     # HAXECI_GH_TOKEN: haxe-ci Github personal access token
     - secure: "TpEMYTLgNrVD7kR6hs6EwyWNXUxnfV6XO5MGvYQncKXB1N65PG18n4WQFhnKaH8C2QTFE7dq7688ooXGzwWeoT9WAOBey10jP1f7LXEAjMGAUA4vh2zS93qBZ92ZgzCDZnQN7ZOTQGocwU6Xolu+7/6hP2M8041HBixmFuNkXF4="
+    # PPA configs
+    - PPA="ppa:haxe/snapshots"
+    - DEBFULLNAME="Haxe CI Bot"
+    - DEBEMAIL="[email protected]"
 
 sudo: false
 addons:
+  ssh_known_hosts: haxe.org
   apt:
     packages: &apt_common
       - ocaml-native-compilers
@@ -29,7 +34,7 @@ apt_targets:
   - &apt_cpp    [*apt_common, gcc-multilib, g++-multilib]
   - &apt_cs     [*apt_common, mono-devel, mono-mcs]
   - &apt_python [*apt_common, python3]
-  - &apt_flash  [*apt_common, libgd2-xpm, ia32-libs, ia32-libs-multiarch]
+  - &apt_flash  [*apt_common, "libcurl3:i386", "libglib2.0-0:i386", "libx11-6:i386", "libxext6:i386", "libxt6:i386", "libxcursor1:i386", "libnss3:i386", "libgtk2.0-0:i386"]
 
 matrix:
   include:
@@ -37,7 +42,82 @@ matrix:
     # linux #
     #########
     - os: linux
-      env: TEST=hl
+      env: TEST=third-party
+      language: php
+      php: 5.4
+      addons: {apt: {packages: [*apt_cpp, *apt_cs, *apt_python]}}
+    - os: linux
+      env: TEST=macro
+      addons: {apt: {packages: [*apt_cs, *apt_python]}}
+    - os: linux
+      sudo: required
+      dist: trusty
+      env:
+        - TEST=neko
+        - DEPLOY=1
+        - BINTRAY=1
+        # haxeci_decrypt (Deploy source package to ppa:haxe/snapshots.)
+        - secure: "Mw3p6bDZuqVQ6u7GrwLQfje5hhIOA4+mdqqLXYHP79UKdhgqb91Dn6IbG9vQ1VXVe64W4YZbQAMBMMRX5kEPDl6JvTVGSBhg00Mi69oO5qrCMcBI6f9FntG72YaVvLf+PA7co+vKrnJzaP2M9pe4SH9Ztbhy0YNxULp7NQ8FLsM="
+        # deploy_key_decrypt (Deploy doc to api.haxe.org.)
+        - secure: "A75uYqU0Xz6plIgSewEs0QQWe472dCMb9kf3j7Hx0DS7dApXgx8++189sw9Sv0wam5KPtbcIM292MucjGCb5zocVj9xCUVgajhEA0QpTuDMBjk/cg3ClWCGjfybaCl2E5LLdUs7Zy4b4oNWtVikOWLWJ4sC1kaarR9p6kv8yYZg="
+      before_script:
+        - travis_retry sudo apt-get install mysql-server -y
+        - mysql -u root -e "create user travis@localhost identified by '';"
+    - os: linux
+      env:
+        - TEST=js
+        - SAUCE=1
+      addons: {apt: {packages: *apt_common}, sauce_connect: true}
+    - os: linux
+      env: TEST=php
+      language: php
+      php: 5.4
+    - os: linux
+      env: TEST=cpp
+      addons: {apt: {packages: *apt_cpp}}
+    - os: linux
+      env: TEST=flash9
+      addons: {apt: {packages: *apt_flash}}
+    - os: linux
+      env: TEST=as3
+      addons: {apt: {packages: *apt_flash}}
+    - os: linux
+      env: TEST=java
+    - os: linux
+      env: TEST=cs
+      addons: {apt: {packages: *apt_cs}}
+    - os: linux
+      env: TEST=python
+      addons: {apt: {packages: *apt_python}}
+
+    #######
+    # osx #
+    #######
+    - os: osx
+      env: TEST=third-party
+    - os: osx
+      env: TEST=macro
+    - os: osx
+      env:
+        - TEST=neko
+        - DEPLOY=1
+        - BINTRAY=1
+    - os: osx
+      env: TEST=js
+    - os: osx
+      env: TEST=php
+    - os: osx
+      env: TEST=cpp
+    - os: osx
+      env: TEST=flash9
+    - os: osx
+      env: TEST=as3
+    - os: osx
+      env: TEST=java
+    - os: osx
+      env: TEST=cs
+    - os: osx
+      env: TEST=python
 
 install:
   # Install haxe and neko dependencies
@@ -58,16 +138,17 @@ install:
       travis_retry brew install neko --HEAD;
     fi
 
-before_script:
+script:
+  # setup database
   - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
-    travis_retry brew install mysql &&
-    mysql.server start;
-    mysql -u root -e "create user if not exists travis@localhost identified by '';";
+      travis_retry brew install mysql &&
+      mysql.server start;
+      mysql -u root -e "create user if not exists travis@localhost identified by '';";
     fi
   - mysql -u root -e "CREATE DATABASE haxe_test;"
   - mysql -u root -e "grant all on haxe_test.* to travis@localhost;"
-
-script:
+  # start ssh-agent for deployment to haxe.org
+  - eval `ssh-agent -s`
   - make package_src -s
   - make -s
   - make tools -s

+ 114 - 64
analyzer.ml

@@ -93,7 +93,7 @@ let can_throw e =
 	let rec loop e = match e.eexpr with
 		| TConst _ | TLocal _ | TTypeExpr _ | TFunction _ | TBlock _ -> ()
 		| TCall _ | TNew _ | TThrow _ | TCast(_,Some _) -> raise Exit
-		| TField _ -> raise Exit (* sigh *)
+		| TField _ | TArray _ -> raise Exit (* sigh *)
 		| _ -> Type.iter loop e
 	in
 	try
@@ -155,6 +155,44 @@ let is_ref_type = function
 	| TAbstract({a_path=["hl";"types"],"Ref"},_) -> true
 	| _ -> false
 
+let type_change_ok com t1 t2 =
+	if t1 == t2 then
+		true
+	else begin
+		let rec map t = match t with
+			| TMono r -> (match !r with None -> t_dynamic | Some t -> map t)
+			| _ -> Type.map map t
+		in
+		let t1 = map t1 in
+		let t2 = map t2 in
+		let rec is_nullable_or_whatever = function
+			| TMono r ->
+				(match !r with None -> false | Some t -> is_nullable_or_whatever t)
+			| TType ({ t_path = ([],"Null") },[_]) ->
+				true
+			| TLazy f ->
+				is_nullable_or_whatever (!f())
+			| TType (t,tl) ->
+				is_nullable_or_whatever (apply_params t.t_params tl t.t_type)
+			| TFun _ ->
+				false
+			| TInst ({ cl_kind = KTypeParameter _ },_) ->
+				false
+			| TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta ->
+				not (Meta.has Meta.NotNull a.a_meta)
+			| TAbstract (a,tl) ->
+				not (Meta.has Meta.NotNull a.a_meta) && is_nullable_or_whatever (apply_params a.a_params tl a.a_this)
+			| _ ->
+				true
+		in
+		(* Check equality again to cover cases where TMono became t_dynamic *)
+		t1 == t2 || match follow t1,follow t2 with
+			| TDynamic _,_ | _,TDynamic _ -> false
+			| _ ->
+				if com.config.pf_static && is_nullable_or_whatever t1 <> is_nullable_or_whatever t2 then false
+				else type_iseq t1 t2
+	end
+
 let dynarray_map f d =
 	DynArray.iteri (fun i e -> DynArray.unsafe_set d i (f e)) d
 
@@ -217,8 +255,6 @@ module Config = struct
 						true
 					else
 						loop ml
-				| (Meta.HasUntyped,_,_) :: _ ->
-					true
 				| _ :: ml ->
 					loop ml
 				| [] ->
@@ -228,9 +264,9 @@ module Config = struct
 		with Not_found ->
 			false
 
-	let get_base_config com optimize =
+	let get_base_config com =
 		{
-			optimize = optimize;
+			optimize = not (Common.defined com Define.NoAnalyzer);
 			const_propagation = not (Common.raw_defined com "analyzer-no-const-propagation");
 			copy_propagation = not (Common.raw_defined com "analyzer-no-copy-propagation");
 			code_motion = Common.raw_defined com "analyzer-code-motion";
@@ -262,12 +298,14 @@ module Config = struct
 					| EConst (Ident s) when s = flag_dot_debug -> {config with dot_debug = true}
 					| _ -> config
 				) config el
+			| (Meta.HasUntyped,_,_) ->
+				{config with optimize = false}
 			| _ ->
 				config
 		) config meta
 
 	let get_class_config com c =
-		let config = get_base_config com true in
+		let config = get_base_config com in
 		update_config_from_meta config c.cl_meta
 
 	let get_field_config com c cf =
@@ -451,15 +489,11 @@ module Fusion = struct
 				Type.iter loop e
 		in
 		loop e;
-		let type_change_ok t1 t2 = t1 == t2 || match follow t1,follow t2 with
-			| TMono _,_ | _,TMono _ -> not com.config.pf_static
-			| TDynamic _,_ | _,TDynamic _ -> false
-			| _ ->
-				if com.config.pf_static && is_null t1 <> is_null t2 then false
-				else type_iseq t1 t2
-		in
 		let can_be_fused v e =
-			get_num_uses v <= 1 && get_num_writes v = 0 && can_be_used_as_value com e && (Meta.has Meta.CompilerGenerated v.v_meta || config.Config.optimize && config.Config.fusion && type_change_ok v.v_type e.etype && v.v_extra = None)
+			let b = get_num_uses v <= 1 && get_num_writes v = 0 && can_be_used_as_value com e && (Meta.has Meta.CompilerGenerated v.v_meta || config.Config.optimize && config.Config.fusion && type_change_ok com v.v_type e.etype && v.v_extra = None) in
+			(* let st = s_type (print_context()) in *)
+			(* if e.epos.pfile = "src/Main.hx" then print_endline (Printf.sprintf "%s: %i %i %b %s %s (%b %b %b %b %b) -> %b" v.v_name (get_num_uses v) (get_num_writes v) (can_be_used_as_value com e) (st v.v_type) (st e.etype) (Meta.has Meta.CompilerGenerated v.v_meta) config.Config.optimize config.Config.fusion (type_change_ok com v.v_type e.etype) (v.v_extra = None) b); *)
+			b
 		in
 		let rec fuse acc el = match el with
 			| ({eexpr = TVar(v1,None)} as e1) :: {eexpr = TBinop(OpAssign,{eexpr = TLocal v2},e2)} :: el when v1 == v2 ->
@@ -907,6 +941,7 @@ type analyzer_context = {
 	config : Config.t;
 	graph : Graph.t;
 	temp_var_name : string;
+	is_real_function : bool;
 	mutable entry : BasicBlock.t;
 	mutable has_unbound : bool;
 	mutable loop_counter : int;
@@ -1102,6 +1137,25 @@ module TexprTransformer = struct
 			let e = List.fold_left (fun e f -> f e) e (List.rev fl) in
 			bb,e
 		and declare_var_and_assign bb v e =
+			let rec loop bb e = match e.eexpr with
+				| TParenthesis e1 ->
+					loop bb e1
+				| TBlock el ->
+					let rec loop2 bb el = match el with
+						| [e] ->
+							bb,e
+						| e1 :: el ->
+							let bb = block_element bb e1 in
+							loop2 bb el
+						| [] ->
+							assert false
+					in
+					let bb,e = loop2 bb el in
+					loop bb e
+				| _ ->
+					bb,e
+			in
+			let bb,e = loop bb e in
 			begin match follow v.v_type with
 				| TAbstract({a_path=[],"Void"},_) -> error "Cannot use Void as value" e.epos
 				| _ -> ()
@@ -1450,6 +1504,15 @@ module TexprTransformer = struct
 
 	let from_texpr com config e =
 		let g = Graph.create e.etype e.epos in
+		let tf,is_real_function = match e.eexpr with
+			| TFunction tf ->
+				tf,true
+			| _ ->
+				(* Wrap expression in a function so we don't have to treat it as a special case throughout. *)
+				let e = mk (TReturn (Some e)) t_dynamic e.epos in
+				let tf = { tf_args = []; tf_type = e.etype; tf_expr = e; } in
+				tf,false
+		in
 		let ctx = {
 			com = com;
 			config = config;
@@ -1457,6 +1520,7 @@ module TexprTransformer = struct
 			(* For CPP we want to use variable names which are "probably" not used by users in order to
 			   avoid problems with the debugger, see https://github.com/HaxeFoundation/hxcpp/issues/365 *)
 			temp_var_name = (match com.platform with Cpp -> "_hx_tmp" | _ -> "tmp");
+			is_real_function = is_real_function;
 			entry = g.g_unreachable;
 			has_unbound = false;
 			loop_counter = 0;
@@ -1464,12 +1528,7 @@ module TexprTransformer = struct
 			scope_depth = 0;
 			scopes = [0];
 		} in
-		let bb_func,bb_exit = match e.eexpr with
-			| TFunction tf ->
-				func ctx g.g_root tf e.etype e.epos;
-			| _ ->
-				raise Exit
-		in
+		let bb_func,bb_exit = func ctx g.g_root tf e.etype e.epos in
 		ctx.entry <- bb_func;
 		close_node g g.g_root;
 		finalize g bb_exit;
@@ -1890,18 +1949,6 @@ module DataFlow (M : DataFlowApi) = struct
 		M.commit ctx
 end
 
-let type_iseq_strict_no_mono com t1 t2 =
-	let rec map t = match follow t with
-		| TMono _ -> t_dynamic
-		| _ -> Type.map map t
-	in
-	let t1 = map t1 in
-	let t2 = map t2 in
-	if com.Common.config.pf_static then
-		type_iseq_strict t1 t2
-	else
-		type_iseq t1 t2
-
 (*
 	ConstPropagation implements sparse conditional constant propagation using the DataFlow algorithm. Its lattice consists of
 	constants and enum values, but only the former are propagated. Enum values are treated as immutable data tuples and allow
@@ -2022,7 +2069,7 @@ module ConstPropagation = DataFlow(struct
 				raise Not_found
 			| Const ct ->
 				let e' = Codegen.type_constant ctx.com (tconst_to_const ct) e.epos in
-				if not (type_iseq_strict_no_mono ctx.com e'.etype e.etype) then raise Not_found;
+				if not (type_change_ok ctx.com e'.etype e.etype) then raise Not_found;
 				e'
 		in
 		let rec commit e = match e.eexpr with
@@ -2116,7 +2163,7 @@ module CopyPropagation = DataFlow(struct
 						raise Not_found
 					in
 					let v' = match lat with Local v -> v | _ -> leave() in
-					if not (type_iseq_strict_no_mono ctx.com v'.v_type v.v_type) then leave();
+					if not (type_change_ok ctx.com v'.v_type v.v_type) then leave();
 					let v'' = get_var_origin ctx.graph v' in
 					(* This restriction is in place due to how we currently reconstruct the AST. Multiple SSA-vars may be turned back to
 					   the same origin var, which creates interference that is not tracked in the analysis. We address this by only
@@ -2819,47 +2866,50 @@ module Run = struct
 
 	let roundtrip com config e =
 		let ctx = there com config e in
-		let e = back_again ctx in
-		e
+		back_again ctx
 
 	let run_on_expr com config e =
-		try
-			let ctx = there com config e in
-			if config.optimize && not ctx.has_unbound then begin
-				with_timer "analyzer-ssa-apply" (fun () -> Ssa.apply ctx);
-				if config.const_propagation then with_timer "analyzer-const-propagation" (fun () -> ConstPropagation.apply ctx);
-				if config.copy_propagation then with_timer "analyzer-copy-propagation" (fun () -> CopyPropagation.apply ctx);
-				if config.code_motion then with_timer "analyzer-code-motion" (fun () -> CodeMotion.apply ctx);
-				with_timer "analyzer-local-dce" (fun () -> LocalDce.apply ctx);
-			end;
-			let e = back_again ctx in
-			Some ctx,e
-		with Exit ->
-			None,e
+		let ctx = there com config e in
+		if config.optimize && not ctx.has_unbound then begin
+			with_timer "analyzer-ssa-apply" (fun () -> Ssa.apply ctx);
+			if config.const_propagation then with_timer "analyzer-const-propagation" (fun () -> ConstPropagation.apply ctx);
+			if config.copy_propagation then with_timer "analyzer-copy-propagation" (fun () -> CopyPropagation.apply ctx);
+			if config.code_motion then with_timer "analyzer-code-motion" (fun () -> CodeMotion.apply ctx);
+			with_timer "analyzer-local-dce" (fun () -> LocalDce.apply ctx);
+		end;
+		ctx,back_again ctx
 
 	let run_on_field ctx config c cf = match cf.cf_expr with
 		| Some e when not (is_ignored cf.cf_meta) && not (Codegen.is_removable_field ctx cf) ->
 			let config = update_config_from_meta config cf.cf_meta in
-			let e =  match run_on_expr ctx.Typecore.com config e with
-				| None,e -> e
-				| Some ctx,e ->
-					if config.dot_debug then Debug.dot_debug ctx c cf;
-					e
-			in
+			let ctx,e = run_on_expr ctx.Typecore.com config e in
+			if config.dot_debug then Debug.dot_debug ctx c cf;
+			let e = if ctx.is_real_function then
+				e
+			else begin
+				(* Get rid of the wrapping function and its return expressions. *)
+				let rec loop first e = match e.eexpr with
+					| TReturn (Some e) -> e
+					| TFunction tf when first -> loop false tf.tf_expr
+					| TFunction _ -> e
+					| _ -> Type.map_expr (loop first) e
+				in
+				loop true e
+			end in
 			cf.cf_expr <- Some e;
 		| _ -> ()
 
 	let run_on_class ctx config c =
 		let config = update_config_from_meta config c.cl_meta in
-		let process_field cf = match cf.cf_kind with
-			| Method _ -> run_on_field ctx config c cf
-			| _ -> ()
+		let process_field stat cf = match cf.cf_kind with
+			| Var _ when not stat -> ()
+			| _ -> run_on_field ctx config c cf
 		in
-		List.iter process_field c.cl_ordered_fields;
-		List.iter process_field c.cl_ordered_statics;
+		List.iter (process_field false) c.cl_ordered_fields;
+		List.iter (process_field true) c.cl_ordered_statics;
 		(match c.cl_constructor with
 		| None -> ()
-		| Some f -> process_field f)
+		| Some f -> process_field false f)
 
 	let run_on_type ctx config t =
 		match t with
@@ -2869,9 +2919,9 @@ module Run = struct
 		| TTypeDecl _ -> ()
 		| TAbstractDecl _ -> ()
 
-	let run_on_types ctx full types =
+	let run_on_types ctx types =
 		let com = ctx.Typecore.com in
-		let config = get_base_config com full in
-		if full && config.purity_inference then Purity.infer com;
+		let config = get_base_config com in
+		if config.optimize && config.purity_inference then Purity.infer com;
 		List.iter (run_on_type ctx config) types
 end

+ 1 - 0
ast.ml

@@ -24,6 +24,7 @@ type pos = {
 }
 
 module IntMap = Map.Make(struct type t = int let compare a b = a - b end)
+module StringMap = Map.Make(struct type t = string let compare = String.compare end)
 
 module Meta = struct
 	type strict_meta =

+ 25 - 10
codegen.ml

@@ -481,7 +481,7 @@ let rec build_generic ctx c p tl =
 						apply_params c.cl_params tl (TInst(cs,pl))
 				in
 				let ts = follow (find_class gctx.subst) in
-				let cs,pl = Typeload.check_extends ctx c ts p in
+				let cs,pl = Typeload.Inheritance.check_extends ctx c ts p in
 				match cs.cl_kind with
 				| KGeneric ->
 					(match build_generic ctx cs p pl with
@@ -709,15 +709,17 @@ let build_instance ctx mtype p =
 	| TAbstractDecl a ->
 		a.a_params, a.a_path, (fun tl -> TAbstract(a,tl))
 
-let on_inherit ctx c p h =
-	match h with
-	| HExtends { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
+let on_inherit ctx c p (is_extends,tp) =
+	if not is_extends then
+		true
+	else match tp with
+	| { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
 		extend_remoting ctx c t p false true;
 		false
-	| HExtends { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
+	| { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
 		extend_remoting ctx c t p true true;
 		false
-	| HExtends { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
+	| { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
 		extend_xml_proxy ctx c t file p;
 		true
 	| _ ->
@@ -880,11 +882,24 @@ module AbstractCast = struct
 			| _,[],_ -> pl
 			| _,el,_ ->
 				let relevant = Hashtbl.create 0 in
-				List.iter (fun e -> match fst e with
-					| EConst(Ident s) -> Hashtbl.replace relevant s true
-					| _ -> error "Type parameter expected" (pos e)
+				List.iter (fun e ->
+					let rec loop f e = match fst e with
+						| EConst(Ident s) ->
+							Hashtbl.replace relevant s f
+						| EMeta((Meta.Custom ":followWithAbstracts",_,_),e1) ->
+							loop Abstract.follow_with_abstracts e1;
+						| _ ->
+							error "Type parameter expected" (pos e)
+					in
+					loop (fun t -> t) e
 				) el;
-				let tl = List.map2 (fun (n,_) t -> if Hashtbl.mem relevant n || not (has_mono t) then t else t_dynamic) a.a_params pl in
+				let tl = List.map2 (fun (n,_) t ->
+					try
+						(Hashtbl.find relevant n) t
+					with Not_found ->
+						if not (has_mono t) then t
+						else t_dynamic
+				) a.a_params pl in
 				if com.platform = Js && a.a_path = ([],"Map") then begin match tl with
 					| t1 :: _ ->
 						let rec loop stack t =

+ 7 - 39
common.ml

@@ -75,12 +75,6 @@ type platform_config = {
 	pf_static : bool;
 	(** has access to the "sys" package *)
 	pf_sys : bool;
-	(** local variables are block-scoped *)
-	pf_locals_scope : bool;
-	(** captured local variables are scoped *)
-	pf_captured_scope : bool;
-	(** generated locals must be absolutely unique wrt the current function *)
-	pf_unique_locals : bool;
 	(** captured variables handling (see before) *)
 	pf_capture_policy : capture_policy;
 	(** when calling a method with optional args, do we replace the missing args with "null" constants *)
@@ -170,11 +164,12 @@ module Define = struct
 	type strict_defined =
 		| AbsolutePath
 		| AdvancedTelemetry
-		| Analyzer
+		(* | Analyzer *)
 		| As3
 		| CheckXmlProxy
 		| CoreApi
 		| CoreApiSerialize
+		| CppAst
 		| Cppia
 		| Dce
 		| DceDebug
@@ -215,6 +210,7 @@ module Define = struct
 		| NetworkSandbox
 		| NetVer
 		| NetTarget
+		| NoAnalyzer
 		| NoCompilation
 		| NoCOpt
 		| NoDeprecationWarnings
@@ -255,12 +251,13 @@ module Define = struct
 	let infos = function
 		| AbsolutePath -> ("absolute_path","Print absolute file path in trace output")
 		| AdvancedTelemetry -> ("advanced-telemetry","Allow the SWF to be measured with Monocle tool")
-		| Analyzer -> ("analyzer","Use static analyzer for optimization (experimental)")
+		(* | Analyzer -> ("analyzer","Use static analyzer for optimization (experimental)") *)
 		| As3 -> ("as3","Defined when outputing flash9 as3 source code")
 		| CheckXmlProxy -> ("check_xml_proxy","Check the used fields of the xml proxy")
 		| CoreApi -> ("core_api","Defined in the core api context")
 		| CoreApiSerialize -> ("core_api_serialize","Mark some generated core api classes with the Serializable attribute on C#")
-		| Cppia -> ("cppia", "Generate experimental cpp instruction assembly")
+		| CppAst -> ("cppast", "Generate experimental cpp code")
+		| Cppia -> ("cppia", "Generate cpp instruction assembly")
 		| Dce -> ("dce","<mode:std|full||no> Set the dead code elimination mode (default std)")
 		| DceDebug -> ("dce_debug","Show DCE log")
 		| Debug -> ("debug","Activated when compiling with -debug")
@@ -301,6 +298,7 @@ module Define = struct
 		| NekoSource -> ("neko_source","Output neko source instead of bytecode")
 		| NekoV1 -> ("neko_v1","Keep Neko 1.x compatibility")
 		| NetworkSandbox -> ("network-sandbox","Use local network sandbox instead of local file access one")
+		| NoAnalyzer -> ("no-analyzer","Disable the static analyzer")
 		| NoCompilation -> ("no-compilation","Disable final compilation for Cs, Cpp and Java")
 		| NoCOpt -> ("no_copt","Disable completion optimization (for debug purposes)")
 		| NoDebug -> ("no_debug","Remove all debug macros from cpp output")
@@ -549,9 +547,6 @@ let default_config =
 	{
 		pf_static = true;
 		pf_sys = true;
-		pf_locals_scope = true;
-		pf_captured_scope = true;
-		pf_unique_locals = false;
 		pf_capture_policy = CPNone;
 		pf_pad_nulls = false;
 		pf_add_final_return = false;
@@ -572,9 +567,6 @@ let get_config com =
 			default_config with
 			pf_static = false;
 			pf_sys = false;
-			pf_locals_scope = false;
-			pf_captured_scope = false;
-			pf_unique_locals = false;
 			pf_capture_policy = CPLoopVars;
 			pf_pad_nulls = false;
 			pf_add_final_return = false;
@@ -588,9 +580,6 @@ let get_config com =
 			default_config with
 			pf_static = false;
 			pf_sys = true;
-			pf_locals_scope = true;
-			pf_captured_scope = true;
-			pf_unique_locals = false;
 			pf_capture_policy = CPNone;
 			pf_pad_nulls = true;
 			pf_add_final_return = false;
@@ -604,9 +593,6 @@ let get_config com =
 			default_config with
 			pf_static = true;
 			pf_sys = false;
-			pf_locals_scope = false;
-			pf_captured_scope = true;
-			pf_unique_locals = true;
 			pf_capture_policy = CPLoopVars;
 			pf_pad_nulls = false;
 			pf_add_final_return = true;
@@ -620,9 +606,6 @@ let get_config com =
 			default_config with
 			pf_static = true;
 			pf_sys = false;
-			pf_locals_scope = true;
-			pf_captured_scope = true; (* handled by genSwf9 *)
-			pf_unique_locals = false;
 			pf_capture_policy = CPLoopVars;
 			pf_pad_nulls = false;
 			pf_add_final_return = false;
@@ -636,9 +619,6 @@ let get_config com =
 			default_config with
 			pf_static = false;
 			pf_sys = true;
-			pf_locals_scope = false; (* some duplicate work is done in genPhp *)
-			pf_captured_scope = false;
-			pf_unique_locals = false;
 			pf_capture_policy = CPNone;
 			pf_pad_nulls = true;
 			pf_add_final_return = false;
@@ -652,9 +632,6 @@ let get_config com =
 			default_config with
 			pf_static = true;
 			pf_sys = true;
-			pf_locals_scope = true;
-			pf_captured_scope = true;
-			pf_unique_locals = false;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_add_final_return = true;
@@ -668,9 +645,6 @@ let get_config com =
 			default_config with
 			pf_static = true;
 			pf_sys = true;
-			pf_locals_scope = false;
-			pf_captured_scope = true;
-			pf_unique_locals = true;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_add_final_return = false;
@@ -684,9 +658,6 @@ let get_config com =
 			default_config with
 			pf_static = true;
 			pf_sys = true;
-			pf_locals_scope = false;
-			pf_captured_scope = true;
-			pf_unique_locals = false;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_add_final_return = false;
@@ -700,9 +671,6 @@ let get_config com =
 			default_config with
 			pf_static = false;
 			pf_sys = true;
-			pf_locals_scope = false;
-			pf_captured_scope = false;
-			pf_unique_locals = false;
 			pf_capture_policy = CPLoopVars;
 			pf_pad_nulls = false;
 			pf_add_final_return = false;

+ 17 - 18
dce.ml

@@ -85,7 +85,7 @@ let rec check_feature dce s =
 
 and check_and_add_feature dce s =
 	check_feature dce s;
-	Common.add_feature dce.com s;
+	Hashtbl.replace dce.curclass.cl_module.m_extra.m_features s true
 
 (* mark a field as kept *)
 and mark_field dce c cf stat =
@@ -98,23 +98,24 @@ and mark_field dce c cf stat =
 		end
 	in
 	if cf.cf_name = "new" then begin
-		let rec loop c = match c.cl_super with
-			| None -> ()
-			| Some (csup,_) ->
-				begin match csup.cl_constructor with
-				| None -> ()
+		let rec loop c =
+			begin match c.cl_constructor with
 				| Some cf -> add cf
-				end;
-				loop csup
+				| None -> ()
+			end;
+			match c.cl_super with
+			| Some(csup,_) -> loop csup
+			| None -> ()
 		in
 		loop c
-	end;
-	if not (PMap.mem cf.cf_name (if stat then c.cl_statics else c.cl_fields)) then begin
-		match c.cl_super with
-		| None -> add cf
-		| Some (c,_) -> mark_field dce c cf stat
-	end else
-		add cf
+	end else begin
+		if not (PMap.mem cf.cf_name (if stat then c.cl_statics else c.cl_fields)) then begin
+			match c.cl_super with
+			| None -> add cf
+			| Some (c,_) -> mark_field dce c cf stat
+		end else
+			add cf
+	end
 
 let rec update_marked_class_fields dce c =
 	(* mark all :?used fields as surely :used now *)
@@ -747,6 +748,4 @@ let run com main full =
 		| x :: l -> x :: remove_meta m l
 	in
 	List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.Used cf.cf_meta) dce.marked_fields;
-	List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.MaybeUsed cf.cf_meta) dce.marked_maybe_fields;
-
-
+	List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.MaybeUsed cf.cf_meta) dce.marked_maybe_fields

BIN
extra/haxeci_sec.gpg.enc


BIN
extra/haxeci_ssh.enc


+ 1 - 1
extra/release-checklist.txt

@@ -30,4 +30,4 @@
 
 - Regenerate and upload API documentation (check --title and -D version values).
 - Update http://haxe.org/file/CHANGES.txt
-- Post announcement post to haxelang.
+- Post announcement post to haxelang.

+ 65 - 116
filters.ml

@@ -522,71 +522,17 @@ let captured_vars com e =
 (* RENAME LOCAL VARS *)
 
 let rename_local_vars ctx e =
-	let cfg = ctx.com.config in
-	let all_scope = (not cfg.pf_captured_scope) || (not cfg.pf_locals_scope) in
-	let vars = ref PMap.empty in
-	let all_vars = ref PMap.empty in
-	let vtemp = alloc_var "~" t_dynamic in
-	let rebuild_vars = ref false in
-	let rebuild m =
-		PMap.fold (fun v acc -> PMap.add v.v_name v acc) m PMap.empty
+	let vars = ref [] in
+	let declare v =
+		vars := v :: !vars
 	in
-	let save() =
-		let old = !vars in
-		if cfg.pf_unique_locals || not cfg.pf_locals_scope then (fun() -> ()) else (fun() -> vars := if !rebuild_vars then rebuild old else old)
+	let reserved = ref StringMap.empty in
+	let reserve name =
+		reserved := StringMap.add name true !reserved
 	in
-	let count = ref 1 in
-	let rename vars v =
-		while PMap.mem (v.v_name ^ string_of_int !count) vars do
-			incr count;
-		done;
-		begin match ctx.com.platform with
-			| Cpp ->
-				if not (Meta.has Meta.RealPath v.v_meta) then
-					v.v_meta <- (Meta.RealPath,[EConst (String v.v_name),e.epos],e.epos) :: v.v_meta
-			| _ ->
-				()
-		end;
-		v.v_name <- v.v_name ^ string_of_int !count;
-	in
-	let declare v p =
-		(match follow v.v_type with
-			| TAbstract ({a_path = [],"Void"},_) -> error "Arguments and variables of type Void are not allowed" p
-			| _ -> ());
-		(* chop escape char for all local variables generated *)
-		if is_gen_local v then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1);
-		let look_vars = (if not cfg.pf_captured_scope && v.v_capture then !all_vars else !vars) in
-		(try
-			let v2 = PMap.find v.v_name look_vars in
-			(*
-				block_vars will create some wrapper-functions that are declaring
-				the same variable twice. In that case do not perform a rename since
-				we are sure it's actually the same variable
-			*)
-			if v == v2 then raise Not_found;
-			rename look_vars v;
-		with Not_found ->
-			());
-		vars := PMap.add v.v_name v !vars;
-		if all_scope then all_vars := PMap.add v.v_name v !all_vars;
-	in
-	(*
-		This is quite a rare case, when a local variable would otherwise prevent
-		accessing a type because it masks the type value or the package name.
-	*)
 	let check t =
 		match (t_infos t).mt_path with
-		| [], name | name :: _, _ ->
-			let vars = if cfg.pf_locals_scope then vars else all_vars in
-			(try
-				let v = PMap.find name !vars in
-				if v == vtemp then raise Not_found; (* ignore *)
-				rename (!vars) v;
-				rebuild_vars := true;
-				vars := PMap.add v.v_name v !vars
-			with Not_found ->
-				());
-			vars := PMap.add name vtemp !vars
+		| [], name | name :: _, _ -> reserve name
 	in
 	let check_type t =
 		match follow t with
@@ -596,70 +542,62 @@ let rename_local_vars ctx e =
 		| TAbstract (a,_) -> check (TAbstractDecl a)
 		| TMono _ | TLazy _ | TAnon _ | TDynamic _ | TFun _ -> ()
 	in
-	let rec loop e =
-		match e.eexpr with
-		| TVar (v,eo) ->
-			if not cfg.pf_locals_scope then declare v e.epos;
-			(match eo with None -> () | Some e -> loop e);
-			if cfg.pf_locals_scope then declare v e.epos;
-		| TFunction tf ->
-			let old = save() in
-			List.iter (fun (v,_) -> declare v e.epos) tf.tf_args;
-			loop tf.tf_expr;
-			old()
-		| TBlock el ->
-			let old = save() in
-			(* we have to look ahead for vars on these targets (issue #3344) *)
-			begin match ctx.com.platform with
-				| Js ->
-					let rec check_var e = match e.eexpr with
-						| TVar (v,eo) ->
-							(match eo with None -> () | Some e -> loop e);
-							declare v e.epos
-						| TBlock _ ->
-							()
-						| _ ->
-							Type.iter check_var e
-					in
-					List.iter check_var el
-				| _ ->
-					()
-			end;
-			List.iter loop el;
-			old()
-		| TFor (v,it,e1) ->
-			loop it;
-			let old = save() in
-			declare v e.epos;
-			loop e1;
-			old()
-		| TTry (e,catchs) ->
-			loop e;
+	let rec collect e = match e.eexpr with
+ 		| TVar(v,eo) ->
+			declare v;
+			(match eo with None -> () | Some e -> collect e)
+		| TFor(v,e1,e2) ->
+			declare v;
+			collect e1;
+			collect e2;
+		| TTry(e1,catches) ->
+			collect e1;
 			List.iter (fun (v,e) ->
-				let old = save() in
-				declare v e.epos;
+				declare v;
 				check_type v.v_type;
-				loop e;
-				old()
-			) catchs;
+				collect e
+			) catches
+		| TFunction tf ->
+			List.iter (fun (v,_) -> declare v) tf.tf_args;
+			collect tf.tf_expr
 		| TTypeExpr t ->
 			check t
 		| TNew (c,_,_) ->
-			Type.iter loop e;
+			Type.iter collect e;
 			check (TClassDecl c);
 		| TCast (e,Some t) ->
-			loop e;
+			collect e;
 			check t;
 		| TConst TSuper ->
 			check_type e.etype
 		| _ ->
-			Type.iter loop e
+			Type.iter collect e
 	in
-	declare (alloc_var "this" t_dynamic) Ast.null_pos; (* force renaming of 'this' vars in abstract *)
+	(* Pass 1: Collect used identifiers and variables. *)
+	reserve "this";
+	if ctx.com.platform = Java then reserve "_";
 	begin match ctx.curclass.cl_path with
-		| s :: _,_ | [],s -> declare (alloc_var s t_dynamic) Ast.null_pos
+		| s :: _,_ | [],s -> reserve s
 	end;
-	loop e;
+	collect e;
+	(* Pass 2: Check and rename variables. *)
+	let count_table = Hashtbl.create 0 in
+	let maybe_rename v =
+		(* chop escape char for all local variables generated *)
+		if is_gen_local v then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1);
+		let name = ref v.v_name in
+		let count = ref (try Hashtbl.find count_table v.v_name with Not_found -> 0) in
+		while StringMap.mem !name !reserved do
+			incr count;
+			name := v.v_name ^ (string_of_int !count);
+		done;
+		reserve !name;
+		Hashtbl.replace count_table v.v_name !count;
+		if not (Meta.has Meta.RealPath v.v_meta) then
+			v.v_meta <- (Meta.RealPath,[EConst (String v.v_name),e.epos],e.epos) :: v.v_meta;
+		v.v_name <- !name;
+	in
+	List.iter maybe_rename (List.rev !vars);
 	e
 
 let check_unification ctx e t =
@@ -910,7 +848,7 @@ let add_field_inits ctx t =
 						eassign;
 			) inits in
 			let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in
-			match c.cl_constructor with
+			let cf = match c.cl_constructor with
 			| None ->
 				let ct = TFun([],ctx.com.basic.tvoid) in
 				let ce = mk (TFunction {
@@ -920,15 +858,27 @@ let add_field_inits ctx t =
 				}) ct c.cl_pos in
 				let ctor = mk_field "new" ct c.cl_pos in
 				ctor.cf_kind <- Method MethNormal;
-				c.cl_constructor <- Some { ctor with cf_expr = Some ce };
+				{ ctor with cf_expr = Some ce }
 			| Some cf ->
 				match cf.cf_expr with
 				| Some { eexpr = TFunction f } ->
 					let bl = match f.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in
 					let ce = mk (TFunction {f with tf_expr = mk (TBlock (el @ bl)) ctx.com.basic.tvoid c.cl_pos }) cf.cf_type cf.cf_pos in
-					c.cl_constructor <- Some {cf with cf_expr = Some ce }
+					{cf with cf_expr = Some ce };
 				| _ ->
 					assert false
+			in
+			let config = Analyzer.Config.get_field_config ctx.com c cf in
+			Analyzer.Run.run_on_field ctx config c cf;
+			(match cf.cf_expr with
+			| Some e ->
+				(* This seems a bit expensive, but hopefully constructor expressions aren't that massive. *)
+				let e = rename_local_vars ctx e in
+				let e = Optimizer.sanitize ctx.com e in
+				cf.cf_expr <- Some e
+			| _ ->
+				());
+			c.cl_constructor <- Some cf
 	in
 	match t with
 	| TClassDecl c ->
@@ -1081,7 +1031,6 @@ let run com tctx main =
 	end;
 	if not (Common.defined com Define.NoDeprecationWarnings) then
 		Codegen.DeprecationCheck.run com;
-	let use_static_analyzer = Common.defined com Define.Analyzer in
 	let new_types = List.filter (fun t -> not (is_cached t)) com.types in
 	(* PASS 1: general expression filters *)
 	let filters = [
@@ -1092,7 +1041,7 @@ let run com tctx main =
 		captured_vars com;
 	] in
 	List.iter (run_expression_filters tctx filters) new_types;
-	if com.platform <> Cross then Analyzer.Run.run_on_types tctx use_static_analyzer new_types;
+	if com.platform <> Cross then Analyzer.Run.run_on_types tctx new_types;
 	let filters = [
 		Optimizer.sanitize com;
 		if com.config.pf_add_final_return then add_final_return else (fun e -> e);

+ 1 - 4
genas3.ml

@@ -298,10 +298,7 @@ let rec type_str ctx t p =
 				| TAbstract ({ a_path = [],"UInt" },_)
 				| TAbstract ({ a_path = [],"Int" },_)
 				| TAbstract ({ a_path = [],"Float" },_)
-				| TAbstract ({ a_path = [],"Bool" },_)
-				| TInst ({ cl_path = [],"Int" },_)
-				| TInst ({ cl_path = [],"Float" },_)
-				| TEnum ({ e_path = [],"Bool" },_) -> "*"
+				| TAbstract ({ a_path = [],"Bool" },_) -> "*"
 				| _ -> type_str ctx t p)
 			| _ -> assert false);
 		| _ -> type_str ctx (apply_params t.t_params args t.t_type) p)

ファイルの差分が大きいため隠しています
+ 1396 - 14
gencpp.ml


+ 2 - 2
genjs.ml

@@ -596,7 +596,7 @@ and gen_expr ctx e =
 		spr ctx "if";
 		gen_value ctx cond;
 		spr ctx " ";
-		gen_expr ctx e;
+		gen_expr ctx (mk_block e);
 		(match eelse with
 		| None -> ()
 		| Some e2 ->
@@ -605,7 +605,7 @@ and gen_expr ctx e =
 			| _ -> ());
 			semicolon ctx;
 			spr ctx " else ";
-			gen_expr ctx e2);
+			gen_expr ctx (match e2.eexpr with | TIf _ -> e2 | _ -> mk_block e2));
 	| TUnop (op,Ast.Prefix,e) ->
 		spr ctx (Ast.s_unop op);
 		gen_value ctx e

+ 5 - 2
genswf9.ml

@@ -213,9 +213,12 @@ let rec type_id ctx t =
 	| TInst ({ cl_path = ["haxe"],"Int32" },_) ->
 		type_path ctx ([],"Int")
 	| TInst ({ cl_path = ["flash"],"Vector" } as c,pl) ->
+		let def() = HMParams (type_path ctx c.cl_path,List.map (type_id ctx) pl) in
 		(match pl with
-		| [TInst({cl_kind = KTypeParameter _},_)] -> type_path ctx ([],"Object")
-		| _ -> HMParams (type_path ctx c.cl_path,List.map (type_id ctx) pl))
+		| [t] -> (match follow t with
+			| TInst({cl_kind = KTypeParameter _},_) -> type_path ctx ([],"Object")
+			| _ -> def())
+		| _ -> def())
 	| TInst (c,_) ->
 		(match c.cl_kind with
 		| KTypeParameter l ->

+ 2 - 2
interp.ml

@@ -3495,7 +3495,7 @@ and call ctx vthis vfun pl p =
 		| Stack_overflow -> exc (VString "Compiler Stack overflow")
 		| Sys_error msg | Failure msg -> exc (VString msg)
 		| Unix.Unix_error (_,cmd,msg) -> exc (VString ("Error " ^ cmd ^ " " ^ msg))
-		(* | Invalid_expr -> exc (VString "Invalid input value") *)
+		| Invalid_expr -> exc (VString "Invalid input value")
 		| Builtin_error | Invalid_argument _ -> exc (VString "Invalid call")) in
 	ctx.vthis <- oldthis;
 	ctx.venv <- oldenv;
@@ -4578,7 +4578,7 @@ and encode_anon_status s =
 	let tag, pl = (match s with
 		| Closed -> 0, []
 		| Opened -> 1, []
-		| Type.Const -> 2, []
+		(* | Type.Const -> 2, [] *)
 		| Extend tl -> 3, [encode_ref tl (fun tl -> enc_array (List.map encode_type tl)) (fun() -> "<extended types>")]
 		| Statics cl -> 4, [encode_clref cl]
 		| EnumStatics en -> 5, [encode_enref en]

+ 2 - 2
main.ml

@@ -1005,7 +1005,6 @@ try
 	let swf_version = ref false in
 	let evals = ref [] in
 	Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 1000.));
-	Common.define_value com Define.HxcppApiLevel "321";
 	Common.raw_define com "haxe3";
 	Common.define_value com Define.Dce "std";
 	com.warning <- (fun msg p -> message ctx ("Warning : " ^ msg) p);
@@ -1451,13 +1450,14 @@ try
 			"n"
 		| Js ->
 			if not (PMap.exists (fst (Define.infos Define.JqueryVer)) com.defines) then
-				Common.define_value com Define.JqueryVer "11103";
+				Common.define_value com Define.JqueryVer "11201";
 			add_std "js";
 			"js"
 		| Php ->
 			add_std "php";
 			"php"
 		| Cpp ->
+			Common.define_value com Define.HxcppApiLevel (if Common.defined_value_safe com Define.CppAst <>"" then "330" else "321");
 			add_std "cpp";
 			"cpp"
 		| Cs ->

+ 17 - 26
matcher.ml

@@ -359,7 +359,7 @@ let to_pattern ctx e t =
 				mk_con_pat (CConst c) [] t p
 			| TTypeExpr mt ->
 				mk_type_pat ctx mt t p
-			| TField(_,FStatic({cl_extern = true},({cf_kind = Var {v_write = AccNever}} as cf))) ->
+			| TField(_,FStatic(_,({cf_kind = Var {v_write = AccNever}} as cf))) ->
 				mk_con_pat (CExpr e) [] cf.cf_type p
 			| TField(_, FEnum(en,ef)) ->
 				begin try
@@ -416,39 +416,28 @@ let to_pattern ctx e t =
 			end
 		| EConst(Ident s) ->
 			begin try
-				let ec = match follow t with
-					| TEnum(en,pl) ->
-						let ef = try
-							PMap.find s en.e_constrs
-						with Not_found when not (is_lower_ident s) ->
-							error (string_error s en.e_names ("Expected constructor for enum " ^ (s_type_path en.e_path))) p
-						in
-						(match ef.ef_type with
-							| TFun (args,_) ->
-								let msg = Printf.sprintf "Enum constructor %s.%s requires parameters %s"
-									(s_type_path en.e_path)
-									ef.ef_name
-									(String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (s_type t)) args))
-								in
-								error msg p
-							| _ -> ());
+				let rec loop t = match follow t with
+					| TEnum (en,tl) ->
+						let ef = PMap.find s en.e_constrs in
 						let et = mk (TTypeExpr (TEnumDecl en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics en) }) p in
-						mk (TField (et,FEnum (en,ef))) (apply_params en.e_params pl ef.ef_type) p
-					| TAbstract({a_impl = Some c} as a,_) when Meta.has Meta.Enum a.a_meta ->
+						mk (TField (et,FEnum (en,ef))) (apply_params en.e_params tl ef.ef_type) p
+					| TAbstract ({a_impl = Some c} as a,_) when has_meta Meta.Enum a.a_meta ->
 						let cf = PMap.find s c.cl_statics in
 						Type.unify (follow cf.cf_type) t;
 						let e = begin match cf.cf_expr with
-						| Some ({eexpr = TConst c | TCast({eexpr = TConst c},None)} as e) -> e
-						| _ -> raise Not_found
+							| Some ({eexpr = TConst c | TCast({eexpr = TConst c},None)} as e) -> e
+							| None when c.cl_extern -> make_static_field_access c cf cf.cf_type p
+							| _ -> raise Not_found
 						end in
 						e
 					| _ ->
-						let old = ctx.untyped in
-						ctx.untyped <- true;
-						let e = try type_expr ctx e (WithType t) with _ -> ctx.untyped <- old; raise Not_found in
-						ctx.untyped <- old;
-						e
+						let old = ctx.in_call_args in
+						ctx.in_call_args <- true; (* Not really, but it does exactly what we want here. *)
+						let ec = try type_expr ctx e (WithType t) with _ -> ctx.in_call_args <- old; raise Not_found in
+						ctx.in_call_args <- old;
+						ec
 				in
+				let ec = loop t in
 				let ec = match Optimizer.make_constant_expression ctx ~concat_strings:true ec with Some e -> e | None -> ec in
 				(match ec.eexpr with
 					| TField (_,FEnum (en,ef)) ->
@@ -465,6 +454,8 @@ let to_pattern ctx e t =
 						mk_con_pat (CConst c) [] t p
 					| TTypeExpr mt ->
 						mk_type_pat ctx mt t p
+					| TField(_,FStatic(_,({cf_kind = Var {v_write = AccNever}} as cf))) ->
+						mk_con_pat (CExpr ec) [] cf.cf_type p
 					| _ ->
 						raise Not_found);
 			with Not_found ->

+ 30 - 26
optimizer.ml

@@ -260,6 +260,8 @@ let create_affection_checker () =
 type in_local = {
 	i_var : tvar;
 	i_subst : tvar;
+	i_outside : bool;
+	i_abstract_this : bool;
 	mutable i_captured : bool;
 	mutable i_write : bool;
 	mutable i_read : int;
@@ -312,6 +314,8 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 			let i = {
 				i_var = v;
 				i_subst = v';
+				i_outside = false;
+				i_abstract_this = Meta.has Meta.This v.v_meta;
 				i_captured = false;
 				i_write = false;
 				i_force_temp = false;
@@ -332,6 +336,8 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 			{
 				i_var = v;
 				i_subst = v;
+				i_outside = true;
+				i_abstract_this = Meta.has Meta.This v.v_meta;
 				i_captured = false;
 				i_write = false;
 				i_force_temp = false;
@@ -418,7 +424,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 				to its variables and not the calling method *)
 			if v.v_name = "__dollar__delay_call" then cancel_inlining := true;
 			let e = { e with eexpr = TLocal l.i_subst } in
-			if Meta.has Meta.This v.v_meta then mk (TCast(e,None)) v.v_type e.epos else e
+			if l.i_abstract_this then mk (TCast(e,None)) v.v_type e.epos else e
 		| TConst TThis ->
 			let l = read_local vthis in
 			l.i_read <- l.i_read + (if !in_loop then 2 else 1);
@@ -515,14 +521,6 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 			l.i_write <- true;
 			let e2 = map false e2 in
 			{e with eexpr = TBinop(op,{e1 with eexpr = TLocal l.i_subst},e2)}
-		| TObjectDecl fl ->
-			let fl = List.map (fun (s,e) -> s,map false e) fl in
-			begin match follow e.etype with
-				| TAnon an when (match !(an.a_status) with Const -> true | _ -> false) ->
-					{e with eexpr = TObjectDecl fl; etype = TAnon { an with a_status = ref Closed}}
-				| _ ->
-					{e with eexpr = TObjectDecl fl}
-			end
 		| TFunction f ->
 			(match f.tf_args with [] -> () | _ -> has_vars := true);
 			let old = save_locals ctx and old_fun = !in_local_fun in
@@ -577,16 +575,16 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 	let force = ref force in
 	let vars = List.fold_left (fun acc (i,e) ->
 		let flag = not i.i_force_temp && (match e.eexpr with
-			| TLocal v when Meta.has Meta.This v.v_meta -> true
+			| TLocal _ when i.i_abstract_this -> true
 			| TLocal _ | TConst _ -> not i.i_write
 			| TFunction _ -> if i.i_write then error "Cannot modify a closure parameter inside inline method" p; true
 			| _ -> not i.i_write && i.i_read <= 1
 		) in
 		let flag = flag && (not i.i_captured || is_constant e) in
 		(* force inlining if we modify 'this' *)
-		if i.i_write && (Meta.has Meta.This i.i_var.v_meta) then force := true;
+		if i.i_write && i.i_abstract_this then force := true;
 		(* force inlining of 'this' variable if it is written *)
-		let flag = if not flag && (Meta.has Meta.This i.i_var.v_meta) && i.i_write then begin
+		let flag = if not flag && i.i_abstract_this && i.i_write then begin
 			if not (is_writable e) then error "Cannot modify the abstract value, store it into a local first" p;
 			true
 		end else flag in
@@ -676,7 +674,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 			let map_var v =
 				if not (Hashtbl.mem vars v.v_id) then begin
 					Hashtbl.add vars v.v_id ();
-					v.v_type <- map_type v.v_type;
+					if not (read_local v).i_outside then v.v_type <- map_type v.v_type;
 				end;
 				v
 			in
@@ -1215,22 +1213,28 @@ let optimize_binop e op e1 e2 =
 		e)
 
 let optimize_unop e op flag esub =
+	let is_int t = match follow t with
+		| TAbstract({a_path = [],"Int"},_) -> true
+		| _ -> false
+	in
 	match op, esub.eexpr with
 		| Not, (TConst (TBool f) | TParenthesis({eexpr = TConst (TBool f)})) -> { e with eexpr = TConst (TBool (not f)) }
 		| Not, (TBinop(op,e1,e2) | TParenthesis({eexpr = TBinop(op,e1,e2)})) ->
-			begin try
-				let op = match op with
-					| OpGt -> OpLte
-					| OpGte -> OpLt
-					| OpLt -> OpGte
-					| OpLte -> OpGt
-					| OpEq -> OpNotEq
-					| OpNotEq -> OpEq
-					| _ -> raise Exit
-				in
-				{e with eexpr = TBinop(op,e1,e2)}
-			with Exit ->
-				e
+			begin
+				let is_int = is_int e1.etype && is_int e2.etype in
+				try
+					let op = match is_int, op with
+						| true, OpGt -> OpLte
+						| true, OpGte -> OpLt
+						| true, OpLt -> OpGte
+						| true, OpLte -> OpGt
+						| _, OpEq -> OpNotEq
+						| _, OpNotEq -> OpEq
+						| _ -> raise Exit
+					in
+					{e with eexpr = TBinop(op,e1,e2)}
+				with Exit ->
+					e
 			end
 		| Neg, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.neg i)) }
 		| NegBits, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.lognot i)) }

+ 3 - 4
parser.ml

@@ -141,15 +141,14 @@ let rec make_unop op ((v,p2) as e) p1 =
 	match v with
 	| EBinop (bop,e,e2) -> EBinop (bop, make_unop op e p1 , e2) , (punion p1 p2)
 	| ETernary (e1,e2,e3) -> ETernary (make_unop op e1 p1 , e2, e3), punion p1 p2
-	| _ ->
-		EUnop (op,Prefix,e), punion p1 p2
+	| _ -> EUnop (op,Prefix,e), punion p1 p2
 
 let rec make_meta name params ((v,p2) as e) p1 =
 	match v with
+	| EBinop ((OpAssign | OpAssignOp _),_,_) -> EMeta((name,params,p1),e),punion p1 p2
 	| EBinop (bop,e,e2) -> EBinop (bop, make_meta name params e p1 , e2) , (punion p1 p2)
 	| ETernary (e1,e2,e3) -> ETernary (make_meta name params e1 p1 , e2, e3), punion p1 p2
-	| _ ->
-		EMeta((name,params,p1),e),punion p1 p2
+	| _ -> EMeta((name,params,p1),e),punion p1 p2
 
 let make_is e t p =
 	let e_is = EField((EConst(Ident "Std"),p),"is"),p in

+ 1 - 1
std/Map.hx

@@ -42,7 +42,7 @@ import haxe.Constraints.IMap;
 
 	Map is an abstract type, it is not available at runtime.
 **/
-@:multiType(K)
+@:multiType(@:followWithAbstracts K)
 abstract Map<K,V>(IMap<K,V> ) {
 
 	/**

+ 23 - 23
std/StdTypes.hx

@@ -22,22 +22,22 @@
 // standard Haxe types
 
 /**
-	The standard Void type. Only `null` values can be of the type `Void`.
+	The standard `Void` type. Only `null` values can be of the type `Void`.
 **/
 @:coreType abstract Void { }
 
 /**
-	The standard Float type, this is a double-precision IEEE 64bit float.
+	The standard `Float` type, this is a double-precision IEEE 64bit float.
 
-	On static targets, null cannot be assigned to Float. If this is necessary,
+	On static targets, `null` cannot be assigned to Float. If this is necessary,
 	`Null<Float>` can be used instead.
 **/
 @:coreType @:notNull @:runtimeValue abstract Float { }
 
 /**
-	The standard Int type. Its precision depends on the platform.
+	The standard `Int` type. Its precision depends on the platform.
 
-	On static targets, null cannot be assigned to Int. If this is necessary,
+	On static targets, `null` cannot be assigned to `Int`. If this is necessary,
 	`Null<Int>` can be used instead.
 **/
 @:coreType @:notNull @:runtimeValue abstract Int to Float { }
@@ -48,64 +48,64 @@
 
 /**
 	`Null` can be useful in two cases. In order to document some methods
-	that accepts or can return a `null` value, or for the Flash compiler and AS3
-	generator to distinguish between base values that can be null and others that
+	that accept or can return a `null` value, or for the Flash compiler and AS3
+	generator to distinguish between base values that can be `null` and others that
 	can't.
 **/
 typedef Null<T> = T
 
 /**
-	The standard Boolean type, which can either be true or false.
+	The standard Boolean type, which can either be `true` or `false`.
 
-	On static targets, null cannot be assigned to Bool. If this is necessary,
+	On static targets, `null` cannot be assigned to `Bool`. If this is necessary,
 	`Null<Bool>` can be used instead.
 **/
 @:coreType @:notNull @:runtimeValue abstract Bool {
 }
 
 /**
-	Dynamic is a special type which is compatible with all other types.
+	`Dynamic` is a special type which is compatible with all other types.
 
-	Use of Dynamic should be minimized as it prevents several compiler
+	Use of `Dynamic` should be minimized as it prevents several compiler
 	checks and optimizations.
 **/
 @:coreType @:runtimeValue abstract Dynamic<T> {
 }
 
 /**
-	An Iterator is a structure that permits iteration over elements of type T.
+	An `Iterator` is a structure that permits iteration over elements of type `T`.
 
-	Any class with matching hasNext and next fields is considered an Iterator
-	and can then be used e.g. in for-loops. This makes it easy to implement
+	Any class with matching `hasNext()` and `next()` fields is considered an `Iterator`
+	and can then be used e.g. in `for`-loops. This makes it easy to implement
 	custom iterators.
 **/
 typedef Iterator<T> = {
 
 	/**
-		Returns false if the iteration is complete, true otherwise.
+		Returns `false` if the iteration is complete, `true` otherwise.
 
 		Usually iteration is considered to be complete if all elements of the
-		underlying data structure were handled through calls to next(). However,
+		underlying data structure were handled through calls to `next()`. However,
 		in custom iterators any logic may be used to determine the completion
 		state.
 	**/
 	function hasNext() : Bool;
 
 	/**
-		Returns the current item of the Iterator and advances to the next one.
+		Returns the current item of the `Iterator` and advances to the next one.
 
-		This method is not required to check `hasNext` first. A call to this
-		method while `hasNext` is false yields unspecified behavior.
+		This method is not required to check `hasNext()` first. A call to this
+		method while `hasNext()` is `false` yields unspecified behavior.
 
-		On the other hand iterators should not require a call to `hasNext`
-		before the first call to `next` if an element is available.
+		On the other hand, iterators should not require a call to `hasNext()`
+		before the first call to `next()` if an element is available.
 	**/
 	function next() : T;
 
 }
 
 /**
-	An Iterable is a data structure which has an iterator() method.
+	An `Iterable` is a data structure which has an `iterator()` method.
 	See `Lambda` for generic functions on iterable structures.
 **/
 typedef Iterable<T> = {
@@ -113,7 +113,7 @@ typedef Iterable<T> = {
 }
 
 /**
-	ArrayAccess is used to indicate a class that can be accessed using brackets.
+	`ArrayAccess` is used to indicate a class that can be accessed using brackets.
 	The type parameter represents the type of the elements stored.
 
 	This interface should be used for externs only. Haxe does not support custom

+ 10 - 10
std/Xml.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- 
+
 /**
 	Xml node types.
 **/
@@ -56,41 +56,41 @@
 
 /**
 	Crossplatform Xml API.
-	
+
 	@see http://haxe.org/manual/std-Xml.html
 **/
 class Xml {
 	/**
 		XML element type.
 	**/
-	static public var Element(default,null) = XmlType.Element;
+	static public var Element(default,never) = XmlType.Element;
 	/**
 		XML parsed character data type.
 	**/
-	static public var PCData(default,null) = XmlType.PCData;
+	static public var PCData(default,never) = XmlType.PCData;
 	/**
 		XML character data type.
 	**/
-	static public var CData(default,null) = XmlType.CData;
+	static public var CData(default,never) = XmlType.CData;
 	/**
 		XML comment type.
 	**/
-	static public var Comment(default,null) = XmlType.Comment;
+	static public var Comment(default,never) = XmlType.Comment;
 	/**
 		XML doctype element type.
 	**/
-	static public var DocType(default,null) = XmlType.DocType;
+	static public var DocType(default,never) = XmlType.DocType;
 	/**
 	 	XML processing instruction type.
 	**/
-	static public var ProcessingInstruction(default,null) = XmlType.ProcessingInstruction;
+	static public var ProcessingInstruction(default,never) = XmlType.ProcessingInstruction;
 	/**
 		XML document type.
 	**/
-	static public var Document(default,null) = XmlType.Document;
+	static public var Document(default,never) = XmlType.Document;
 
 	/**
-		Parses the String into an Xml document. 
+		Parses the String into an Xml document.
 	**/
 	static public function parse( str : String ) : Xml {
 		return haxe.xml.Parser.parse(str);

+ 3 - 1
std/cpp/_std/Reflect.hx

@@ -19,7 +19,9 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-@:coreApi class Reflect {
+@:coreApi
+@:analyzer(ignore)
+class Reflect {
 
 	public  static function hasField( o : Dynamic, field : String ) : Bool untyped {
 		return o!=null && o.__HasField(field);

+ 3 - 1
std/cpp/_std/haxe/Int64.hx

@@ -40,7 +40,9 @@ abstract Int64( __Int64 ) from __Int64 to __Int64
 
 
 	public static #if !cppia inline #end function make( high : Int32, low : Int32 ) : Int64 {
-      return untyped __cpp__("cpp::Int64Struct(( ( (cpp::Int64)((unsigned int){0}) ) << 32 ) | ((unsigned int){1}))",high, low);
+      var tmpHigh = high;
+      var tmpLow = low;
+      return untyped __cpp__("cpp::Int64Struct(( ( (cpp::Int64)((unsigned int){0}) ) << 32 ) | ((unsigned int){1}))",tmpHigh, tmpLow);
 	}
 
 	@:from public static function ofInt( x : Int ) : Int64 {

+ 12 - 0
std/cpp/_std/sys/net/Socket.hx

@@ -99,6 +99,8 @@ private class SocketOutput extends haxe.io.Output {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 				throw Blocked;
+			else if (e == "EOF")
+				throw new haxe.io.Eof();
 			else
 				throw Custom(e);
 		}
@@ -158,6 +160,10 @@ class Socket {
 		} catch( s : String ) {
 			if( s == "std@socket_connect" )
 				throw "Failed to connect on "+host.toString()+":"+port;
+			else if (s == "Blocking") {
+				// Do nothing, this is not a real error, it simply indicates
+				// that a non-blocking connect is in progress
+			}
 			else
 				cpp.Lib.rethrow(s);
 		}
@@ -186,6 +192,9 @@ class Socket {
 
 	public function peer() : { host : Host, port : Int } {
 		var a : Dynamic = socket_peer(__s);
+		if (a == null) {
+			return null;
+		}
 		var h = new Host("127.0.0.1");
 		untyped h.ip = a[0];
 		return { host : h, port : a[1] };
@@ -193,6 +202,9 @@ class Socket {
 
 	public function host() : { host : Host, port : Int } {
 		var a : Dynamic = socket_host(__s);
+		if (a == null) {
+			return null;
+		}
 		var h = new Host("127.0.0.1");
 		untyped h.ip = a[0];
 		return { host : h, port : a[1] };

+ 2 - 2
std/cs/io/NativeInput.hx

@@ -28,7 +28,7 @@ import haxe.io.Input;
 
 class NativeInput extends Input
 {
-	public var canSeek(get_canSeek, null):Bool;
+	public var canSeek(get,never):Bool;
 
 	var stream:cs.system.io.Stream;
 	var _eof:Bool;
@@ -67,7 +67,7 @@ class NativeInput extends Input
 		stream.Close();
 	}
 
-	private function get_canSeek():Bool
+	private inline function get_canSeek():Bool
 	{
 		return stream.CanSeek;
 	}

+ 3 - 2
std/cs/io/NativeOutput.hx

@@ -26,7 +26,8 @@ import haxe.io.Output;
 
 class NativeOutput extends Output
 {
-	var canSeek(get_canSeek, null):Bool;
+	var canSeek(get,never):Bool;
+
 	var stream:cs.system.io.Stream;
 	public function new(stream)
 	{
@@ -55,7 +56,7 @@ class NativeOutput extends Output
 		stream.SetLength(haxe.Int64.add(stream.Length, cast(nbytes, Int64)));
 	}
 
-	private function get_canSeek():Bool
+	private inline function get_canSeek():Bool
 	{
 		return stream.CanSeek;
 	}

+ 4 - 0
std/flash/Boot.hx

@@ -242,7 +242,11 @@ class Boot extends flash.display.MovieClip {
 		aproto.remove = function(obj) {
 			var idx = __this__.indexOf(obj);
 			if( idx == -1 ) return false;
+			#if flash19
+			__this__.removeAt(idx);
+			#else
 			__this__.splice(idx,1);
+			#end
 			return true;
 		}
 		aproto.iterator = function() {

+ 74 - 0
std/flash/_std/haxe/ds/IntMap.hx

@@ -47,6 +47,10 @@ package haxe.ds;
 		return true;
 	}
 
+	#if as3
+
+	// unoptimized version
+	
 	public function keys() : Iterator<Int> {
 		return untyped (__keys__(h)).iterator();
 	}
@@ -60,6 +64,18 @@ package haxe.ds;
 		};
 	}
 
+	#else
+
+	public inline function keys() : Iterator<Int> {
+		return new IntMapKeysIterator(h);
+	}
+
+	public inline function iterator() : Iterator<T> {
+		return new IntMapValuesIterator<T>(h);
+	}
+
+	#end
+	
 	public function toString() : String {
 		var s = new StringBuf();
 		s.add("{");
@@ -74,5 +90,63 @@ package haxe.ds;
 		s.add("}");
 		return s.toString();
 	}
+}
+
+#if !as3
+
+// this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation
+
+@:allow(haxe.ds.IntMap)
+private class IntMapKeysIterator {
+	var h:flash.utils.Dictionary;
+	var index : Int;
+	var nextIndex : Int;
+
+	inline function new(h:flash.utils.Dictionary):Void {
+		this.h = h;
+		this.index = 0;
+		hasNext();
+	}
+
+	public inline function hasNext():Bool {
+		var h = h, index = index; // tmp vars required for __has_next
+		var n = untyped __has_next__(h, index);
+		this.nextIndex = index; // store next index
+		return n;
+	}
+
+	public inline function next():Int {
+		var r : Int = untyped __forin__(h, nextIndex);
+		index = nextIndex;
+		return r;
+	}
+
+}
+
+@:allow(haxe.ds.IntMap)
+private class IntMapValuesIterator<T> {
+	var h:flash.utils.Dictionary;
+	var index : Int;
+	var nextIndex : Int;
+
+	inline function new(h:flash.utils.Dictionary):Void {
+		this.h = h;
+		this.index = 0;
+		hasNext();
+	}
+
+	public inline function hasNext():Bool {
+		var h = h, index = index; // tmp vars required for __has_next
+		var n = untyped __has_next__(h, index);
+		this.nextIndex = index; // store next index
+		return n;
+	}
+
+	public inline function next():T {
+		var r = untyped __foreach__(h, nextIndex);
+		index = nextIndex;
+		return r;
+	}
 
 }
+#end

+ 75 - 0
std/flash/_std/haxe/ds/UnsafeStringMap.hx

@@ -52,6 +52,10 @@ class UnsafeStringMap<T> implements haxe.Constraints.IMap<String,T> {
 		return true;
 	}
 
+	#if as3
+
+	// unoptimized version
+	
 	public function keys() : Iterator<String> {
 		return untyped (__keys__(h)).iterator();
 	}
@@ -65,6 +69,18 @@ class UnsafeStringMap<T> implements haxe.Constraints.IMap<String,T> {
 		};
 	}
 
+	#else
+
+	public inline function keys() : Iterator<String> {
+		return new UnsafeStringMapKeysIterator(h);
+	}
+
+	public inline function iterator() : Iterator<T> {
+		return new UnsafeStringMapValuesIterator<T>(h);
+	}
+
+	#end
+
 	public function toString() : String {
 		var s = new StringBuf();
 		s.add("{");
@@ -81,3 +97,62 @@ class UnsafeStringMap<T> implements haxe.Constraints.IMap<String,T> {
 	}
 
 }
+
+#if !as3
+
+// this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation
+
+@:allow(haxe.ds.UnsafeStringMap)
+private class UnsafeStringMapKeysIterator {
+	var h:flash.utils.Dictionary;
+	var index : Int;
+	var nextIndex : Int;
+
+	inline function new(h:flash.utils.Dictionary):Void {
+		this.h = h;
+		this.index = 0;
+		hasNext();
+	}
+
+	public inline function hasNext():Bool {
+		var h = h, index = index; // tmp vars required for __has_next
+		var n = untyped __has_next__(h, index);
+		this.nextIndex = index; // store next index
+		return n;
+	}
+
+	public inline function next():String {
+		var r : String = untyped __forin__(h, nextIndex);
+		index = nextIndex;
+		return r;
+	}
+
+}
+
+@:allow(haxe.ds.UnsafeStringMap)
+private class UnsafeStringMapValuesIterator<T> {
+	var h:flash.utils.Dictionary;
+	var index : Int;
+	var nextIndex : Int;
+
+	inline function new(h:flash.utils.Dictionary):Void {
+		this.h = h;
+		this.index = 0;
+		hasNext();
+	}
+
+	public inline function hasNext():Bool {
+		var h = h, index = index; // tmp vars required for __has_next
+		var n = untyped __has_next__(h, index);
+		this.nextIndex = index; // store next index
+		return n;
+	}
+
+	public inline function next():T {
+		var r = untyped __foreach__(h, nextIndex);
+		index = nextIndex;
+		return r;
+	}
+
+}
+#end

+ 3 - 2
std/haxe/Template.hx

@@ -112,8 +112,9 @@ class Template {
 	}
 
 	function resolve( v : String ) : Dynamic {
-		if( Reflect.hasField(context,v) )
-			return Reflect.field(context,v);
+		var value = Reflect.field(context, v);
+		if( value != null || Reflect.hasField(context,v) )
+			return value;
 		for( ctx in stack )
 			if( Reflect.hasField(ctx,v) )
 				return Reflect.field(ctx,v);

+ 1 - 1
std/haxe/Timer.hx

@@ -48,7 +48,7 @@ class Timer {
 	/**
 		Creates a new timer that will run every `time_ms` milliseconds.
 
-		After creating the Timer instance, it calls `this].run` repeatedly,
+		After creating the Timer instance, it calls `this.run` repeatedly,
 		with delays of `time_ms` milliseconds, until `this.stop` is called.
 
 		The first invocation occurs after `time_ms` milliseconds, not

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

@@ -270,16 +270,17 @@ abstract Vector<T>(VectorData<T>) {
 
 		If `f` is null, the result is unspecified.
 	**/
-	//public function map<S>(f:T->S):Vector<S> {
-		//var r = new Vector<S>(length);
-		//var i = 0;
-		//var len = length;
-		//for(i in 0...len) {
-			//var v = f(get(i));
-			//r.set(i, v);
-		//}
-		//return r;
-	//}
+	#if cs @:extern #end public inline function map<S>(f:T->S):Vector<S> {
+		var length = length;
+		var r = new Vector<S>(length);
+		var i = 0;
+		var len = length;
+		for(i in 0...len) {
+			var v = f(get(i));
+			r.set(i, v);
+		}
+		return r;
+	}
 
 	/**
 		Sorts `this` Vector according to the comparison function `f`, where

+ 6 - 6
std/haxe/macro/Context.hx

@@ -379,7 +379,7 @@ class Context {
 	public static function resolveType( t : ComplexType, p : Position ) : Type {
 		return load("resolve_type", 2)(t,p);
 	}
-	
+
 	/**
 		Returns the `ComplexType` corresponding to the given `Type` `t`.
 
@@ -451,7 +451,7 @@ class Context {
 		The resource is then available using the `haxe.macro.Resource` API.
 
 		If a previous resource was bound to `name`, it is overwritten.
-		
+
 		Compilation server : when using the compilation server, the resource is bound
 		to the Haxe module which calls the macro, so it will be included again if
 		that module is reused. If this resource concerns several modules, prefix its
@@ -541,10 +541,10 @@ class Context {
 
 		If `e` is null, the result is unspecified.
 	**/
-	@:require(haxe_ver >= 3.3)
-	public static function eval( e : Expr ) : Dynamic {
-		return load("eval",1)(e);
-	}
+	//@:require(haxe_ver >= 3.3)
+	//public static function eval( e : Expr ) : Dynamic {
+		//return load("eval",1)(e);
+	//}
 
 	/**
 		Manually adds a dependency between module `modulePath` and an external

+ 0 - 1
std/js/_std/Type.hx

@@ -99,7 +99,6 @@ enum ValueType {
 		default:
 			throw "Too many arguments";
 		}
-		return null;
 	}
 
 	public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {

+ 2 - 0
std/js/html/ArrayBuffer.hx

@@ -24,6 +24,8 @@
 
 package js.html;
 
+import js.html.compat.ArrayBuffer;
+
 @:native("ArrayBuffer")
 extern class ArrayBuffer
 {

+ 2 - 0
std/js/html/DataView.hx

@@ -24,6 +24,8 @@
 
 package js.html;
 
+import js.html.compat.DataView;
+
 @:native("DataView")
 extern class DataView extends ArrayBufferView
 {

+ 4 - 2
std/js/html/Float32Array.hx

@@ -24,13 +24,15 @@
 
 package js.html;
 
+import js.html.compat.Float32Array;
+
 @:native("Float32Array")
 extern class Float32Array extends ArrayBufferView implements ArrayAccess<Float>
 {
 	static inline var BYTES_PER_ELEMENT : Int = 4;
-	
+
 	var length(default,null) : Int;
-	
+
 	/** @throws DOMError */
 	@:overload( function( length : Int ) : Void {} )
 	@:overload( function( array : Float32Array ) : Void {} )

+ 4 - 2
std/js/html/Float64Array.hx

@@ -24,13 +24,15 @@
 
 package js.html;
 
+import js.html.compat.Float64Array;
+
 @:native("Float64Array")
 extern class Float64Array extends ArrayBufferView implements ArrayAccess<Float>
 {
 	static inline var BYTES_PER_ELEMENT : Int = 8;
-	
+
 	var length(default,null) : Int;
-	
+
 	/** @throws DOMError */
 	@:overload( function( length : Int ) : Void {} )
 	@:overload( function( array : Float64Array ) : Void {} )

+ 4 - 2
std/js/html/Uint8Array.hx

@@ -24,13 +24,15 @@
 
 package js.html;
 
+import js.html.compat.Uint8Array;
+
 @:native("Uint8Array")
 extern class Uint8Array extends ArrayBufferView implements ArrayAccess<Int>
 {
 	static inline var BYTES_PER_ELEMENT : Int = 1;
-	
+
 	var length(default,null) : Int;
-	
+
 	/** @throws DOMError */
 	@:overload( function( length : Int ) : Void {} )
 	@:overload( function( array : Uint8Array ) : Void {} )

+ 1 - 1
std/js/html/compat/ArrayBuffer.hx

@@ -22,7 +22,7 @@
 package js.html.compat;
 
 #if !nodejs
-@:keep
+@:ifFeature("js.html.ArrayBuffer.*")
 class ArrayBuffer {
 
 	public var byteLength : Int;

+ 1 - 1
std/js/html/compat/DataView.hx

@@ -24,7 +24,7 @@ package js.html.compat;
 #if !nodejs
 import haxe.io.Error;
 
-@:ifFeature("haxe.io.Float32Array.*", "haxe.io.Float64Array.*")
+@:ifFeature("js.html.DataView.*")
 @:access(js.html.compat.ArrayBuffer)
 class DataView {
 

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

@@ -24,7 +24,7 @@ package js.html.compat;
 #if !nodejs
 import js.Lib.nativeThis;
 
-@:keep
+@:ifFeature("js.html.Float32Array.*")
 class Float32Array {
 
 	static var BYTES_PER_ELEMENT = 4;

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

@@ -24,7 +24,7 @@ package js.html.compat;
 #if !nodejs
 import js.Lib.nativeThis;
 
-@:keep
+@:ifFeature("js.html.Float64Array.*")
 class Float64Array {
 
 	static var BYTES_PER_ELEMENT = 8;

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

@@ -24,7 +24,7 @@ package js.html.compat;
 #if !nodejs
 import js.Lib.nativeThis;
 
-@:keep
+@:ifFeature("js.html.Uint8Array.*")
 class Uint8Array {
 
 	static var BYTES_PER_ELEMENT = 1;

+ 1 - 1
std/js/jquery/Helper.hx

@@ -17,7 +17,7 @@ package js.jquery;
 	@:allow(js.jquery.JQuery)
 	macro static function embed() {
 		return if (haxe.macro.Context.defined("embed_js")) {
-			macro haxe.macro.Compiler.includeFile("js/jquery/jquery-1.11.3.min.js");
+			macro haxe.macro.Compiler.includeFile("js/jquery/jquery-1.12.1.min.js");
 		} else {
 			macro {};
 		}

+ 7 - 3
std/js/jquery/JQuery.hx

@@ -104,6 +104,10 @@ package js.jquery;
 		Holds or releases the execution of jQuery's ready event.
 	**/
 	static public function holdReady(hold:Bool):Void;
+	/**
+		Modify and filter HTML strings passed through <a href="/category/manipulation/">jQuery manipulation methods</a>.
+	**/
+	static public function htmlPrefilter(html:String):String;
 	/**
 		Search for a specified value within an array and return its index (or -1 if not found).
 	**/
@@ -121,7 +125,7 @@ package js.jquery;
 	**/
 	static public function isFunction(obj:Dynamic):Bool;
 	/**
-		Determines whether its argument is a number.
+		Determines whether its argument represents a JavaScript number.
 	**/
 	static public function isNumeric(value:Dynamic):Bool;
 	/**
@@ -229,7 +233,7 @@ package js.jquery;
 	**/
 	static public function uniqueSort(array:Array<js.html.Element>):Array<js.html.Element>;
 	/**
-		Provides a way to execute callback functions based on one or more objects, usually <a href="/category/deferred-object/">Deferred</a> objects that represent asynchronous events.
+		Provides a way to execute callback functions based on zero or more objects, usually <a href="/category/deferred-object/">Deferred</a> objects that represent asynchronous events.
 	**/
 	static public function when(deferreds:haxe.extern.Rest<js.jquery.Deferred>):js.jquery.Promise;
 	/**
@@ -771,7 +775,7 @@ package js.jquery;
 	**/
 	public function prependTo(target:haxe.extern.EitherType<js.html.Element, haxe.extern.EitherType<Array<js.html.Element>, haxe.extern.EitherType<String, js.jquery.JQuery>>>):js.jquery.JQuery;
 	/**
-		Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector.
+		Get the immediately preceding sibling of each element in the set of matched elements. If a selector is provided, it retrieves the previous sibling only if it matches that selector.
 	**/
 	public function prev(?selector:String):js.jquery.JQuery;
 	/**

ファイルの差分が大きいため隠しています
+ 0 - 1
std/js/jquery/jquery-1.11.3.min.js


ファイルの差分が大きいため隠しています
+ 1 - 0
std/js/jquery/jquery-1.12.1.min.js


+ 0 - 1
std/neko/_std/String.hx

@@ -77,7 +77,6 @@
 					return last;
 				last = p;
 			}
-			return null;
 		}
 	}
 

+ 2 - 2
std/neko/_std/Type.hx

@@ -68,7 +68,7 @@ enum ValueType {
 
 	public static function resolveClass( name : String ) : Class<Dynamic> untyped {
 		var path = name.split(".");
-		cl = Reflect.field(untyped neko.Boot.__classes,path[0]);
+		var cl = Reflect.field(untyped neko.Boot.__classes,path[0]);
 		var i = 1;
 		while( cl != null && i < path.length ) {
 			cl = Reflect.field(cl,path[i]);
@@ -83,7 +83,7 @@ enum ValueType {
 
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped {
 		var path = name.split(".");
-		e = Reflect.field(neko.Boot.__classes,path[0]);
+		var e = Reflect.field(neko.Boot.__classes,path[0]);
 		var i = 1;
 		while( e != null && i < path.length ) {
 			e = Reflect.field(e,path[i]);

+ 12 - 0
std/neko/_std/sys/net/Socket.hx

@@ -39,6 +39,8 @@ private class SocketOutput extends haxe.io.Output {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 				throw Blocked;
+			else if ( e == "EOF" )
+				throw new haxe.io.Eof();
 			else
 				throw Custom(e);
 		}
@@ -151,6 +153,10 @@ class Socket {
 		} catch( s : String ) {
 			if( s == "std@socket_connect" )
 				throw "Failed to connect on "+host.toString()+":"+port;
+			else if ( s == "Blocking" ) {
+				// Do nothing, this is not a real error, it simply indicates
+				// that a non-blocking connect is in progress
+			}
 			else
 				neko.Lib.rethrow(s);
 		}
@@ -179,6 +185,9 @@ class Socket {
 
 	public function peer() : { host : Host, port : Int } {
 		var a : Dynamic = socket_peer(__s);
+		if (a == null) {
+			return null;
+		}
 		var h = new Host("127.0.0.1");
 		untyped h.ip = a[0];
 		return { host : h, port : a[1] };
@@ -186,6 +195,9 @@ class Socket {
 
 	public function host() : { host : Host, port : Int } {
 		var a : Dynamic = socket_host(__s);
+		if (a == null) {
+			return null;
+		}
 		var h = new Host("127.0.0.1");
 		untyped h.ip = a[0];
 		return { host : h, port : a[1] };

+ 5 - 16
std/python/io/NativeInput.hx

@@ -27,7 +27,7 @@ import python.Bytearray;
 import python.lib.io.IOBase;
 import python.lib.io.RawIOBase;
 
-class NativeInput<T:IOBase> extends Input{
+class NativeInput<T:IOBase> extends Input {
 
 	var stream:T;
 	var wasEof:Bool;
@@ -39,12 +39,8 @@ class NativeInput<T:IOBase> extends Input{
 		if (!stream.readable()) throw "Write-only stream";
 	}
 
-	public var canSeek(get_canSeek, null):Bool;
-
-	private function get_canSeek():Bool
-	{
-		return stream.seekable();
-	}
+	public var canSeek(get,never):Bool;
+	inline function get_canSeek():Bool return stream.seekable();
 
 	override public function close():Void
 	{
@@ -73,22 +69,15 @@ class NativeInput<T:IOBase> extends Input{
 		throw "abstract method, should be overriden";
 	}
 
-	override public function readBytes(s:haxe.io.Bytes, pos:Int, len:Int):Int
-	{
+	override public function readBytes(s:haxe.io.Bytes, pos:Int, len:Int):Int {
 		if( pos < 0 || len < 0 || pos + len > s.length )
 			throw haxe.io.Error.OutsideBounds;
 
-
-		if (canSeek) {
-			seek(pos, SeekBegin);
-		} else if (pos > 0) {
-			throw "Cannot call readBytes for pos > 0 (" + pos + ") on not seekable stream";
-		}
 		var ba = new Bytearray(len);
 		var ret = readinto(ba);
-		s.blit(pos, haxe.io.Bytes.ofData(ba) ,0,len);
 		if (ret == 0)
 			throwEof();
+		s.blit(pos, haxe.io.Bytes.ofData(ba), 0, len);
 		return ret;
 	}
 }

+ 2 - 6
std/python/io/NativeOutput.hx

@@ -30,7 +30,8 @@ class NativeOutput<T:IOBase> extends Output {
 
 	var stream:T;
 
-	public var canSeek(get_canSeek, null):Bool;
+	public var canSeek(get,never):Bool;
+	inline function get_canSeek():Bool return stream.seekable();
 
 	public function new (stream:T) {
 		this.bigEndian = false;
@@ -43,11 +44,6 @@ class NativeOutput<T:IOBase> extends Output {
 		stream.close();
 	}
 
-	private function get_canSeek():Bool
-	{
-		return stream.seekable();
-	}
-
 	override public function prepare(nbytes:Int):Void
 	{
 		stream.truncate(nbytes);

+ 90 - 23
tests/RunCi.hx

@@ -169,7 +169,10 @@ class RunCi {
 				Sys.putEnv("DISPLAY", ":99.0");
 				runCommand("sh", ["-e", "/etc/init.d/xvfb", "start"]);
 				Sys.putEnv("AUDIODEV", "null");
-				requireAptPackages(["libgd2-xpm", "ia32-libs", "ia32-libs-multiarch"]);
+				requireAptPackages([
+					"libcurl3:i386", "libglib2.0-0:i386", "libx11-6:i386", "libxext6:i386",
+					"libxt6:i386", "libxcursor1:i386", "libnss3:i386", "libgtk2.0-0:i386"	
+				]);
 				runCommand("wget", ["-nv", "http://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz"], true);
 				runCommand("tar", ["-xf", "flashplayer_11_sa_debug.i386.tar.gz", "-C", Sys.getEnv("HOME")]);
 				File.saveContent(mmcfgPath, "ErrorReportingEnable=1\nTraceOutputFileEnable=1");
@@ -245,7 +248,8 @@ class RunCi {
 				runCommand(exe, args);
 				switch (ci) {
 					case AppVeyor:
-						runCommand("mono", [exe].concat(args));
+						// https://github.com/HaxeFoundation/haxe/issues/4873
+						// runCommand("mono", [exe].concat(args));
 					case _:
 						//pass
 				}
@@ -595,15 +599,36 @@ class RunCi {
 				throw haxe_ver;
 		}
 	}
+	static var haxeVerFull(default, never) = {
+		var ver = haxeVer.split(".");
+		while (ver.length < 3) {
+			ver.push("0");
+		}
+		ver.join(".");
+	}
+
+	static function deploy():Void {
+		if (
+			Sys.getEnv("DEPLOY") != null
+		) {
+			changeDirectory(repoDir);
+
+			// generate doc
+			runCommand("make", ["-s", "install_dox"]);
+			runCommand("make", ["-s", "package_doc"]);
 
-	static function bintray():Void {
+			deployBintray();
+			deployApiDoc();
+			deployPPA();
+		}
+	}
+
+	static function deployBintray():Void {
 		if (
 			Sys.getEnv("BINTRAY") != null &&
 			Sys.getEnv("BINTRAY_USERNAME") != null &&
 			Sys.getEnv("BINTRAY_API_KEY") != null
 		) {
-			changeDirectory(repoDir);
-
 			// generate bintray config
 			var tpl = new Template(File.getContent("extra/bintray.tpl.json"));
 			var compatDate = ~/[^0-9]/g.replace(gitInfo.date, "");
@@ -624,24 +649,66 @@ class RunCi {
 			File.saveContent("extra/bintray.json", json);
 			infoMsg("saved " + FileSystem.absolutePath(path) + " with content:");
 			Sys.println(json);
+		}
+	}
 
-			// generate doc
-			runCommand("make", ["-s", "install_dox"]);
-			runCommand("make", ["-s", "package_doc"]);
+	/**
+		Deploy doc to api.haxe.org.
+	*/
+	static function deployApiDoc():Void {
+		if (
+			gitInfo.branch == "development" &&
+			Sys.getEnv("DEPLOY") != null &&
+			Sys.getEnv("deploy_key_decrypt") != null
+		) {
+			// setup deploy_key
+			runCommand("openssl aes-256-cbc -k \"$deploy_key_decrypt\" -in extra/deploy_key.enc -out extra/deploy_key -d");
+			runCommand("chmod 600 extra/deploy_key");
+			runCommand("ssh-add extra/deploy_key");
 
-			// deploy doc to api.haxe.org
-			if (
-				gitInfo.branch == "development" && 
-				Sys.getEnv("DEPLOY") != null && 
-				Sys.getEnv("deploy_key_decrypt") != null
-			) {
-				//setup deploy_key
-				runCommand("openssl aes-256-cbc -k \"$deploy_key_decrypt\" -in extra/deploy_key.enc -out extra/deploy_key -d");
-				runCommand("chmod 600 extra/deploy_key");
-				runCommand("ssh-add extra/deploy_key");
-
-				runCommand("make", ["-s", "deploy_doc"]);
-			}
+			runCommand("make", ["-s", "deploy_doc"]);
+		}
+	}
+
+	/**
+		Deploy source package to ppa:haxe/snapshots.
+	*/
+	static function deployPPA():Void {
+		if (
+			gitInfo.branch == "development" && 
+			Sys.getEnv("DEPLOY") != null && 
+			Sys.getEnv("haxeci_decrypt") != null
+		) {
+			// setup haxeci_ssh
+			runCommand("openssl aes-256-cbc -k \"$haxeci_decrypt\" -in extra/haxeci_ssh.enc -out extra/haxeci_ssh -d");
+			runCommand("chmod 600 extra/haxeci_ssh");
+			runCommand("ssh-add extra/haxeci_ssh");
+			// setup haxeci_sec.gpg
+			runCommand("openssl aes-256-cbc -k \"$haxeci_decrypt\" -in extra/haxeci_sec.gpg.enc -out extra/haxeci_sec.gpg -d");
+			runCommand("gpg --allow-secret-key-import --import extra/haxeci_sec.gpg");
+			runCommand("sudo apt-get install devscripts git-buildpackage ubuntu-dev-tools dh-make -y");
+			var compatDate = ~/[^0-9]/g.replace(gitInfo.date, "");
+			var SNAPSHOT_VERSION = '${haxeVerFull}+1SNAPSHOT${compatDate}+${gitInfo.commit.substr(0,7)}';
+			runCommand('cp out/haxe*_src.tar.gz "../haxe_${SNAPSHOT_VERSION}.orig.tar.gz"');
+			changeDirectory("..");
+			runCommand("git clone https://github.com/HaxeFoundation/haxe-debian.git");
+			changeDirectory("haxe-debian");
+			runCommand("git checkout upstream");
+			runCommand("git checkout next");
+			runCommand('gbp import-orig "../haxe_${SNAPSHOT_VERSION}.orig.tar.gz" -u "${SNAPSHOT_VERSION}" --debian-branch=next');
+			runCommand('dch -v "1:${SNAPSHOT_VERSION}-1" --urgency low "snapshot build"');
+			runCommand("debuild -S -sa");
+			runCommand("backportpackage -d xenial  --upload ${PPA} --yes ../haxe_*.dsc");
+			runCommand("backportpackage -d wily    --upload ${PPA} --yes ../haxe_*.dsc");
+			runCommand("backportpackage -d vivid   --upload ${PPA} --yes ../haxe_*.dsc");
+			runCommand("backportpackage -d trusty  --upload ${PPA} --yes ../haxe_*.dsc");
+			runCommand("git checkout debian/changelog");
+			runCommand("git config --global user.name \"${DEBFULLNAME}\"");
+			runCommand("git config --global user.email \"${DEBEMAIL}\"");
+			runCommand("git merge -X ours --no-edit origin/backport-precise");
+			runCommand('dch -v "1:${SNAPSHOT_VERSION}-1" --urgency low "snapshot build"');
+			runCommand("debuild -S -sa");
+			runCommand("backportpackage -d precise --upload ${PPA} --yes ../haxe_*.dsc");
 		}
 	}
 
@@ -780,8 +847,6 @@ class RunCi {
 	static function main():Void {
 		Sys.putEnv("OCAMLRUNPARAM", "b");
 
-		bintray();
-
 		var tests:Array<TEST> = switch (Sys.getEnv("TEST")) {
 			case null:
 				[Macro];
@@ -1086,6 +1151,8 @@ class RunCi {
 		) {
 			saveOutput();
 		}
+
+		deploy();
 	}
 
 	static function testHxTemplo() {

+ 11 - 0
tests/misc/projects/Issue2148/Main1.hx

@@ -0,0 +1,11 @@
+enum E {
+    CTor(i:Int);
+}
+
+class Main {
+    static public function main() {
+        expectE(CTor(foo));
+    }
+
+    static function expectE(e:E) { }
+}

+ 2 - 0
tests/misc/projects/Issue2148/compile1-fail.hxml

@@ -0,0 +1,2 @@
+-main Main1
+--interp

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

@@ -0,0 +1 @@
+Main1.hx:7: characters 21-24 : Unknown identifier : foo

+ 8 - 0
tests/misc/projects/Issue2232/Main1.hx

@@ -0,0 +1,8 @@
+class Main1 {
+    static function main() {
+		var v : Float = 0;
+		foo(v,v);
+    }
+
+	static function foo(x=0,y=0) { }
+}

+ 8 - 0
tests/misc/projects/Issue2232/Main2.hx

@@ -0,0 +1,8 @@
+class Main1 {
+    static function main() {
+		var v : Float = 0;
+		foo(v);
+    }
+
+	static function foo(x=0,y:Float) { }
+}

+ 3 - 0
tests/misc/projects/Issue2232/compile1-fail.hxml

@@ -0,0 +1,3 @@
+-main Main1
+-swf swf.swf
+--no-output

+ 2 - 0
tests/misc/projects/Issue2232/compile1-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main1.hx:4: characters 6-7 : Float should be Int
+Main1.hx:4: characters 6-7 : For optional function argument 'x'

+ 3 - 0
tests/misc/projects/Issue2232/compile2-fail.hxml

@@ -0,0 +1,3 @@
+-main Main2
+-swf swf.swf
+--no-output

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

@@ -0,0 +1 @@
+Main2.hx:4: characters 2-8 : Cannot skip non-nullable argument x

+ 0 - 0
tests/misc/projects/Issue2278/compile.hxml → tests/misc/projects/Issue2278/compile.hxml.disabled


+ 5 - 0
tests/misc/projects/Issue3192/Main1.hx

@@ -0,0 +1,5 @@
+class Main {
+    static function main() {
+		var a:{a:Int} = { a: 1, b: 2 };
+    }
+}

+ 2 - 0
tests/misc/projects/Issue3192/compile1-fail.hxml

@@ -0,0 +1,2 @@
+-main Main1
+--interp

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

@@ -0,0 +1 @@
+Main1.hx:3: characters 18-32 : { b : Int, a : Int } has extra field b

+ 0 - 2
tests/misc/projects/Issue3782/compile-fail.hxml

@@ -1,2 +0,0 @@
--main Main
---interp

+ 3 - 0
tests/misc/projects/Issue3782/compile-fail.hxml.disabled

@@ -0,0 +1,3 @@
+-main Main
+--interp
+-D no-analyzer

+ 21 - 0
tests/misc/projects/Issue4448/Main1.hx

@@ -0,0 +1,21 @@
+abstract A(Int) {
+    function f() {}
+
+    var v(get,never):Int;
+    function get_v() return this;
+
+    var v2(get,never):Int;
+    inline function get_v2() return this;
+
+    static function e() {
+        f(); // Not enough arguments, expected this:Int - should be just unavailable
+        v; // generates _$Main_A_$Impl_$.get_v();
+        v2; // Invalid abstract implementation function
+    }
+}
+
+class Main {
+	static function main() {
+
+	}
+}

+ 2 - 0
tests/misc/projects/Issue4448/compile1-fail.hxml

@@ -0,0 +1,2 @@
+-main Main1
+--interp

+ 3 - 0
tests/misc/projects/Issue4448/compile1-fail.hxml.stderr

@@ -0,0 +1,3 @@
+Main1.hx:11: characters 8-9 : Cannot access non-static field f from static method
+Main1.hx:12: characters 8-9 : Cannot access non-static field v from static method
+Main1.hx:13: characters 8-10 : Cannot access non-static field v2 from static method

+ 6 - 0
tests/misc/projects/Issue4671/Main1.hx

@@ -0,0 +1,6 @@
+interface IFoo extends IBar{}
+interface IBar extends IFoo{}
+
+class Main1 {
+	static function main() { }
+}

+ 6 - 0
tests/misc/projects/Issue4671/Main2.hx

@@ -0,0 +1,6 @@
+class A extends B { }
+class B extends A { }
+
+class Main1 {
+	static function main() { }
+}

+ 2 - 0
tests/misc/projects/Issue4671/compile1-fail.hxml

@@ -0,0 +1,2 @@
+-main Main1
+--interp

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

@@ -0,0 +1 @@
+Main1.hx:1: characters 0-29 : Recursive class

+ 2 - 0
tests/misc/projects/Issue4671/compile2-fail.hxml

@@ -0,0 +1,2 @@
+-main Main2
+--interp

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

@@ -0,0 +1 @@
+Main2.hx:1: characters 0-21 : Recursive class

+ 6 - 0
tests/misc/projects/Issue4816/Main1.hx

@@ -0,0 +1,6 @@
+class Main {
+    static function main() {
+        var f = { f : { name : "hello" } };
+        trace( macro $i{f.name} );
+    }
+}

+ 2 - 0
tests/misc/projects/Issue4816/compile1-fail.hxml

@@ -0,0 +1,2 @@
+-main Main1
+--interp

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

@@ -0,0 +1 @@
+Main1.hx:4: characters 24-30 : { f : { name : String } } has no field name

+ 13 - 7
tests/optimization/src/TestJs.hx

@@ -45,7 +45,7 @@ class TestJs {
 		for (v in a) { }
 	}
 
-	@:js('var a = 1;var v2 = a;if(a + v2 > 0) TestJs["use"](a);')
+	@:js('var a = 1;var v2 = a;if(a + v2 > 0) {TestJs["use"](a);}')
 	@:analyzer(no_const_propagation)
 	@:analyzer(no_copy_propagation)
 	@:analyzer(no_local_dce)
@@ -61,7 +61,7 @@ class TestJs {
 		return v + v2;
 	}
 
-	@:js("var a = [];a;")
+	@:js("var a = [];var tmp;try {tmp = a[0];} catch( e ) {tmp = null;}tmp;")
 	@:analyzer(no_local_dce)
 	static function testInlineWithComplexExpr() {
 		var a = [];
@@ -90,7 +90,7 @@ class TestJs {
 		forEach(function(x) trace(x + 2));
 	}
 
-	@:js('var a = "";var e;var __ex0 = a;var _g = __ex0.toLowerCase();switch(_g) {case "e":e = 0;break;default:throw new Error();}')
+	@:js('var a = "";var __ex0 = a;var e;var _g = __ex0.toLowerCase();switch(_g) {case "e":e = 0;break;default:throw new Error();}')
 	@:analyzer(no_const_propagation, no_local_dce, no_copy_propagation)
 	static function testRValueSwitchWithExtractors() {
 		var a = "";
@@ -229,7 +229,7 @@ class TestJs {
 
 	@:js('
 		var map = new haxe_ds_StringMap();
-		if(__map_reserved.some != null) map.setReserved("some",2); else map.h["some"] = 2;
+		if(__map_reserved.some != null) {map.setReserved("some",2);} else {map.h["some"] = 2;}
 		TestJs["use"](2);
 	')
 	static function testIssue4731() {
@@ -281,9 +281,13 @@ class TestJs {
 
 	@:js('
 		var a = 0;
-		if(Math.random() < 0.5) a = 2;
+		if(Math.random() < 0.5) {
+			a = 2;
+		}
 		var b = "";
-		if(Math.random() < 0.5) b = "hello";
+		if(Math.random() < 0.5) {
+			b = "hello";
+		}
 		TestJs["use"](a);
 		TestJs["use"](b);
 	')
@@ -443,7 +447,9 @@ class TestJs {
 
 	@:js('
 		TestJs.getInt();
-		if(TestJs.getInt() != 0) throw new js__$Boot_HaxeError("meh");
+		if(TestJs.getInt() != 0) {
+			throw new js__$Boot_HaxeError("meh");
+		}
 	')
 	static function testIfInvert() {
 		var tmp;

+ 2 - 2
tests/unit/compile-hl.hxml

@@ -1,4 +1,4 @@
 compile-each.hxml
 -main unit.Test
--hl bin/unit.hl
--D interp
+-hl d:/projects/hxtools/hl/src/_main.c
+-D interp

+ 30 - 0
tests/unit/issues/Issue3762.hx

@@ -0,0 +1,30 @@
+package unit.issues;
+import unit.Test;
+import haxe.ds.IntMap;
+
+class Issue3762 extends Test
+{
+	function test()
+	{
+		// test fast iterators against normal keys
+		var d = new IntMap<Int>();
+		var keys = [1, 2, 3];
+		for (i in 0...keys.length) {
+			var k = keys[i];
+			d.set(k, i);
+		}
+		var keyCount:Int = 0;
+		for (k in d.keys()) {
+			f( keys.indexOf(k) == -1 ); // key missing from keys iterator
+			keyCount++;
+		}
+		f( keyCount != keys.length ); // keys missing
+		var keyCount:Int = 0;
+		for (v in d) {
+			f(v < 0 || v >= keys.length); // bad value iterated
+			keyCount++;
+		}
+		f(keyCount != keys.length); // values missing
+
+	}
+}

+ 17 - 0
tests/unit/src/unit/issues/Issue3192.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+
+class Issue3192 extends Test {
+	function test() {
+		var x1 = {x:1, y:2};
+		var x2 = ({x:1, y:2}:{x:Int,y:Int});
+		var x3:{x:Int,y:Int} = {x:1, y:2};
+		var y1:{} = x1;
+		var y2:{} = x2;
+		var y3:{} = x3;
+		var z1:{x:Int} = x1;
+		var z2:{x:Int} = x2;
+		var z3:{x:Int} = x3;
+		eq(1, x1.x);
+		eq(2, x1.y);
+	}
+}

+ 23 - 0
tests/unit/src/unit/issues/Issue3528.hx

@@ -0,0 +1,23 @@
+package unit.issues;
+
+private abstract Optional<T>(haxe.ds.Option<T>) from haxe.ds.Option<T> {}
+
+class Issue3528 extends Test {
+    function test() {
+		var x = test1(Some(4));
+
+		test2(Some(4));
+		switch test2(x) {
+			case Some(v):
+			case None:
+		}
+    }
+
+	static function test1(v:haxe.ds.Option<Int>) {
+		return v;
+	}
+
+	static function test2(v:Optional<Int>) {
+		return v;
+	}
+}

+ 21 - 0
tests/unit/src/unit/issues/Issue4121.hx

@@ -0,0 +1,21 @@
+package unit.issues;
+
+import unit.issues.misc.Issue4121Macro.wrap;
+
+private typedef P2 = {
+	var hidden(null, null):Int;
+}
+
+class Issue4121 extends Test {
+	function test() {
+		eq("(@:test ((x) = (1)))", wrap(@:test x = 1));
+		eq("(@:test (@:test2 ((x) = (@:test3 (1)))))", wrap(@:test @:test2 x = @:test3 1));
+
+		var p2:P2 = { hidden: 12 };
+		t(unit.TestType.typeError(p2.hidden));
+		eq(12, @:privateAccess p2.hidden);
+		t(unit.TestType.typeError(p2.hidden = 13));
+		@:privateAccess p2.hidden = 13;
+		eq(13, @:privateAccess p2.hidden);
+	}
+}

+ 68 - 0
tests/unit/src/unit/issues/Issue4526.hx

@@ -0,0 +1,68 @@
+package unit.issues;
+
+@:structInit
+private class Struct1 {
+	var x:Int;
+	var y:Int;
+	public function get() {
+		return x + " " + y;
+	}
+}
+
+@:structInit
+private class Struct2 {
+	@:optional var x:Int;
+	var y:Int;
+	public function get() {
+		return x + " " + y;
+	}
+}
+
+@:structInit
+private class Struct3 {
+	@:optional var x:Int;
+	@:optional var y:Int;
+	public function get() {
+		return x + " " + y;
+	}
+}
+
+@:structInit
+private class Struct4 {
+	var x:Int;
+	var y:Int;
+	var z:Int;
+	public function get() {
+		return x + " " + y + " " + z;
+	}
+}
+
+class Issue4526 extends Test {
+	function test() {
+		var fieldNull = #if (cpp || flash || java || cs) 0 #else null #end;
+
+		var s1:Struct1 = { x: 12, y: 13 };
+		eq("12 13", s1.get());
+		t(unit.TestType.typeError(({x:12} : Struct1)));
+		t(unit.TestType.typeError(({y:12} : Struct1)));
+
+		var s2:Struct2 = { x: 12, y: 13 };
+		eq("12 13", s2.get());
+		var s2:Struct2 = { y: 13 };
+		eq(fieldNull + " 13", s2.get());
+		t(unit.TestType.typeError(({x:12} : Struct2)));
+
+		var s3:Struct3 = { x: 12, y: 13 };
+		eq("12 13", s3.get());
+		var s3:Struct3 = { y: 13 };
+		eq(fieldNull + " 13", s3.get());
+		var s3:Struct3 = { };
+		eq(fieldNull + " " + fieldNull, s3.get());
+	}
+
+	function testOrder() {
+		var i = 0;
+		var s4:Struct4 = { y: i++, x: i++, z: i++ };
+		eq("1 0 2", s4.get());
+	}
+}

+ 11 - 0
tests/unit/src/unit/issues/Issue4777.hx

@@ -0,0 +1,11 @@
+package unit.issues;
+
+private abstract A(String) from String {}
+
+class Issue4777 extends Test {
+	function test() {
+		var map:Map<A, String> = new Map();
+		map["foo"] = "bar";
+		eq("bar", map["foo"]);
+	}
+}

+ 13 - 0
tests/unit/src/unit/issues/Issue4843.hx

@@ -0,0 +1,13 @@
+package unit.issues;
+
+private abstract A({}) from {} {
+	@:from static function fromB(b:{a:Int}):A {
+		return null;
+	}
+}
+
+class Issue4843 extends Test {
+	function test() {
+		var a:A = {};
+	}
+}

+ 28 - 0
tests/unit/src/unit/issues/Issue4862.hx

@@ -0,0 +1,28 @@
+package unit.issues;
+
+#if js
+@:native("__issue4862__http_status")
+@:enum private extern abstract HttpStatus(Int) to Int {
+    var Ok;
+    var NotFound;
+
+    static function __init__():Void {
+        untyped __js__("var __issue4862__http_status = {Ok: 200, NotFound: 404};");
+    }
+}
+#end
+
+class Issue4862 extends Test {
+    #if js
+    function test() {
+        var a = Ok;
+        eq(200, a);
+        var b = HttpStatus.NotFound;
+        eq(404, b);
+        t(switch (a) { case HttpStatus.Ok: true; default: false; });
+        t(switch (b) { case HttpStatus.NotFound: true; default: false; });
+        t(switch (a) { case Ok: true; default: false; });
+        t(switch (b) { case NotFound: true; default: false; });
+    }
+    #end
+}

+ 21 - 0
tests/unit/src/unit/issues/Issue4867.hx

@@ -0,0 +1,21 @@
+package unit.issues;
+
+@:enum
+private abstract EnumAbstract(Int) to Int {
+    var a = 0;
+    var b = 1;
+
+    @:from
+    public static function fromString(s:String):EnumAbstract {
+        if (s == "b")
+            return b;
+        return a;
+    }
+}
+
+class Issue4867 extends Test {
+	function test() {
+		var b:EnumAbstract = "b";
+		eq(1, b);
+	}
+}

+ 23 - 0
tests/unit/src/unit/issues/Issue4885.hx

@@ -0,0 +1,23 @@
+package unit.issues;
+
+private class Context {
+
+	public var name:String;
+
+	public function new(n:String):Void {
+		name = n;
+	}
+
+}
+
+class Issue4885 extends Test {
+	function test() {
+        var
+            raw:String = "My name is ::name::.",
+            context:Context = new Context("Joan"),
+            template:haxe.Template = new haxe.Template(raw),
+            output:String = template.execute(context)
+        ;
+        eq("My name is Joan.", output);
+	}
+}

+ 22 - 0
tests/unit/src/unit/issues/Issue4886.hx

@@ -0,0 +1,22 @@
+package unit.issues;
+
+private class C {
+	@:extern inline function get() {
+		var intStruct = { i: 0 };
+		return intStruct;
+	}
+
+	var a = [get(), get(), get()];
+
+	public var b:Bool;
+	public function new() {
+		b = a[0] == a[1];
+	}
+}
+
+class Issue4886 extends Test {
+	function test() {
+		var c = new C();
+		f(c.b);
+	}
+}

+ 12 - 0
tests/unit/src/unit/issues/Issue4889.hx

@@ -0,0 +1,12 @@
+package unit.issues;
+
+class Issue4889 extends Test {
+	function test() {
+		var f = getFloat();
+		t(!(f > Math.NaN));
+	}
+
+	static function getFloat() {
+		return 1.0;
+	}
+}

+ 14 - 0
tests/unit/src/unit/issues/misc/Issue4121Macro.hx

@@ -0,0 +1,14 @@
+package unit.issues.misc;
+
+import haxe.macro.Expr;
+using haxe.macro.Tools;
+
+class Issue4121Macro {
+	macro static public function wrap(e:Expr) {
+		function addParens(e:Expr) {
+			return macro (${e.map(addParens)});
+		}
+		var e = addParens(e);
+		return macro $v{e.toString()};
+	}
+}

+ 12 - 9
tests/unit/src/unitstd/haxe/ds/Vector.unit.hx

@@ -135,15 +135,18 @@ vec.join(", ") == "foo, bar";
 
 // map
 
-//var vec = new haxe.ds.Vector(0);
-//vec.map(function(i) return throw false);
-//
-//var vec = new haxe.ds.Vector(2);
-//vec[0] = 12;
-//vec[1] = 13;
-//var vec2 = vec.map(function(i) return "value: " +i);
-//vec2[0] == "value: 12";
-//vec2[1] == "value: 13";
+var vec = new haxe.ds.Vector(0);
+vec.map(function(i) {
+	throw false;
+	return null;
+});
+
+var vec = new haxe.ds.Vector(2);
+vec[0] = 12;
+vec[1] = 13;
+var vec2 = vec.map(function(i) return "value: " +i);
+vec2[0] == "value: 12";
+vec2[1] == "value: 13";
 
 // sort
 

+ 1 - 1
tests/unit/unit-js.html

@@ -7,7 +7,7 @@
         <meta name="viewport" content="width=device-width, initial-scale=1">
     </head>
     <body id="haxe:trace">
-        <script type="text/javascript" src="//code.jquery.com/jquery-1.11.3.min.js"></script>
+        <script type="text/javascript" src="//code.jquery.com/jquery-1.12.1.min.js"></script>
         <script type="text/javascript">
             // http://stackoverflow.com/questions/11582512/how-to-get-url-parameters-with-javascript
             function getURLParameter(name) {

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません