فهرست منبع

Merge branch 'development'

Simon Krajewski 8 سال پیش
والد
کامیت
95993d3c67
100فایلهای تغییر یافته به همراه1264 افزوده شده و 646 حذف شده
  1. 6 2
      Makefile
  2. 8 5
      appveyor.yml
  3. 18 0
      extra/CHANGES.txt
  4. 3 2
      extra/choco/haxe.nuspec
  5. 1 1
      extra/haxelib_src
  6. 1 1
      extra/installer.nsi
  7. 3 1
      src/context/common.ml
  8. 1 1
      src/display/display.ml
  9. 7 9
      src/display/displayOutput.ml
  10. 4 4
      src/generators/gencpp.ml
  11. 1 1
      src/generators/genhl.ml
  12. 1 0
      src/generators/genjs.ml
  13. 55 31
      src/generators/genlua.ml
  14. 1 1
      src/generators/genphp.ml
  15. 230 325
      src/generators/genphp7.ml
  16. 1 1
      src/globals.ml
  17. 2 2
      src/macro/macroContext.ml
  18. 3 3
      src/main.ml
  19. 5 5
      src/optimization/analyzer.ml
  20. 2 0
      src/optimization/analyzerTexpr.ml
  21. 6 3
      src/optimization/analyzerTexprTransformer.ml
  22. 10 9
      src/optimization/analyzerTypes.ml
  23. 0 4
      src/optimization/filters.ml
  24. 1 0
      src/optimization/optimizer.ml
  25. 302 0
      src/sourcemaps.ml
  26. 13 1
      src/typing/type.ml
  27. 14 3
      src/typing/typeload.ml
  28. 13 14
      src/typing/typer.ml
  29. 1 0
      std/Any.hx
  30. 6 6
      std/Array.hx
  31. 1 1
      std/List.hx
  32. 4 4
      std/String.hx
  33. 1 1
      std/StringTools.hx
  34. 2 2
      std/Sys.hx
  35. 1 1
      std/Xml.hx
  36. 2 2
      std/cpp/Callable.hx
  37. 3 2
      std/cpp/Function.hx
  38. 37 0
      std/cpp/NativeGc.hx
  39. 3 5
      std/cpp/_std/StringBuf.hx
  40. 2 2
      std/cpp/_std/sys/net/Socket.hx
  41. 1 0
      std/cpp/cppia/HostClasses.hx
  42. 1 1
      std/cpp/vm/Debugger.hx
  43. 35 46
      std/cpp/vm/Gc.hx
  44. 6 6
      std/cs/_std/sys/net/Socket.hx
  45. 1 1
      std/cs/types/Char16.hx
  46. 1 1
      std/cs/types/Int16.hx
  47. 1 1
      std/cs/types/Int64.hx
  48. 1 1
      std/cs/types/Int8.hx
  49. 1 1
      std/cs/types/UInt16.hx
  50. 1 1
      std/cs/types/UInt64.hx
  51. 1 1
      std/cs/types/UInt8.hx
  52. 1 1
      std/haxe/CallStack.hx
  53. 1 1
      std/haxe/Json.hx
  54. 4 4
      std/haxe/Ucs2.hx
  55. 1 1
      std/haxe/Utf8.hx
  56. 0 2
      std/haxe/io/BytesData.hx
  57. 3 3
      std/haxe/macro/Context.hx
  58. 2 2
      std/haxe/macro/Expr.hx
  59. 1 1
      std/haxe/macro/TypeTools.hx
  60. 1 1
      std/haxe/remoting/ExternalConnection.hx
  61. 1 1
      std/haxe/remoting/SocketProtocol.hx
  62. 3 3
      std/haxe/xml/Parser.hx
  63. 55 1
      std/hl/Gc.hx
  64. 1 0
      std/hl/_std/sys/io/FileInput.hx
  65. 1 0
      std/hl/_std/sys/io/FileOutput.hx
  66. 2 2
      std/js/_std/Reflect.hx
  67. 1 1
      std/js/html/SpeechSynthesisEvent.hx
  68. 1 1
      std/lua/Coroutine.hx
  69. 12 10
      std/lua/Ffi.hx
  70. 1 1
      std/lua/HaxeIterator.hx
  71. 167 37
      std/lua/Math.hx
  72. 3 1
      std/lua/Table.hx
  73. 1 1
      std/lua/_std/EReg.hx
  74. 2 2
      std/lua/_std/Reflect.hx
  75. 2 1
      std/lua/_std/Std.hx
  76. 1 1
      std/lua/_std/Type.hx
  77. 1 1
      std/neko/Web.hx
  78. 1 1
      std/neko/net/ServerLoop.hx
  79. 3 3
      std/neko/vm/Loader.hx
  80. 1 1
      std/neko/vm/Thread.hx
  81. 1 1
      std/php/Boot.hx
  82. 3 3
      std/php/Web.hx
  83. 1 1
      std/php/_std/Std.hx
  84. 2 2
      std/php/_std/StringTools.hx
  85. 1 1
      std/php/_std/sys/FileSystem.hx
  86. 7 7
      std/php7/Boot.hx
  87. 40 0
      std/php7/NativeStructArray.hx
  88. 1 3
      std/php7/Resource.hx
  89. 3 3
      std/php7/Web.hx
  90. 2 0
      std/php7/_std/StringBuf.hx
  91. 17 4
      std/php7/_std/haxe/CallStack.hx
  92. 2 0
      std/php7/_std/haxe/io/BytesInput.hx
  93. 5 3
      std/php7/_std/sys/db/Mysql.hx
  94. 6 6
      std/python/_std/sys/net/Socket.hx
  95. 4 4
      std/python/lib/net/Socket.hx
  96. 2 2
      std/sys/FileStat.hx
  97. 6 6
      std/sys/net/Socket.hx
  98. 16 0
      tests/display/src/cases/Issue5988.hx
  99. 17 0
      tests/display/src/cases/Issue6029.hx
  100. 29 0
      tests/display/src/cases/Issue6068.hx

+ 6 - 2
Makefile

@@ -67,7 +67,7 @@ RELDIR=../../..
 MODULES=json version globals path context/meta syntax/ast display/displayTypes typing/type typing/error \
 	syntax/lexer context/common generators/genxml \
 	syntax/parser typing/abstract typing/typecore display/display optimization/optimizerTexpr \
-	optimization/optimizer typing/overloads typing/typeload generators/codegen generators/gencommon generators/genas3 \
+	optimization/optimizer typing/overloads typing/typeload sourcemaps generators/codegen generators/gencommon generators/genas3 \
 	generators/gencpp generators/genjs generators/genneko generators/genphp generators/genphp7 generators/genswf9 \
 	generators/genswf generators/genjava generators/gencs generators/genpy macro/macroApi macro/interp generators/hlcode generators/hlopt generators/hlinterp generators/hl2c \
 	generators/genlua \
@@ -164,6 +164,10 @@ src/display/displayTypes.$(MODULE_EXT) : src/globals.$(MODULE_EXT) src/syntax/as
 
 src/display/displayOutput.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/display/display.$(MODULE_EXT)
 
+# sourcemaps
+
+src/sourcemaps.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
+
 # generators
 
 src/generators/codegen.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
@@ -192,7 +196,7 @@ src/generators/genswf.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$
 
 src/generators/hlinterp.$(MODULE_EXT): src/context/common.$(MODULE_EXT) src/generators/hlcode.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/generators/hlopt.$(MODULE_EXT) src/macro/macroApi.$(MODULE_EXT)
 
-src/generators/genphp7.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
+src/generators/genphp7.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/sourcemaps.$(MODULE_EXT)
 
 src/generators/hl2c.$(MODULE_EXT): src/generators/hlcode.$(MODULE_EXT) src/context/common.$(MODULE_EXT)
 

+ 8 - 5
appveyor.yml

@@ -10,7 +10,8 @@ environment:
         MYSQL_USER: root
         MYSQL_PASSWORD: Password12!
     matrix:
-        - TEST: "neko,python,cs,java,macro,php7"
+        - TEST: "neko,python,cs,java,macro"
+        - TEST: "php7,php"
         - TEST: "cpp"
 
 services:
@@ -36,10 +37,12 @@ install:
     - '%CYG_ROOT%/bin/bash -lc "opam install camlp4 --yes"'
     # Install neko
     - choco install neko --prerelease --ignore-dependencies -s 'https://ci.appveyor.com/nuget/neko' -y
-    - choco install php --ignore-dependencies
-    - echo extension=php_mysqli.dll >> C:\tools\php\php.ini
-    - echo extension=php_sqlite3.dll >> C:\tools\php\php.ini
-    - echo extension=php_openssl.dll >> C:\tools\php\php.ini
+    - choco install chocolatey-core.extension php --ignore-dependencies -y
+    - echo extension=php_mysqli.dll >> C:\tools\php71\php.ini
+    - echo extension=php_sqlite3.dll >> C:\tools\php71\php.ini
+    - echo extension=php_openssl.dll >> C:\tools\php71\php.ini
+    - echo extension=php_pdo_mysql.dll >> C:\tools\php71\php.ini
+    - echo extension=php_pdo_sqlite.dll >> C:\tools\php71\php.ini
     - RefreshEnv
     - neko -version
     # setup python

+ 18 - 0
extra/CHANGES.txt

@@ -1,3 +1,21 @@
+2017-03-14: 3.4.1
+
+	New features:
+
+	php7 : added source maps generation with `-D source_map` flag.
+
+	Bugfixes:
+
+	all : fixed compilation server issue with two identical @:native paths on extern abstracts (#5993)
+	all : fixed invalid inling in a specific case (#6067)
+	all : fixed various display related issues
+	cpp : improved typing of some Function/Callable-related types
+	hl : various fixes and improvements
+	php : fixed FileSystem.stat() for directories on Windows (#6057)
+	php/php7 : fixed invalid result of Web.getPostData() (#6033)
+	php7 : fixed invalid access to length of string in some cases (#6055)
+	php7 : fixed infinite recursion on MysqlConnection.close() (#6056)
+
 2017-01-31: 3.4.0
 
 	General improvements and optimizations:

+ 3 - 2
extra/choco/haxe.nuspec

@@ -19,9 +19,10 @@
         <description>Haxe is an open source toolkit based on a modern, high level, strictly typed programming language, a cross-compiler, a complete cross-platform standard library and ways to access each platform's native capabilities.
  
 This package will install haxe and haxelib. After installation, you should run `haxelib setup &lt;path&gt;`, where `&lt;path&gt;` is the haxelib repository folder for placing third-party libraries. The folder should be created manually before running the command.</description>
-        <tags>haxe</tags>
+        <releaseNotes>https://github.com/HaxeFoundation/haxe/blob/master/extra/CHANGES.txt</releaseNotes>
+        <tags>haxe programming development foss cross-platform</tags>
         <dependencies>
-            <dependency id="neko" />
+            <dependency id="neko" version="2.1.0" />
         </dependencies>
     </metadata>
 </package>

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit 9d79a55ddb054d79ed8d136f1c0583baa407fd67
+Subproject commit eeac8f4e77b23b120f27d27502f43589db26d143

+ 1 - 1
extra/installer.nsi

@@ -20,7 +20,7 @@
 !define VERLONG "%%VERLONG%%"
 
 ; Define Neko info
-!define NEKO_VERSION "2.0.0"
+!define NEKO_VERSION "2.1.0"
 
 ; Installer details
 VIAddVersionKey "CompanyName" "Haxe Foundation"

+ 3 - 1
src/context/common.ml

@@ -487,6 +487,7 @@ module Define = struct
 		| JsEs
 		| JsUnflatten
 		| JsSourceMap
+		| SourceMap
 		| KeepOldOutput
 		| LoopUnrollMaxCost
 		| LuaVer
@@ -582,6 +583,7 @@ module Define = struct
 		| JsEs -> ("js_es","Generate JS compilant with given ES standard version (default 5)")
 		| JsUnflatten -> ("js_unflatten","Generate nested objects for packages and types")
 		| JsSourceMap -> ("js_source_map","Generate JavaScript source map even in non-debug mode")
+		| SourceMap -> ("source_map","Generate source map for compiled files (Currently supported for php7 only)")
 		| KeepOldOutput -> ("keep_old_output","Keep old source files in the output directory (for C#/Java)")
 		| LoopUnrollMaxCost -> ("loop_unroll_max_cost","Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)")
 		| LuaJit -> ("lua_jit","Enable the jit compiler for lua (version 5.2 only")
@@ -608,7 +610,7 @@ module Define = struct
 		| NoTraces -> ("no_traces","Disable all trace calls")
 		| Objc -> ("objc","Sets the hxcpp output to objective-c++ classes. Must be defined for interop")
 		| PhpPrefix -> ("php_prefix","Compiled with --php-prefix")
-		| RealPosition -> ("real_position","Disables Haxe source mapping when targetting C#, removes position comments in Java output")
+		| RealPosition -> ("real_position","Disables Haxe source mapping when targetting C#, removes position comments in Java and Php7 output")
 		| ReplaceFiles -> ("replace_files","GenCommon internal")
 		| Scriptable -> ("scriptable","GenCPP internal")
 		| ShallowExpose -> ("shallow-expose","Expose types to surrounding scope of Haxe generated closure without writing to window object")

+ 1 - 1
src/display/display.ml

@@ -27,7 +27,7 @@ exception Diagnostics of string
 exception Statistics of string
 exception ModuleSymbols of string
 exception Metadata of string
-exception DisplaySignatures of (t * documentation) list * int
+exception DisplaySignatures of (tsignature * documentation) list * int
 exception DisplayType of t * pos * string option
 exception DisplayPosition of pos list
 exception DisplayFields of (string * display_field_kind * documentation) list

+ 7 - 9
src/display/displayOutput.ml

@@ -103,11 +103,11 @@ let print_type t p doc =
 
 let print_signatures tl =
 	let b = Buffer.create 0 in
-	List.iter (fun (t,doc) ->
+	List.iter (fun ((args,ret),doc) ->
 		Buffer.add_string b "<type";
 		Option.may (fun s -> Buffer.add_string b (Printf.sprintf " d=\"%s\"" (htmlescape s))) doc;
 		Buffer.add_string b ">\n";
-		Buffer.add_string b (htmlescape (s_type (print_context()) (follow t)));
+		Buffer.add_string b (htmlescape (s_type (print_context()) (TFun(args,ret))));
 		Buffer.add_string b "\n</type>\n";
 	) tl;
 	Buffer.contents b
@@ -409,17 +409,15 @@ let print_signature tl display_arg =
 	let st = s_type (print_context()) in
 	let s_arg (n,o,t) = Printf.sprintf "%s%s:%s" (if o then "?" else "") n (st t) in
 	let s_fun args ret = Printf.sprintf "(%s):%s" (String.concat ", " (List.map s_arg args)) (st ret) in
-	let siginf = List.map (fun (t,doc) ->
-		let label = match follow t with TFun(args,ret) -> s_fun args ret | _ -> st t in
-		let parameters = match follow t with
-			| TFun(args,_) ->
-				List.map (fun arg ->
+	let siginf = List.map (fun ((args,ret),doc) ->
+		let label = s_fun args ret in
+		let parameters =
+			List.map (fun arg ->
 					let label = s_arg arg in
 					JObject [
 						"label",JString label
 					]
-				) args
-			| _ -> []
+			) args
 		in
 		let js = [
 			"label",JString label;

+ 4 - 4
src/generators/gencpp.ml

@@ -4012,9 +4012,9 @@ let is_dynamic_haxe_method f =
 
 
 let is_data_member field =
-   match field.cf_expr with
-   | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field
-   | _ -> true;;
+   match field.cf_kind with
+   | Var _ | Method MethDynamic -> true
+   | _ -> false;;
 
 
 let is_override class_def field =
@@ -5846,7 +5846,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
 
    let generate_script_function isStatic field scriptName callName =
       match follow field.cf_type  with
-      | TFun (args,return_type) ->
+      | TFun (args,return_type) when not (is_data_member field) ->
          output_cpp ("\nstatic void CPPIA_CALL " ^ scriptName ^ "(hx::CppiaCtx *ctx) {\n");
          let ret = script_signature return_type false in
          if (ret<>"v") then output_cpp ("ctx->return" ^ (script_type return_type false) ^ "(");

+ 1 - 1
src/generators/genhl.ml

@@ -2651,7 +2651,7 @@ and gen_assign_op ctx acc e1 f =
 			op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx (array_class ctx at).cl_path "__expand", ra, ridx));
 			j();
 			match at with
-			| HI32 | HF64 ->
+			| HUI8 | HUI16 | HI32 | HF32 | HF64 ->
 				let hbytes = alloc_tmp ctx HBytes in
 				op ctx (OField (hbytes, ra, 1));
 				let ridx = shl ctx ridx (type_size_bits at) in

+ 1 - 0
src/generators/genjs.ml

@@ -1104,6 +1104,7 @@ let generate_class ctx c =
 		| [] -> ()
 		| props ->
 			print ctx "%s.__properties__ = {%s}" p (gen_props props);
+			ctx.separator <- true;
 			newline ctx);
 	end;
 

+ 55 - 31
src/generators/genlua.ml

@@ -54,6 +54,7 @@ type object_store = {
 	mutable os_fields : object_store list;
 }
 
+
 let debug_expression expression  =
     " --[[ " ^ Type.s_expr_kind expression  ^ " --]] "
 
@@ -462,22 +463,13 @@ let rec gen_call ctx e el in_value =
 	| TField (e, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el ->
 		let s = (field_name ef) in
 		if Hashtbl.mem kwds s || not (valid_lua_ident s) then begin
-		    match e.eexpr with
-		    |TNew _-> (
-			add_feature ctx "use._hx_apply_self";
-			spr ctx "_hx_apply_self(";
-			gen_value ctx e;
-			print ctx ",\"%s\"" (field_name ef);
-			if List.length(el) > 0 then spr ctx ",";
-			concat ctx "," (gen_value ctx) el;
-			spr ctx ")";
-		    );
-		    |_ -> (
-			gen_value ctx e;
-			print ctx "%s(" (anon_field s);
-			concat ctx "," (gen_value ctx) (e::el);
-			spr ctx ")"
-		    )
+		    add_feature ctx "use._hx_apply_self";
+		    spr ctx "_hx_apply_self(";
+		    gen_value ctx e;
+		    print ctx ",\"%s\"" (field_name ef);
+		    if List.length(el) > 0 then spr ctx ",";
+		    concat ctx "," (gen_value ctx) el;
+		    spr ctx ")";
 		end else begin
 		    gen_value ctx e;
 		    print ctx ":%s(" (field_name ef);
@@ -840,7 +832,7 @@ and gen_expr ?(local=true) ctx e = begin
 		spr ctx "_hx_o({__fields__={";
 		concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); spr ctx "true") fields;
 		spr ctx "},";
-		concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); gen_value ctx e) fields;
+		concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); gen_anon_value ctx e) fields;
 		spr ctx "})";
 		ctx.separator <- true
 	| TFor (v,it,e) ->
@@ -1024,6 +1016,35 @@ and gen_block_element ctx e  =
 		semicolon ctx;
 	end;
 
+(* values generated in anon structures can get modified.  Functions are bind-ed *)
+(* and include a dummy "self" leading variable so they can be called like normal *)
+(* instance methods *)
+and gen_anon_value ctx e =
+    match e with
+    | { eexpr = TFunction f} ->
+	let old = ctx.in_value, ctx.in_loop in
+	ctx.in_value <- None;
+	ctx.in_loop <- false;
+	print ctx "function(%s) " (String.concat "," ("self" :: (List.map ident (List.map arg_name f.tf_args))));
+	let fblock = fun_block ctx f e.epos in
+	(match fblock.eexpr with
+	| TBlock el ->
+		let bend = open_block ctx in
+		List.iter (gen_block_element ctx) el;
+	    bend();
+	    newline ctx;
+	|_ -> ());
+	spr ctx "end";
+	ctx.in_value <- fst old;
+	ctx.in_loop <- snd old;
+	ctx.separator <- true
+    | { etype = TFun (args, ret)}  ->
+	spr ctx "function(_,...) return ";
+	gen_value ctx e;
+	spr ctx "(...) end";
+    | _->
+	gen_value ctx e
+
 and gen_value ctx e =
 	let assign e =
 		mk (TBinop (Ast.OpAssign,
@@ -1716,17 +1737,12 @@ let generate_type ctx = function
 			()
 		else if not c.cl_extern then
 			generate_class ctx c
-		else if Meta.has Meta.LuaRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
-			generate_require ctx c.cl_path c.cl_meta
 		else if Meta.has Meta.InitPackage c.cl_meta then
 			(match c.cl_path with
 			| ([],_) -> ()
 			| _ -> generate_package_create ctx c.cl_path);
 		check_multireturn ctx c;
-	| TEnumDecl e when e.e_extern ->
-		if Meta.has Meta.LuaRequire e.e_meta && is_directly_used ctx.com e.e_meta then
-		    generate_require ctx e.e_path e.e_meta;
-	| TEnumDecl e -> generate_enum ctx e
+	| TEnumDecl e when not e.e_extern -> generate_enum ctx e
 	| TTypeDecl _ | TAbstractDecl _ -> ()
 
 let generate_type_forward ctx = function
@@ -1735,13 +1751,17 @@ let generate_type_forward ctx = function
 		| None -> ()
 		| Some e ->
 			ctx.inits <- e :: ctx.inits);
-		if not c.cl_extern then begin
-		    generate_package_create ctx c.cl_path;
-		    let p = s_path ctx c.cl_path in
-		    println ctx "%s = _hx_e()" p;
-		end
+		if not c.cl_extern then
+		    begin
+			generate_package_create ctx c.cl_path;
+			let p = s_path ctx c.cl_path in
+			println ctx "%s = _hx_e()" p
+		    end
+		else if Meta.has Meta.LuaRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
+		    generate_require ctx c.cl_path c.cl_meta
 	| TEnumDecl e when e.e_extern ->
-		()
+		if Meta.has Meta.LuaRequire e.e_meta && is_directly_used ctx.com e.e_meta then
+		    generate_require ctx e.e_path e.e_meta;
 	| TEnumDecl e ->
 		generate_package_create ctx e.e_path;
 		let p = s_path ctx e.e_path in
@@ -1982,15 +2002,18 @@ let generate com =
 	println ctx "_hx_array_mt.__index = Array.prototype";
 	newline ctx;
 
+	let b = open_block ctx in
+	println ctx "local _hx_static_init = function()";
 	(* Generate statics *)
 	List.iter (generate_static ctx) (List.rev ctx.statics);
-
 	(* Localize init variables inside a do-block *)
 	(* Note: __init__ logic can modify static variables. *)
-	println ctx "do";
+	(* Generate statics *)
 	List.iter (gen_block_element ctx) (List.rev ctx.inits);
+	b();
 	newline ctx;
 	println ctx "end";
+	newline ctx;
 
 	let rec chk_features e =
 		if is_dynamic_iterator ctx e then add_feature ctx "use._iterator";
@@ -2092,6 +2115,7 @@ let generate com =
 	    println ctx "end;";
 	end;
 
+	println ctx "_hx_static_init();";
 
 	List.iter (generate_enumMeta_fields ctx) com.types;
 

+ 1 - 1
src/generators/genphp.ml

@@ -848,7 +848,7 @@ and gen_field_access ctx isvar e s =
 		gen_value ctx e;
 		spr ctx ")";
 		gen_member_access ctx isvar e s
-	| TCast (ec, _) when (match ec.eexpr with | TNew _ | TArrayDecl _ -> true | _ -> false) ->
+	| TCast (ec, _) when (match ec.eexpr with | TNew _ | TArrayDecl _ | TConst TNull -> true | _ -> false) ->
 		spr ctx "_hx_deref(";
 		ctx.is_call <- false;
 		gen_value ctx e;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 230 - 325
src/generators/genphp7.ml


+ 1 - 1
src/globals.ml

@@ -20,7 +20,7 @@ type platform =
 	| Python
 	| Hl
 
-let version = 3400
+let version = 3401
 let version_major = version / 1000
 let version_minor = (version mod 1000) / 100
 let version_revision = (version mod 100)

+ 2 - 2
src/macro/macroContext.ml

@@ -477,7 +477,6 @@ let get_macro_context ctx p =
 		api, mctx
 
 let load_macro ctx display cpath f p =
-	let t = macro_timer ctx ["typing";s_type_path cpath ^ "." ^ f] in
 	let api, mctx = get_macro_context ctx p in
 	let mint = Interp.get_ctx() in
 	let cpath, sub = (match List.rev (fst cpath) with
@@ -485,6 +484,7 @@ let load_macro ctx display cpath f p =
 		| _ -> cpath, None
 	) in
 	let meth = try Hashtbl.find mctx.com.cached_macros (cpath,f) with Not_found ->
+		let t = macro_timer ctx ["typing";s_type_path cpath ^ "." ^ f] in
 		(* Temporarily enter display mode while typing the macro. *)
 		if display then mctx.com.display <- ctx.com.display;
 		let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in
@@ -522,9 +522,9 @@ let load_macro ctx display cpath f p =
 			wildcard_packages = [];
 			module_imports = [];
 		};
+		t();
 		meth
 	in
-	t();
 	let call args =
 		let t = macro_timer ctx ["execution";s_type_path cpath ^ "." ^ f] in
 		incr stats.s_macros_called;

+ 3 - 3
src/main.ml

@@ -905,11 +905,11 @@ with
 	| Display.DisplayType (t,p,doc) ->
 		let doc = match doc with Some _ -> doc | None -> DisplayOutput.find_doc t in
 		raise (DisplayOutput.Completion (DisplayOutput.print_type t p doc))
-	| Display.DisplaySignatures(tl,display_arg) ->
+	| Display.DisplaySignatures(signatures,display_arg) ->
 		if ctx.com.display.dms_kind = DMSignature then
-			raise (DisplayOutput.Completion (DisplayOutput.print_signature tl display_arg))
+			raise (DisplayOutput.Completion (DisplayOutput.print_signature signatures display_arg))
 		else
-			raise (DisplayOutput.Completion (DisplayOutput.print_signatures tl))
+			raise (DisplayOutput.Completion (DisplayOutput.print_signatures signatures))
 	| Display.DisplayPosition pl ->
 		raise (DisplayOutput.Completion (DisplayOutput.print_positions pl))
 	| Display.DisplayToplevel il ->

+ 5 - 5
src/optimization/analyzer.ml

@@ -978,14 +978,14 @@ module Run = struct
 			(match e.eexpr with TFunction tf -> cf.cf_expr_unoptimized <- Some tf | _ -> ());
 			let actx = create_analyzer_context ctx.Typecore.com config e in
 			let debug() =
-				prerr_endline (Printf.sprintf "While analyzing %s.%s" (s_type_path c.cl_path) cf.cf_name);
+				print_endline (Printf.sprintf "While analyzing %s.%s" (s_type_path c.cl_path) cf.cf_name);
 				List.iter (fun (s,e) ->
-					prerr_endline (Printf.sprintf "<%s>" s);
-					prerr_endline (Type.s_expr_pretty true "" false (s_type (print_context())) e);
-					prerr_endline (Printf.sprintf "</%s>" s);
+					print_endline (Printf.sprintf "<%s>" s);
+					print_endline (Type.s_expr_pretty true "" false (s_type (print_context())) e);
+					print_endline (Printf.sprintf "</%s>" s);
 				) (List.rev actx.debug_exprs);
 				Debug.dot_debug actx c cf;
-				prerr_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (Debug.get_dump_path actx c cf)));
+				print_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (Debug.get_dump_path actx c cf)));
 			in
 			let e = try
 				run_on_expr actx e

+ 2 - 0
src/optimization/analyzerTexpr.ml

@@ -30,6 +30,8 @@ let rec is_true_expr e1 = match e1.eexpr with
 	| TParenthesis e1 -> is_true_expr e1
 	| _ -> false
 
+let is_stack_allocated c = Meta.has Meta.StructAccess c.cl_meta
+
 let map_values ?(allow_control_flow=true) f e =
 	let branching = ref false in
 	let efinal = ref None in

+ 6 - 3
src/optimization/analyzerTexprTransformer.ml

@@ -243,7 +243,7 @@ let rec func ctx bb tf t p =
 		end;
 		let bb = declare_var_and_assign bb v e e.epos in
 		let e = {e with eexpr = TLocal v} in
-		let e = List.fold_left (fun e f -> f e) e (List.rev fl) in
+		let e = List.fold_left (fun e f -> f e) e fl in
 		bb,e
 	and declare_var_and_assign bb v e p =
 		(* TODO: this section shouldn't be here because it can be handled as part of the normal value processing *)
@@ -333,7 +333,10 @@ let rec func ctx bb tf t p =
 		add_texpr bb {e with eexpr = TBinop(OpAssign,ea,eop)};
 		bb,ea
 	and field_assign_op bb op e ef e1 fa e2 =
-		let bb,e1 = bind_to_temp bb false e1 in
+		let bb,e1 = match fa with
+			| FInstance(c,_,_) | FClosure(Some(c,_),_) when is_stack_allocated c -> bb,e1
+			| _ -> bind_to_temp bb false e1
+		in
 		let ef = {ef with eexpr = TField(e1,fa)} in
 		let bb,e3 = bind_to_temp bb false ef in
 		let bb,e2 = bind_to_temp bb false e2 in
@@ -519,7 +522,7 @@ let rec func ctx bb tf t p =
 			block_element bb (mk (TReturn None) t_dynamic e.epos)
 		| TReturn (Some e1) ->
 			begin try
-				let mk_return e1 = mk (TReturn (Some e1)) t_dynamic e.epos in
+				let mk_return e1 = mk (TReturn (Some e1)) t_dynamic e1.epos in
 				block_element_value bb e1 mk_return
 			with Exit ->
 				let bb,e1 = value bb e1 in

+ 10 - 9
src/optimization/analyzerTypes.ml

@@ -211,17 +211,18 @@ module Graph = struct
 		} in
 		DynArray.add g.g_var_infos vi;
 		let i = DynArray.length g.g_var_infos - 1 in
-		v.v_extra <- Some([],Some (mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos))
+		v.v_extra <- Some([],Some (mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos));
+		vi
 
 	let get_var_info g v = match v.v_extra with
 		| Some(_,Some {eexpr = TConst (TInt i32)}) -> DynArray.get g.g_var_infos (Int32.to_int i32)
 		| _ ->
-			prerr_endline "Unbound variable, please report this";
-			prerr_endline (Printer.s_tvar v);
-			assert false
+			print_endline "Unbound variable, please report this";
+			print_endline (Printer.s_tvar v);
+			create_var_info g g.g_unreachable v
 
 	let declare_var g v bb =
-		create_var_info g bb v
+		ignore(create_var_info g bb v)
 
 	let add_var_def g bb v =
 		if bb.bb_id > 0 then begin
@@ -311,15 +312,15 @@ module Graph = struct
 		List.iter (fun bb ->
 			List.iter (fun edge ->
 				if edge.cfg_to = g.g_unreachable then
-					prerr_endline (Printf.sprintf "Outgoing edge from %i to the unreachable block" bb.bb_id)
+					print_endline (Printf.sprintf "Outgoing edge from %i to the unreachable block" bb.bb_id)
 				else if not (List.memq edge edge.cfg_to.bb_incoming) then
-					prerr_endline (Printf.sprintf "Outgoing edge %i -> %i has no matching incoming edge" edge.cfg_from.bb_id edge.cfg_to.bb_id)
+					print_endline (Printf.sprintf "Outgoing edge %i -> %i has no matching incoming edge" edge.cfg_from.bb_id edge.cfg_to.bb_id)
 			) bb.bb_outgoing;
 			List.iter (fun edge ->
 				if edge.cfg_from == g.g_unreachable then
-					prerr_endline (Printf.sprintf "Incoming edge to %i from the unreachable block" bb.bb_id)
+					print_endline (Printf.sprintf "Incoming edge to %i from the unreachable block" bb.bb_id)
 				else if not (List.memq edge edge.cfg_from.bb_outgoing) then
-					prerr_endline (Printf.sprintf "Incoming edge %i <- %i has no matching outgoing edge" edge.cfg_to.bb_id edge.cfg_from.bb_id)
+					print_endline (Printf.sprintf "Incoming edge %i <- %i has no matching outgoing edge" edge.cfg_to.bb_id edge.cfg_from.bb_id)
 			) bb.bb_incoming
 		) g.g_nodes
 

+ 0 - 4
src/optimization/filters.ml

@@ -776,10 +776,6 @@ let apply_native_paths ctx t =
 			let meta,path = get_real_path e.e_meta e.e_path in
 			e.e_meta <- meta :: e.e_meta;
 			e.e_path <- path;
-		| TAbstractDecl a ->
-			let meta,path = get_real_path a.a_meta a.a_path in
-			a.a_meta <- meta :: a.a_meta;
-			a.a_path <- path;
 		| _ ->
 			())
 	with Not_found ->

+ 1 - 0
src/optimization/optimizer.ml

@@ -426,6 +426,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 				let rec loop e =
 					let r = match e.eexpr with
 					| TReturn _ -> true
+					| TFunction _ -> false
 					| TIf (_,_,None) | TSwitch (_,_,None) | TFor _ | TWhile (_,_,NormalWhile) -> false (* we might not enter this code at all *)
 					| TTry (a, catches) -> List.for_all has_term_return (a :: List.map snd catches)
 					| TIf (cond,a,Some b) -> has_term_return cond || (has_term_return a && has_term_return b)

+ 302 - 0
src/sourcemaps.ml

@@ -0,0 +1,302 @@
+
+open Globals
+open Ast
+open Lexer
+open Common
+
+(**
+	Characters used for base64 VLQ encoding
+*)
+let chars = [|
+	'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P';
+	'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f';
+	'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v';
+	'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/'
+|]
+
+(**
+	Encode an integer in range 0...63 (including 63)
+*)
+let encode_digit digit = Array.unsafe_get chars digit
+
+(**
+	Move the sign bit to the least significant bit.
+	E.g.:
+		1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
+		2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
+*)
+let to_vlq number =
+	if number < 0 then
+		((-number) lsl 1) + 1
+	else
+		number lsl 1
+
+(**
+	Writes sourcemap for a signle `generated_file` to disk.
+	If your code generation is straightforward, you can use this class directly.
+	Otherwise use `sourcemap_builder` (e.g. if you need to generate some middle parts of a code and then generate the beginning).
+*)
+class sourcemap_writer (generated_file:string) =
+	object (self)
+		(** Output buffer for generated sourcemap *)
+		val buffer = Rbuffer.create 1024
+		(** Source Haxe files referenced by this sourcemap *)
+		val files = DynArray.create()
+		(** Positions of source Haxe files in `files` list *)
+		val files_indexes = Hashtbl.create 100
+		(** Index of a source file referenced in previous `map` call *)
+		val mutable last_src_file = 0
+		(** Zero-based index of a source line referenced in previous `map` call *)
+		val mutable last_src_line = 0
+		(** Zero-based index of a source column in a line referenced in previous `map` call *)
+		val mutable last_src_col = 0
+		(** Zero based index of a column in `generated_file` where last written string ended *)
+		val mutable current_out_col = 0
+		(** `current_out_col` value as it was when previous call to `map` was performed *)
+		val mutable last_out_col = 0
+		(** Indicates whether comma should be written to output buffer on next `map` call *)
+		val mutable print_comma = false
+		(** Last position passed to `map` *)
+		val mutable last_mapped_pos = None
+	(**
+		Map specified haxe position.
+		This method should be called right before an expression in `pos` is writtend to generated file.
+	*)
+	method map pos =
+		last_mapped_pos <- Some pos;
+		let src_file = self#get_file_index pos
+		and src_line, src_col = match (Lexer.find_pos pos) with (line, col) -> (line - 1, col) in
+		if print_comma then
+			Rbuffer.add_char buffer ','
+		else
+			print_comma <- true;
+		(*
+			We need to map the start of each line to the first expression on that line.
+			Otherwise languages, which don't provide column in stack trace, will point one line above the correct line.
+		*)
+		if last_out_col = 0 then
+			self#write_base64_vlq 0
+		else
+			self#write_base64_vlq (current_out_col - last_out_col);
+		self#write_base64_vlq (src_file - last_src_file);
+		self#write_base64_vlq (src_line - last_src_line);
+		self#write_base64_vlq (src_col - last_src_col);
+		last_src_file <- src_file;
+		last_src_line <- src_line;
+		last_src_col <- src_col;
+		last_out_col <- current_out_col
+	(**
+		Should be called every time something is written to `generated_file`
+	*)
+	method string_written str =
+		let length = String.length str in
+		let rec handle_next_new_line previous_index =
+			let next_index = try (String.index_from str (previous_index + 1) '\n') with Not_found -> -1 in
+			if next_index < 0 then
+				if previous_index >= 0 then
+					begin
+						print_comma <- false;
+						current_out_col <- length - previous_index;
+						last_out_col <- 0
+					end
+				else
+					current_out_col <- current_out_col + length
+			else begin
+				Rbuffer.add_char buffer ';';
+				handle_next_new_line next_index
+			end
+		in
+		handle_next_new_line (-1);
+		()
+	(**
+		Write generated map to disk.
+		If `file_name` is not provided then `generated_file` will be used with additional `.map` extension.
+		E.g if `generated_file` is `path/to/file.js`, then sourcemap will be written to `path/to/file.js.map`.
+		This function does not try to create missing directories.
+	*)
+	method generate ?file_name ?source_root com =
+		let file_name = match file_name with Some f -> f | None -> generated_file ^ ".map"
+		and source_root = match source_root with Some r -> r | None -> "" in
+		let channel = open_out file_name in
+		let sources = DynArray.to_list files in
+		let to_url file =
+			ExtString.String.map (fun c -> if c == '\\' then '/' else c) (Path.get_full_path file)
+		in
+		output_string channel "{\n";
+		output_string channel "\"version\":3,\n";
+		output_string channel ("\"file\":\"" ^ (String.concat "\\\\" (ExtString.String.nsplit generated_file "\\")) ^ "\",\n");
+		output_string channel ("\"sourceRoot\":\"" ^ source_root ^ "\",\n");
+		output_string channel ("\"sources\":[" ^
+			(String.concat "," (List.map (fun s -> "\"" ^ to_url s ^ "\"") sources)) ^
+			"],\n");
+		if Common.defined com Define.SourceMapContent then begin
+			output_string channel ("\"sourcesContent\":[" ^
+				(String.concat "," (List.map (fun s -> try "\"" ^ Ast.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^
+				"],\n");
+		end;
+		output_string channel "\"names\":[],\n";
+		output_string channel "\"mappings\":\"";
+		Rbuffer.output_buffer channel buffer;
+		output_string channel "\"\n";
+		output_string channel "}";
+		close_out channel
+	(**
+		Get source Haxe file position in a list of files referenced by this sourcemap
+	*)
+	method private get_file_index pos =
+		try
+			Hashtbl.find files_indexes pos.pfile
+		with Not_found ->
+			let index = (DynArray.length files) in
+			Hashtbl.add files_indexes pos.pfile index;
+			DynArray.add files pos.pfile;
+			index
+	(**
+		Apply base64 VLQ encoding to `number` and write it to output buffer
+	*)
+	method private write_base64_vlq number =
+		let rec loop vlq =
+			let shift = 5 in
+			let base = 1 lsl shift in
+			let mask = base - 1 in
+			let continuation_bit = base in
+			let digit = vlq land mask in
+			let next = vlq asr shift in
+			Rbuffer.add_char buffer (encode_digit (if next > 0 then digit lor continuation_bit else digit));
+			if next > 0 then loop next else ()
+		in
+		loop (to_vlq number)
+end
+
+type sm_node_data =
+	| SMPos of pos
+	| SMStr of string
+	| SMNil (* this data type marks the beginning and the end of a list *)
+
+type sm_node = {
+	mutable smn_left : sm_node option;
+	mutable smn_right : sm_node option;
+	smn_data : sm_node_data;
+}
+
+let init_sourcemap_node_list () : sm_node =
+	let first =
+		{
+			smn_left = None;
+			smn_right = None;
+			smn_data = SMNil;
+		}
+	in
+	let last =
+		{
+			smn_left = Some first;
+			smn_right = None;
+			smn_data = SMNil;
+		}
+	in
+	first.smn_right <- Some last;
+	first
+
+(**
+	Builds data for sourcemap.
+*)
+class sourcemap_builder (generated_file:string) =
+	object (self)
+	(** Current node *)
+	val mutable current = init_sourcemap_node_list()
+	(**
+		Add data to sourcemap.
+		1. `#insert (SMPos pos)` should be called right before an expression in `pos` is writtend to generated file.
+		2. `#insert (SMStr str)` should be called every time some string is written to generated file.
+	*)
+	method insert (data:sm_node_data) =
+		(* new node which will be inserted after current one *)
+		let inserted =
+			{
+				smn_left = Some current;
+				smn_right = current.smn_right;
+				smn_data = data;
+			}
+		in
+		(* link new node with current and next to current one *)
+		current.smn_right <- Some inserted;
+		(match inserted.smn_right with
+			| Some right -> right.smn_left <- current.smn_right
+			| None -> ()
+		);
+		(* inserted node becomes current *)
+		current <- inserted
+	(**
+		Rewind builder so that next `#insert data` call will insert data in the beginning of this sourcemap.
+	*)
+	method rewind =
+		let rec loop node =
+			match node with
+				| Some ({ smn_data = SMNil } as node) -> current <- node
+				| Some node -> loop node.smn_left
+				| None -> assert false
+		in
+		loop (Some current)
+	(**
+		Fast forward builder so that next `#insert data` call will attach data to the end of this sourcemap.
+	*)
+	method fast_forward =
+		let rec loop node =
+			match node.smn_right with
+				| Some { smn_data = SMNil } -> current <- node
+				| Some node -> loop node
+				| None -> assert false
+		in
+		loop current
+	(**
+		Set builder pointer to `node` so that next `#insert data` call will insert data right after this `node`.
+	*)
+	method seek (node:sm_node) = current <- node
+	(**
+		Get current node in this builder
+	*)
+	method get_pointer = current
+	(**
+		Write source map to disk.
+		If `file_name` is not provided then `generated_file` will be used with additional `.map` extension.
+		E.g if `generated_file` is `path/to/file.js`, then sourcemap will be written to `path/to/file.js.map`.
+		This function does not try to create missing directories.
+	*)
+	method generate ?file_name ?source_root com =
+		(* remember position *)
+		let pointer = self#get_pointer in
+		self#rewind;
+		(* write source map to a buffer *)
+		let writer = new sourcemap_writer generated_file in
+		let rec loop node =
+			(match node.smn_data with
+				| SMPos pos -> writer#map pos
+				| SMStr str -> writer#string_written str
+				| SMNil -> ()
+			);
+			(match node.smn_right with
+				| None -> ()
+				| Some node -> loop node
+			)
+		in
+		loop current;
+		(* dump source map to a file *)
+		let file_name = match file_name with Some f -> f | None -> generated_file ^ ".map"
+		and source_root = match source_root with Some r -> r | None -> "" in
+		writer#generate ~file_name:file_name ~source_root:source_root com;
+		(* restore position *)
+		self#seek pointer
+end
+
+let get_sourcemap_pointer (builder:sourcemap_builder option) =
+	match builder with
+		| Some builder -> Some builder#get_pointer
+		| None -> None
+
+let set_sourcemap_pointer (builder:sourcemap_builder option) (pointer:sm_node option) =
+	match builder with
+		| None -> ()
+		| Some builder ->
+			match pointer with
+				| Some node -> builder#seek node
+				| None -> ()

+ 13 - 1
src/typing/type.ml

@@ -57,12 +57,14 @@ type t =
 	| TEnum of tenum * tparams
 	| TInst of tclass * tparams
 	| TType of tdef * tparams
-	| TFun of (string * bool * t) list * t
+	| TFun of tsignature
 	| TAnon of tanon
 	| TDynamic of t
 	| TLazy of (unit -> t) ref
 	| TAbstract of tabstract * tparams
 
+and tsignature = (string * bool * t) list * t
+
 and tparams = t list
 
 and type_params = (string * t) list
@@ -1744,6 +1746,16 @@ let unify_stack = ref []
 let abstract_cast_stack = ref []
 let unify_new_monos = ref []
 
+let print_stacks() =
+	let ctx = print_context() in
+	let st = s_type ctx in
+	print_endline "unify_stack";
+	List.iter (fun (a,b) -> Printf.printf "\t%s , %s\n" (st a) (st b)) !unify_stack;
+	print_endline "monos";
+	List.iter (fun m -> print_endline ("\t" ^ st m)) !unify_new_monos;
+	print_endline "abstract_cast_stack";
+	List.iter (fun (a,b) -> Printf.printf "\t%s , %s\n" (st a) (st b)) !abstract_cast_stack
+
 let rec unify a b =
 	if a == b then
 		()

+ 14 - 3
src/typing/typeload.ml

@@ -573,7 +573,7 @@ and load_complex_type ctx allow_display p (t,pn) =
 				| _ ->
 					error "Can only extend structures" p
 			in
-			let il = List.map (fun (t,_) -> load_instance ctx ~allow_display (t,pn) false p) tl in
+			let il = List.map (fun (t,pn) -> load_instance ctx ~allow_display (t,pn) false p) tl in
 			let tr = ref None in
 			let t = TMono tr in
 			let r = exc_protect ctx (fun r ->
@@ -1562,7 +1562,18 @@ let type_function ctx args ret fmode f do_display p =
 	ctx.curfun <- fmode;
 	ctx.ret <- ret;
 	ctx.opened <- [];
-	let e = match f.f_expr with None -> error "Function body required" p | Some e -> e in
+	let e = match f.f_expr with
+		| None ->
+			if ctx.com.display.dms_error_policy = EPIgnore then
+				(* when we don't care because we're in display mode, just act like
+				   the function has an empty block body. this is fine even if function
+				   defines a return type, because returns aren't checked in this mode
+				*)
+				EBlock [],p
+			else
+				error "Function body required" p
+		| Some e -> e
+	in
 	let e = if not do_display then
 		type_expr ctx e NoValue
 	else begin
@@ -1573,7 +1584,7 @@ let type_function ctx args ret fmode f do_display p =
 		with
 		| Parser.TypePath (_,None,_) | Exit ->
 			type_expr ctx e NoValue
-		| Display.DisplayType (t,_,_) | Display.DisplaySignatures ([(t,_)],_) when (match follow t with TMono _ -> true | _ -> false) ->
+		| Display.DisplayType (t,_,_) when (match follow t with TMono _ -> true | _ -> false) ->
 			type_expr ctx (if ctx.com.display.dms_kind = DMToplevel then Display.ExprPreprocessing.find_enclosing ctx.com e else e) NoValue
 	end in
 	let e = match e.eexpr with

+ 13 - 14
src/typing/typer.ml

@@ -646,7 +646,7 @@ let unify_field_call ctx fa el args ret p inline =
 		| TFun(args,ret) ->
 			let el,tf = unify_call_args' ctx el args ret p inline is_forced_inline in
 			let mk_call ethis p_field =
-				let ef = mk (TField(ethis,mk_fa cf)) tf p_field in
+				let ef = mk (TField(ethis,mk_fa cf)) t p_field in
 				make_call ctx ef (List.map fst el) ret p
 			in
 			el,tf,mk_call
@@ -3655,9 +3655,9 @@ and handle_display ctx e_ast with_type =
 	let e = match e_ast,with_type with
 	| (EConst (Ident "$type"),_),_ ->
 		let mono = mk_mono() in
-		raise (Display.DisplaySignatures ([(TFun(["expression",false,mono],mono),Some "Outputs type of argument as a warning and uses argument as value")],0))
+		raise (Display.DisplaySignatures ([((["expression",false,mono],mono),Some "Outputs type of argument as a warning and uses argument as value")],0))
 	| (EConst (Ident "trace"),_),_ ->
-		raise (Display.DisplaySignatures ([(tfun [t_dynamic] ctx.com.basic.tvoid,Some "Print given arguments")],0))
+		raise (Display.DisplaySignatures ([((["value",false,t_dynamic],ctx.com.basic.tvoid),Some "Print given arguments")],0))
 	| (EConst (Ident "_"),p),WithType t ->
 		mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *)
 	| _ -> try
@@ -3717,7 +3717,8 @@ and handle_signature_display ctx e_ast with_type =
 	in
 	let rec follow_with_callable (t,doc) = match follow t with
 		| TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> follow_with_callable (Abstract.get_underlying_type a tl,doc)
-		| t -> (t,doc)
+		| TFun(args,ret) -> ((args,ret),doc)
+		| _ -> error ("Not a callable type: " ^ (s_type (print_context()) t)) p
 	in
 	let tl = List.map follow_with_callable tl in
 	let rec loop i p1 el = match el with
@@ -3732,16 +3733,14 @@ and handle_signature_display ctx e_ast with_type =
 	let el = if display_arg >= List.length el then el @ [EConst (Ident "null"),null_pos] else el in
 	let rec loop acc tl = match tl with
 		| (t,doc) :: tl ->
-			let keep t = match t with
-				| TFun (args,r) ->
-					begin try
-						let _ = unify_call_args' ctx el args r p false false in
-						true
-					with
-					| Error(Call_error (Not_enough_arguments _),_) -> true
-					| _ -> false
-					end
+			let keep (args,r) =
+				begin try
+					let _ = unify_call_args' ctx el args r p false false in
+					true
+				with
+				| Error(Call_error (Not_enough_arguments _),_) -> true
 				| _ -> false
+				end
 			in
 			loop (if keep t then (t,doc) :: acc else acc) tl
 		| [] ->
@@ -4268,7 +4267,7 @@ and build_call ctx acc el (with_type:with_type) p =
 				| _ ->
 					let el, tfunc = unify_call_args ctx el args r p false false in
 					let r = match tfunc with TFun(_,r) -> r | _ -> assert false in
-					mk (TCall ({e with etype = tfunc},el)) r p
+					mk (TCall (e,el)) r p
 			end
 		| TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta ->
 			loop (Abstract.get_underlying_type a tl)

+ 1 - 0
std/Any.hx

@@ -34,4 +34,5 @@
 abstract Any(Dynamic) {
 	@:noCompletion @:extern @:to inline function __promote<T>():T return this;
 	@:noCompletion @:extern @:from inline static function __cast<T>(value:T):Any return cast value;
+	@:noCompletion @:extern inline function toString():String return Std.string(this);
 }

+ 6 - 6
std/Array.hx

@@ -153,8 +153,8 @@ extern class Array<T> {
 
 		This operation modifies `this` Array in place.
 
-		If `len` is < 0 or `pos` exceeds `this`.length, the result is the empty
-		Array [].
+		If `len` is < 0 or `pos` exceeds `this`.length, an empty Array [] is 
+		returned and `this` Array is unchanged.
 
 		If `pos` is negative, its value is calculated from the end	of `this`
 		Array by `this.length + pos`. If this yields a negative value, 0 is
@@ -210,12 +210,12 @@ extern class Array<T> {
 	function insert( pos : Int, x : T ) : Void;
 
 	/**
-		Removes the first occurence of `x` in `this` Array.
+		Removes the first occurrence of `x` in `this` Array.
 
 		This operation modifies `this` Array in place.
 
 		If `x` is found by checking standard equality, it is removed from `this`
-		Array and all following elements are reindexed acoordingly. The function
+		Array and all following elements are reindexed accordingly. The function
 		then returns true.
 
 		If `x` is not found, `this` Array is not changed and the function
@@ -224,7 +224,7 @@ extern class Array<T> {
 	function remove( x : T ) : Bool;
 
 	/**
-		Returns position of the first occurense of `x` in `this` Array, searching front to back.
+		Returns position of the first occurrence of `x` in `this` Array, searching front to back.
 
 		If `x` is found by checking standard equality, the function returns its index.
 
@@ -239,7 +239,7 @@ extern class Array<T> {
 	function indexOf( x : T, ?fromIndex:Int ) : Int;
 
 	/**
-		Returns position of the last occurense of `x` in `this` Array, searching back to front.
+		Returns position of the last occurrence of `x` in `this` Array, searching back to front.
 
 		If `x` is found by checking standard equality, the function returns its index.
 

+ 1 - 1
std/List.hx

@@ -127,7 +127,7 @@ class List<T> {
 	}
 
 	/**
-		Removes the first occurence of `v` in `this` List.
+		Removes the first occurrence of `v` in `this` List.
 
 		If `v` is found by checking standard equality, it is removed from `this`
 		List and the function returns true.

+ 4 - 4
std/String.hx

@@ -78,7 +78,7 @@ extern class String {
 	function charCodeAt( index : Int) : Null<Int>;
 
 	/**
-		Returns the position of the leftmost occurence of `str` within `this`
+		Returns the position of the leftmost occurrence of `str` within `this`
 		String.
 
 		If `startIndex` is given, the search is performed within the substring
@@ -91,7 +91,7 @@ extern class String {
 	function indexOf( str : String, ?startIndex : Int ) : Int;
 
 	/**
-		Returns the position of the rightmost occurence of `str` within `this`
+		Returns the position of the rightmost occurrence of `str` within `this`
 		String.
 
 		If `startIndex` is given, the search is performed within the substring
@@ -104,7 +104,7 @@ extern class String {
 	function lastIndexOf( str : String, ?startIndex : Int ) : Int;
 
 	/**
-		Splits `this` String at each occurence of `delimiter`.
+		Splits `this` String at each occurrence of `delimiter`.
 
 		If `this` String is the empty String `""`, the result is not consistent
 		across targets and may either be `[]` (on Js, Cpp) or `[""]`.
@@ -118,7 +118,7 @@ extern class String {
 
 		If `delimiter` is null, the result is unspecified.
 
-		Otherwise, `this` String is split into parts at each occurence of
+		Otherwise, `this` String is split into parts at each occurrence of
 		`delimiter`. If `this` String starts (or ends) with `delimiter`, the
 		result `Array` contains a leading (or trailing) empty String `""` element.
 		Two subsequent delimiters also result in an empty String `""` element.

+ 1 - 1
std/StringTools.hx

@@ -361,7 +361,7 @@ class StringTools {
 	}
 
 	/**
-		Replace all occurences of the String `sub` in the String `s` by the
+		Replace all occurrences of the String `sub` in the String `s` by the
 		String `by`.
 
 		If `sub` is the empty String `""`, `by` is inserted after each character

+ 2 - 2
std/Sys.hx

@@ -36,7 +36,7 @@ extern class Sys {
 	static function println( v : Dynamic ) : Void;
 
 	/**
-		Returns all the arguments that were passed by the commandline.
+		Returns all the arguments that were passed by the command line.
 	**/
 	static function args() : Array<String>;
 
@@ -51,7 +51,7 @@ extern class Sys {
 	static function putEnv( s : String, v : String ) : Void;
 
 	/**
-		Returns the whole environement variables.
+		Returns the whole environment variables.
 	**/
 	static function environment() : Map<String,String>;
 

+ 1 - 1
std/Xml.hx

@@ -57,7 +57,7 @@
 }
 
 /**
-	Crossplatform Xml API.
+	Cross-platform Xml API.
 
 	@see https://haxe.org/manual/std-Xml.html
 **/

+ 2 - 2
std/cpp/Callable.hx

@@ -31,8 +31,8 @@ typedef CallableData<T> = T;
 abstract Callable<T>( CallableData<T> )
 {
    inline public function new(inValue:T) this = inValue;
-   public var call(get,never):T;
-   inline function get_call():T return this;
+   public var call(get,never):CallableData<T>;
+   inline function get_call():CallableData<T> return this;
 
    #if cpp
    @:from

+ 3 - 2
std/cpp/Function.hx

@@ -21,6 +21,7 @@
  */
 package cpp;
 
+@:callable
 typedef FunctionData<T,ABI> = T;
 
 
@@ -30,8 +31,8 @@ extern abstract Function<T, ABI:cpp.abi.Abi>( FunctionData<T,ABI> )
    inline public function new(inValue:T) this = inValue;
 
    // Legacy Api
-   public var call(get,never):T;
-   inline function get_call():T return this;
+   public var call(get,never):FunctionData<T,ABI>;
+   inline function get_call():FunctionData<T,ABI> return this;
 
 
    @:native("::cpp::Function_obj::getProcAddress")

+ 37 - 0
std/cpp/NativeGc.hx

@@ -18,5 +18,42 @@ extern class NativeGc
    {
       return Pointer.fromRaw( allocGcBytesRaw(inBytes, false) );
    }
+
+
+   @:native("__hxcpp_enable") @:extern
+   static public function enable(inEnable:Bool) : Void { }
+
+   @:native("__hxcpp_collect") @:extern
+   static public function run(major:Bool) : Void { }
+
+   @:native("__hxcpp_gc_compact") @:extern
+   static public function compact() : Void { }
+
+   @:native("__hxcpp_gc_trace") @:extern
+   static public function nativeTrace(sought:Class<Dynamic>,printInstances:Bool) : Int return 0;
+
+   @:native("__hxcpp_gc_do_not_kill") @:extern
+   static public function doNotKill(inObject:Dynamic) : Void { }
+
+   @:native("__hxcpp_get_next_zombie") @:extern
+   static public function getNextZombie() : Dynamic return null;
+
+   @:native("__hxcpp_gc_safe_point") @:extern
+   static public function safePoint() : Void { }
+
+   @:native("__hxcpp_enter_gc_free_zone") @:extern
+   static public function enterGCFreeZone() : Void { }
+
+   @:native("__hxcpp_exit_gc_free_zone") @:extern
+   static public function exitGCFreeZone() : Void { }
+
+   @:native("__hxcpp_set_minimum_free_space") @:extern
+   static public function setMinimumFreeSpace(inBytes:Int) : Void { }
+
+   @:native("__hxcpp_set_target_free_space_percentage") @:extern
+   static public function setTargetFreeSpacePercentage(inPercentage:Int) : Void { }
+
+   @:native("__hxcpp_set_minimum_working_memory") @:extern
+   static public function setMinimumWorkingMemory(inBytes:Int) : Void { }
 }
 

+ 3 - 5
std/cpp/_std/StringBuf.hx

@@ -78,13 +78,11 @@ class StringBuf {
 
    public function toString() : String {
       if (charBuf!=null)
-      {
-         if (b==null)
-           return( charBufAsString() );
          flush();
-      }
-      if (b==null)
+      if (b==null || b.length==0)
          return "";
+      if (b.length==1)
+         return b[0];
       return b.join("");
    }
 

+ 2 - 2
std/cpp/_std/sys/net/Socket.hx

@@ -153,7 +153,7 @@ class Socket {
 
    public function connect(host : Host, port : Int) : Void {
       try {
-         if (host.ip==0) {
+         if (host.ip==0 && host.host!="0.0.0.0") {
             // hack, hack, hack
             var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6");
             if (ipv6!=null)
@@ -189,7 +189,7 @@ class Socket {
    }
 
    public function bind(host : Host, port : Int) : Void {
-      if (host.ip==0)
+      if (host.ip==0  && host.host!="0.0.0.0")
       {
           var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6");
           if (ipv6!=null)

+ 1 - 0
std/cpp/cppia/HostClasses.hx

@@ -55,6 +55,7 @@ class HostClasses
    "cpp.vm.WeakRef",
    "cpp.Object",
    "cpp.Int64",
+   "cpp.Finalizable",
    "Std",
    "StringBuf",
    "sys.db.Mysql",

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

@@ -136,7 +136,7 @@ class Debugger
      *        thread events.  Note that this function is called directly from
      *        the thread experiencing the event and the handler should return
      *        quickly to avoid blocking the calling thread unnecessarily.
-     *        The paramaters to handler are:
+     *        The parameters to handler are:
      *          - threadNumber, the thread number of the event
      *          - event, one of THREAD_CREATED, THREAD_TERMINATED,
      *            THREAD_STARTED, or THREAD_STOPPED

+ 35 - 46
std/cpp/vm/Gc.hx

@@ -28,20 +28,6 @@ class Gc
    public static inline var MEM_INFO_CURRENT = 2;
    public static inline var MEM_INFO_LARGE = 3;
 
-   static public function enable(inEnable:Bool) : Void
-   {
-      untyped __global__.__hxcpp_enable(inEnable);
-   }
-
-   static public function run(major:Bool) : Void
-   {
-      untyped __global__.__hxcpp_collect(major);
-   }
-
-   static public function compact() : Void
-   {
-      untyped __global__.__hxcpp_gc_compact();
-   }
 
    // Introduced hxcpp_api_level 310
    // Returns stats on memory usage:
@@ -61,63 +47,66 @@ class Gc
       return NativeGc.memInfo(inWhatInfo);
    }
 
-
    static public function memUsage() : Int
    {
       return Std.int(NativeGc.memInfo(MEM_INFO_USAGE));
    }
 
+   static public function versionCheck() { return true; }
+
    static public function trace(sought:Class<Dynamic>,printInstances:Bool=true) : Int
    {
-      return untyped __global__.__hxcpp_gc_trace(sought,printInstances);
+      return cpp.NativeGc.nativeTrace(sought,printInstances);
    }
 
-   static public function versionCheck() { return true; }
 
+   #if !cppia inline #end
+   static public function enable(inEnable:Bool) : Void
+      cpp.NativeGc.enable(inEnable);
+
+   #if !cppia inline #end
+   static public function run(major:Bool) : Void
+      cpp.NativeGc.run(major);
+
+   #if !cppia inline #end
+   static public function compact() : Void
+      cpp.NativeGc.compact();
+
+   #if !cppia inline #end
    static public function doNotKill(inObject:Dynamic) : Void
-   {
-      untyped __global__.__hxcpp_gc_do_not_kill(inObject);
-   }
+      cpp.NativeGc.doNotKill(inObject);
 
+   #if !cppia inline #end
    static public function getNextZombie() : Dynamic
-   {
-      return untyped __global__.__hxcpp_get_next_zombie();
-   }
+      return cpp.NativeGc.getNextZombie();
 
+   #if !cppia inline #end
    static public function safePoint() : Void
-   {
-      untyped __global__.__hxcpp_gc_safe_point();
-   }
+      cpp.NativeGc.safePoint();
 
+   #if !cppia inline #end
    static public function enterGCFreeZone() : Void
-   {
-      untyped __global__.__hxcpp_enter_gc_free_zone();
-   }
+      cpp.NativeGc.enterGCFreeZone();
 
+   #if !cppia inline #end
    static public function exitGCFreeZone() : Void
-   {
-      untyped __global__.__hxcpp_exit_gc_free_zone();
-   }
+      cpp.NativeGc.exitGCFreeZone();
 
+   #if !cppia inline #end
    static public function setMinimumFreeSpace(inBytes:Int) : Void
-   {
-      untyped __global__.__hxcpp_set_minimum_free_space(inBytes);
-   }
+      cpp.NativeGc.setMinimumFreeSpace(inBytes);
 
+   #if !cppia inline #end
    static public function setTargetFreeSpacePercentage(inPercentage:Int) : Void
-   {
-      untyped __global__.__hxcpp_set_target_free_space_percentage(inPercentage);
-   }
+      cpp.NativeGc.setTargetFreeSpacePercentage(inPercentage);
 
+   #if !cppia inline #end
    static public function setMinimumWorkingMemory(inBytes:Int) : Void
-   {
-      untyped __global__.__hxcpp_set_minimum_working_memory(inBytes);
-   }
+      cpp.NativeGc.setMinimumWorkingMemory(inBytes);
 
-   @:unreflective
-   inline static public function setFinalizer<T>(inObject:T, inFinalizer:cpp.Callable<T->Void> ) : Void
-   {
-      untyped __global__.__hxcpp_set_finalizer(inObject, inFinalizer);
-   }
+   #if !cppia
+   @:native("__hxcpp_set_finalizer") @:extern
+   static public function setFinalizer<T>(inObject:T, inFinalizer:cpp.Callable<T->Void> ) : Void { }
+   #end
 }
 

+ 6 - 6
std/cs/_std/sys/net/Socket.hx

@@ -54,7 +54,7 @@ class Socket {
 	public var output(default,null) : haxe.io.Output;
 
 	/**
-		A custom value that can be associated with the socket. Can be used to retreive your custom infos after a `select`.
+		A custom value that can be associated with the socket. Can be used to retrieve your custom infos after a `select`.
 	***/
 	public var custom : Dynamic;
 
@@ -90,7 +90,7 @@ class Socket {
 	}
 
 	/**
-		Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
+		Connect to the given server host/port. Throw an exception in case we couldn't successfully connect.
 	**/
 	public function connect( host : Host, port : Int ) : Void {
 		sock.Connect( host.ipAddress, port );
@@ -146,7 +146,7 @@ class Socket {
 	}
 
 	/**
-		Return the informations about the other side of a connected socket.
+		Return the information about the other side of a connected socket.
 	**/
 	public function peer() : { host : Host, port : Int } {
 		var remoteIP = cast(sock.RemoteEndPoint, IPEndPoint);
@@ -154,7 +154,7 @@ class Socket {
 	}
 
 	/**
-		Return the informations about our side of a connected socket.
+		Return the information about our side of a connected socket.
 	**/
 	public function host() : { host : Host, port : Int } {
 		var localIP = cast(sock.LocalEndPoint, IPEndPoint);
@@ -179,14 +179,14 @@ class Socket {
 	}
 
 	/**
-		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
+		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocking value.
 	**/
 	public function setBlocking( b : Bool ) : Void {
 		sock.Blocking = b;
 	}
 
 	/**
-		Allows the socket to immediatly send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
+		Allows the socket to immediately send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
 	**/
 	public function setFastSend( b : Bool ) : Void {
 		sock.NoDelay = b;

+ 1 - 1
std/cs/types/Char16.hx

@@ -19,6 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef Char16 = cs.StdTypes.Char16;

+ 1 - 1
std/cs/types/Int16.hx

@@ -19,6 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef Int16 = cs.StdTypes.Int16;

+ 1 - 1
std/cs/types/Int64.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef Int64 = cs.StdTypes.Int64;
 

+ 1 - 1
std/cs/types/Int8.hx

@@ -19,6 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef Int8 = cs.StdTypes.Int8;

+ 1 - 1
std/cs/types/UInt16.hx

@@ -19,6 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef UInt16 = cs.StdTypes.UInt16;

+ 1 - 1
std/cs/types/UInt64.hx

@@ -19,6 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef UInt64 = cs.StdTypes.UInt64;

+ 1 - 1
std/cs/types/UInt8.hx

@@ -19,6 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
- package cs.types;
+package cs.types;
 
 typedef UInt8 = cs.StdTypes.UInt8;

+ 1 - 1
std/haxe/CallStack.hx

@@ -33,7 +33,7 @@ enum StackItem {
 }
 
 /**
-	Get informations about the call stack.
+	Get information about the call stack.
 **/
 class CallStack {
 	#if js

+ 1 - 1
std/haxe/Json.hx

@@ -22,7 +22,7 @@
 package haxe;
 
 /**
-	Crossplatform JSON API: it will automatically use the optimized native API if available.
+	Cross-platform JSON API: it will automatically use the optimized native API if available.
 	Use `-D haxeJSON` to force usage of the Haxe implementation even if a native API is found:
 	This will provide extra encoding features such as enums (replaced by their index) and StringMaps.
 

+ 4 - 4
std/haxe/Ucs2.hx

@@ -83,7 +83,7 @@ abstract Ucs2(String) {
 	}
 
 	/**
-		Returns the position of the leftmost occurence of `str` within `this`
+		Returns the position of the leftmost occurrence of `str` within `this`
 		Ucs2.
 
 		If `startIndex` is given, the search is performed within the substring
@@ -98,7 +98,7 @@ abstract Ucs2(String) {
 	}
 
 	/**
-		Returns the position of the rightmost occurence of `str` within `this`
+		Returns the position of the rightmost occurrence of `str` within `this`
 		Ucs2.
 
 		If `startIndex` is given, the search is performed within the substring
@@ -113,7 +113,7 @@ abstract Ucs2(String) {
 	}
 
 	/**
-		Splits `this` Ucs2 at each occurence of `delimiter`.
+		Splits `this` Ucs2 at each occurrence of `delimiter`.
 
 		If `this` Ucs2 is the empty Ucs2 "", the result is not consistent
 		across targets and may either be `[]` (on Js, Cpp) or `[""]`.
@@ -127,7 +127,7 @@ abstract Ucs2(String) {
 
 		If `delimiter` is null, the result is unspecified.
 
-		Otherwise, `this` Ucs2 is split into parts at each occurence of
+		Otherwise, `this` Ucs2 is split into parts at each occurrence of
 		`delimiter`. If `this` Ucs2 starts (or ends) with `delimiter`, the
 		result Array contains a leading (or trailing) empty Ucs2 "" element.
 		Two subsequent delimiters also result in an empty Ucs2 "" element.

+ 1 - 1
std/haxe/Utf8.hx

@@ -23,7 +23,7 @@ package haxe;
 
 /**
 	Since not all platforms guarantee that `String` always uses UTF-8 encoding, you
-	can use this crossplatform API to perform operations on such strings.
+	can use this cross-platform API to perform operations on such strings.
 **/
 class Utf8 {
 

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

@@ -27,8 +27,6 @@ package haxe.io;
 	typedef BytesData =	flash.utils.ByteArray;
 #elseif php
 	typedef BytesData = php.BytesData;
-#elseif php
-	typedef BytesData = php.NativeString;
 #elseif cpp
 	typedef BytesData = Array< cpp.UInt8 >;
 #elseif java

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

@@ -475,7 +475,7 @@ class Context {
 		Defines a new module as `modulePath` with several `TypeDefinition`
 		`types`. This is analogous to defining a .hx file.
 
-		The individial `types` can reference each other and any identifier
+		The individual `types` can reference each other and any identifier
 		respects the `imports` and `usings` as usual, expect that imports are
 		not allowed to have `.*` wildcards or `in s` shorthands.
 	**/
@@ -554,7 +554,7 @@ class Context {
 	}
 
 	/**
-		Register a macro call to be performed everytime the module `modulePath` is reused by the compilation cache,
+		Register a macro call to be performed every time the module `modulePath` is reused by the compilation cache,
 		meaning that neither the module itself nor its dependencies was changed since last compilation.
 
 		The `macroCall` should be a String containing valid Haxe expression, similar to `--init` macros (see https://haxe.org/manual/macro-initialization.html).
@@ -571,7 +571,7 @@ class Context {
 	}
 
 	/**
-		Register a callback function that will be called everytime the macro context cached is reused with a new
+		Register a callback function that will be called every time the macro context cached is reused with a new
 		compilation. This enable to reset some static vars since the code might have been changed. If the callback
 		returns false, the macro context is discarded and another one is created.
 	**/

+ 2 - 2
std/haxe/macro/Expr.hx

@@ -67,7 +67,7 @@ enum Constant {
 	CString( s : String );
 
 	/**
-		Represents an indentifier.
+		Represents an identifier.
 	**/
 	CIdent( s : String );
 
@@ -819,7 +819,7 @@ typedef TypeDefinition = {
 	@:optional var meta : Metadata;
 
 	/**
-		The paramater type declarations of the type definition.
+		The parameter type declarations of the type definition.
 	**/
 	@:optional var params : Array<TypeParamDecl>;
 

+ 1 - 1
std/haxe/macro/TypeTools.hx

@@ -230,7 +230,7 @@ class TypeTools {
 		Applies the type parameters `typeParameters` to type `t` with the given
 		types `concreteTypes`.
 
-		This function replaces occurences of type parameters in `t` if they are
+		This function replaces occurrences of type parameters in `t` if they are
 		part of `typeParameters`. The array index of such a type parameter is
 		then used to lookup the concrete type in `concreteTypes`.
 

+ 1 - 1
std/haxe/remoting/ExternalConnection.hx

@@ -61,7 +61,7 @@ class ExternalConnection implements Connection implements Dynamic<Connection> {
 		var params = escapeString(s.toString());
 		var data = null;
 		#if flash
-			#if js-unflatten
+			#if js_unflatten
 				data = flash.external.ExternalInterface.call("haxe.remoting.ExternalConnection.doCall",__data.name,__path.join("."),params);
 			#else
 				data = flash.external.ExternalInterface.call("haxe_remoting_ExternalConnection.doCall",__data.name,__path.join("."),params);

+ 1 - 1
std/haxe/remoting/SocketProtocol.hx

@@ -48,7 +48,7 @@ typedef Socket =
 	 - the boolean false for a response
 	 - a serialized value representing the result
 
-	Exceptions are serialized with `serializeException` so they will be thrown immediatly
+	Exceptions are serialized with `serializeException` so they will be thrown immediately
 	when they are unserialized.
 **/
 class SocketProtocol {

+ 3 - 3
std/haxe/xml/Parser.hx

@@ -54,17 +54,17 @@ class XmlParserException
 	public var message:String;
 
 	/**
-	 * the line number at which the XML parsing error occured
+	 * the line number at which the XML parsing error occurred
 	 */
 	public var lineNumber:Int;
 
 	/**
-	 * the character position in the reported line at which the parsing error occured
+	 * the character position in the reported line at which the parsing error occurred
 	 */
 	public var positionAtLine:Int;
 
 	/**
-	 * the character position in the XML string at which the parsing error occured
+	 * the character position in the XML string at which the parsing error occurred
 	 */
 	public var position:Int;
 

+ 55 - 1
std/hl/Gc.hx

@@ -21,8 +21,24 @@
  */
 package hl;
 
+enum GcFlag {
+	/**
+		Activate profiling: regularly print on stdout gc allocation stats
+	**/
+	Profile;
+	/**
+		Allows to dump a hlmemory.dump file when HL runs out of memory to be examined with hl memory inspector tool.
+	**/
+	DumpMem;
+	/**
+		Enable block tracking (see Gc.track API)
+	**/
+	Track;
+}
+
 class Gc {
 
+	public static var flags(get,set) : haxe.EnumFlags<GcFlag>;
 
 	public static function stats() {
 		var tot = 0., count = 0., mem = 0.;
@@ -30,6 +46,31 @@ class Gc {
 		return { totalAllocated : tot, allocationCount : count, currentMemory : mem };
 	}
 
+	/**
+		Start tracking an object field change.
+		The check will be performed every allocation and the callback function triggered everytime
+		a change has been performed since last check. The callback parameter is true if the object was collected.
+		It is necessary to enable the Track flag in Gc.flags
+	**/
+	public static function track( obj : Dynamic, field : String, callb : Dynamic -> Bytes -> Void ) {
+		var oval = if( Reflect.isFunction(obj) ) Api.getClosureValue(obj) else obj;
+		var fid = if( ~/^[0-9]+$/.match(field) ) Std.parseInt(field) else @:privateAccess field.bytes.hash();
+		if( !_track(oval, fid, callb) )
+			throw "Could not track "+obj+"."+field;
+	}
+
+	public static function untrack( obj : Dynamic ) {
+		var oval = if( Reflect.isFunction(obj) ) Api.getClosureValue(obj) else obj;
+		return _untrack(oval);
+	}
+
+	@:hlNative("std", "gc_untrack_all") public static function untrackAll() : Void {
+	}
+
+	@:hlNative("std", "gc_track_count") public static function trackCount() : Int {
+		return 0;
+	}
+
 	/**
 		Dump whole memory into target filename for analysis.
 	**/
@@ -37,11 +78,24 @@ class Gc {
 		_dump(@:privateAccess fileName.toUtf8());
 	}
 
+	static function get_flags() : haxe.EnumFlags<GcFlag> {
+		return haxe.EnumFlags.ofInt(_get_flags());
+	}
+
+	static function set_flags(v : haxe.EnumFlags<GcFlag>) {
+		_set_flags(v.toInt());
+		return v;
+	}
+
 	@:hlNative("std", "gc_dump_memory") static function _dump( b : hl.Bytes ) : Void {}
 
-	@:hlNative("std", "gc_profile") public static function activeProfileInfos( b : Bool ) : Void {}
 	@:hlNative("std", "gc_enable") public static function enable( b : Bool ) : Void {}
 	@:hlNative("std", "gc_major") public static function major() : Void {}
 	@:hlNative("std", "gc_stats") static function _stats( totalAllocated : hl.Ref<Float>, allocationCount : hl.Ref<Float>, currentMemory : hl.Ref<Float> ) : Void {}
+	@:hlNative("std", "gc_track") static function _track( obj : Dynamic, fid : Int, callb : Dynamic -> Bytes -> Void ) : Bool { return false; }
+	@:hlNative("std", "gc_untrack") static function _untrack( obj : Dynamic ) : Bool { return false; }
+
+	@:hlNative("std", "gc_get_flags") static function _get_flags() : Int { return 0; }
+	@:hlNative("std", "gc_set_flags") static function _set_flags( v : Int ) {}
 
 }

+ 1 - 0
std/hl/_std/sys/io/FileInput.hx

@@ -46,6 +46,7 @@ import sys.io.File;
 	public override function close() : Void {
 		super.close();
 		file_close(__f);
+		__f = null;
 	}
 
 	public function seek( p : Int, pos : FileSeek ) : Void {

+ 1 - 0
std/hl/_std/sys/io/FileOutput.hx

@@ -48,6 +48,7 @@ import sys.io.File;
 	public override function close() : Void {
 		super.close();
 		@:privateAccess FileInput.file_close(__f);
+		__f = null;
 	}
 
 	public function seek( p : Int, pos : FileSeek ) : Void {

+ 2 - 2
std/js/_std/Reflect.hx

@@ -34,12 +34,12 @@
 		o[field] = value;
 	}
 
-	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic untyped {
+	public static function getProperty( o : Dynamic, field : String ) : Dynamic untyped {
 		var tmp;
 		return if( o == null ) __define_feature__("Reflect.getProperty",null) else if( o.__properties__ && (tmp=o.__properties__["get_"+field]) ) o[tmp]() else o[field];
 	}
 
-	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
+	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
 		var tmp;
 		if( o.__properties__ && (tmp=o.__properties__["set_"+field]) ) o[tmp](value) else o[field] = __define_feature__("Reflect.setProperty",value);
 	}

+ 1 - 1
std/js/html/SpeechSynthesisEvent.hx

@@ -51,7 +51,7 @@ extern class SpeechSynthesisEvent extends Event
 	var elapsedTime(default,null) : Float;
 	
 	/**
-		Returns the name associated with certain types of events occuring as the `SpeechSynthesisUtterance.text` is being spoken: the name of the SSML marker reached in the case of a `mark` event, or the type of boundary reached in the case of a `boundary` event.
+		Returns the name associated with certain types of events occurring as the `SpeechSynthesisUtterance.text` is being spoken: the name of the SSML marker reached in the case of a `mark` event, or the type of boundary reached in the case of a `boundary` event.
 	**/
 	var name(default,null) : String;
 	

+ 1 - 1
std/lua/Coroutine.hx

@@ -64,7 +64,7 @@ extern class Coroutine<T:Function> extends Thread {
 		The coroutine cannot be running a C function, a metamethod, or an iterator.
 		Any arguments to `yield` are passed as extra results to `resume`.
 	**/
-	public static function yield(args : Rest<Dynamic>) : Dynamic;
+	public static function yield<T>(args : Rest<T>) : T;
 
 	/**
 		Creates a new coroutine, with body `f`.

+ 12 - 10
std/lua/Ffi.hx

@@ -22,27 +22,29 @@
 
 package lua;
 
+import haxe.Constraints.Function;
+import lua.Table;
 #if lua_jit
-@:native("_G.ffi")
+@:luaRequire("ffi")
 extern class Ffi {
 
 	// Declaring and accessing external symbols
 	public static var C : Dynamic;
 	public static function gc(cdata : Dynamic, finalizer : Function) : Void;
-	public static function load : (name : String, ?global : Bool) : Dynamic;
-	public static function metatype<T>(ct : Ctype<T>, metatable : Table<Dynamic>) : Ctype<T>;
+	public static function load (name : String, ?global : Bool) : Dynamic;
+	public static function metatype<T>(ct : Ctype<T>, metatable : Table<Dynamic,Dynamic>) : Ctype<T>;
 	public static function typeof(str:String) : Ctype<Dynamic>;
 
-	// C Type functionality 
-	public static function alignof(ct : Ctype<T>) : Int;
-	public static function istype(ct : Ctype<T>, obj:Dynamic) : Bool;
-	public static function offsetof(ct : Ctype<T>, field:String) : Int;
-	public static function sizeof(ct : Ctype<T>, ?nelem : Int) : Int;
+	// C Type functionality
+	public static function alignof<T>(ct : Ctype<T>) : Int;
+	public static function istype<T>(ct : Ctype<T>, obj:Dynamic) : Bool;
+	public static function offsetof<T>(ct : Ctype<T>, field:String) : Int;
+	public static function sizeof<T>(ct : Ctype<T>, ?nelem : Int) : Int;
 
 
 	// Utility functionality
 	public static function errno(?newerr : Int) : Int;
-	public static function fill(dst : Dynamic, len : Int, c:Int) : Void; 
+	public static function fill(dst : Dynamic, len : Int, c:Int) : Void;
 	public static function string(ptr : Dynamic, ?len : Int) : String;
 
 	@:overload(   function     (dst : Dynamic, str : String)             : Dynamic {})
@@ -51,7 +53,7 @@ extern class Ffi {
 	// Target specific functionality
 	public static var os : String;
 	public static var arch : String;
-	public static function abi(param : String) : Bool; 
+	public static function abi(param : String) : Bool;
 }
 
 extern class Ctype<T> {}

+ 1 - 1
std/lua/HaxeIterator.hx

@@ -23,7 +23,7 @@
 package lua;
 
 /**
-  An implementation of the Haxe iterator datastructure needed for identical 
+  An implementation of the Haxe iterator data structure needed for identical 
   lua iterator behavior. 
  **/
 class HaxeIterator<T> {

+ 167 - 37
std/lua/Math.hx

@@ -1,43 +1,173 @@
 package lua;
 
+import haxe.extern.Rest;
+
+/**
+	Mathematical Functions
+**/
 @:native("_G.math")
 extern class Math {
-	public static var pi   : Float;
-	public static var huge : Float;
-	public static var NaN  : Float;
-
-	public static function abs  (i : Float) : Float;
-	public static function ceil (i : Float) : Int;
-	public static function floor(i : Float) : Int;
-
-	public static function acos (i : Float) : Float;
-	public static function asin (i : Float) : Float;
-	public static function atan (i : Float) : Float;
-	public static function atan2(i : Float, j : Float) : Float;
-	public static function cos  (i : Float) : Float;
-	public static function cosh (i : Float) : Float;
-	public static function sin  (i : Float) : Float;
-	public static function sinh (i : Float) : Float;
-	public static function tan  (i : Float) : Float;
-	public static function tanh (i : Float) : Float;
-	public static function rad  (i : Float) : Float;
-
-	public static function modf (i : Float) : Float;
-	public static function fmod (i : Float) : Float;
-
-	public static function pow  (i : Float, j : Float) : Float;
-	public static function sqrt (i : Float) : Float;
-	public static function exp  (i : Float) : Float;
-	public static function frexp(i : Float) : Float;
-	public static function ldexp(i : Float) : Float;
-
-	public static function log  (i : Float) : Float;
-	public static function log10(i : Float) : Float;
-
-	public static function max  (i : Float, j :Float) : Float;
-	public static function min  (i : Float, j :Float) : Float;
-
-	public static function random() : Float;
-	public static function randomseed(i : Float) : Float;
+	/**
+		The value of pi.
+	**/
+	static var pi(default,never) : Float;
+
+	/**
+		The value HUGE_VAL, a value larger than or equal to any other numerical value.
+	**/
+	static var huge(default,never) : Float;
+
+	/**
+		Returns the absolute value of x.
+	**/
+	static function abs  (x : Float) : Float;
+
+	/**
+		Returns the smallest integer larger than or equal to x.
+	**/
+	static function ceil (x : Float) : Int;
+
+	/**
+		Returns the largest integer smaller than or equal to x.
+	**/
+	static function floor(x : Float) : Int;
+
+	/**
+		Returns the arc cosine of x (in radians).
+	**/
+	static function acos (x : Float) : Float;
+
+	/**
+		Returns the arc sine of x (in radians).
+	**/
+	static function asin (x : Float) : Float;
+
+	/**
+		Returns the arc tangent of x (in radians).
+	**/
+	static function atan (x : Float) : Float;
+
+	/**
+		Returns the arc tangent of y/x (in radians), but uses the signs of both parameters to find the quadrant of the result.
+		(It also handles correctly the case of x being zero.)
+	**/
+	static function atan2(y : Float, x : Float) : Float;
+
+	/**
+		Returns the cosine of x (assumed to be in radians).
+	**/
+	static function cos  (x : Float) : Float;
+
+	/**
+		Returns the hyperbolic cosine of x.
+	**/
+	static function cosh (x : Float) : Float;
+
+	/**
+		Returns the sine of x (assumed to be in radians).
+	**/
+	static function sin  (x : Float) : Float;
+
+	/**
+		Returns the hyperbolic sine of x.
+	**/
+	static function sinh (x : Float) : Float;
+
+	/**
+		Returns the tangent of x (assumed to be in radians)
+	**/
+	static function tan  (x : Float) : Float;
+
+	/**
+		Returns the hyperbolic tangent of x.
+	**/
+	static function tanh (x : Float) : Float;
+
+	/**
+		Returns the angle x (given in degrees) in radians.
+	**/
+	static function rad  (x : Float) : Float;
+
+	/**
+		Returns two numbers, the integral part of x and the fractional part of x.
+	**/
+	static function modf (x : Float) : Float;
+
+	/**
+		Returns the remainder of the division of x by y that rounds the quotient towards zero.
+	**/
+	static function fmod (x : Float) : Float;
+
+	/**
+		Returns y-th power of x.
+	**/
+	static function pow  (x : Float, y : Float) : Float;
+
+	/**
+		Returns the square root of x.
+	**/
+	static function sqrt (x : Float) : Float;
+
+	/**
+		Returns the value e^x.
+	**/
+	static function exp  (x : Float) : Float;
+
+	/**
+		Returns m and e such that x = m2^e, e is an integer and the absolute value of m is in the range [0.5, 1) (or zero when x is zero).
+	**/
+	static function frexp(x : Float) : MathFrexpResult;
+
+	/**
+		Returns m2^e (e should be an integer).
+	**/
+	static function ldexp(m : Float, e : Int) : Float;
+
+	/**
+		Returns the natural logarithm of x.
+	**/
+	static function log  (x : Float) : Float;
+
+	/**
+		Returns the base-10 logarithm of x.
+	**/
+	static function log10(x : Float) : Float;
+
+	/**
+		Returns the maximum value among its arguments.
+	**/
+	static function max  (x : Float, numbers : Rest<Float>) : Float;
+
+	/**
+		Returns the minimum value among its arguments.
+	**/
+	static function min  (x : Float, numbers : Rest<Float>) : Float;
+
+	/**
+		Returns the angle x (given in radians) in degrees.
+	**/
+	static function deg  (x : Float) : Float;
+
+	/**
+		This function is an interface to the simple pseudo-random generator function rand provided by ANSI C.
+		(No guarantees can be given for its statistical properties.)
+
+		When called without arguments, returns a uniform pseudo-random real number in the range [0,1).
+		When called with an integer number `m`, returns a uniform pseudo-random integer in the range [1, m].
+		When called with two integer numbers `m` and `n`, returns a uniform pseudo-random integer in the range [m, n].
+	**/
+	static function random(?m:Float, ?n:Float) : Float;
+
+	/**
+		Sets `x` as the "seed" for the pseudo-random generator: equal seeds produce equal sequences of numbers.
+	**/
+	static function randomseed(x : Float) : Float;
 }
 
+/**
+	The return value of `Math.frexp`.
+**/
+@:multiReturn extern class MathFrexpResult {
+	var m:Float;
+	var e:Int;
+}

+ 3 - 1
std/lua/Table.hx

@@ -6,7 +6,9 @@ package lua;
 // TODO: use an abstract here?
 @:native("_G.table")
 extern class Table<A,B> implements ArrayAccess<B> implements Dynamic<B> {
-	public inline static function create<A,B>(?arr:Array<B>, ?hsh:Dynamic<B>) : Table<A,B> {
+
+	@:analyzer(no_fusion)
+	public inline static function create<A,B>(?arr:Array<B>, ?hsh:Dynamic) : Table<A,B> {
 		return untyped __lua_table__(arr,hsh);
 	}
 

+ 1 - 1
std/lua/_std/EReg.hx

@@ -121,7 +121,7 @@ class EReg {
 	}
 
 	public function replace( s : String, by : String ) : String {
-		by = Rex.gsub(by, "\\$(\\d)", "%%1"); // convert dollar sign matched groups to Rex equivalent
+		by = Rex.gsub(by, "\\$(\\d)", "%%%1"); // convert dollar sign matched groups to Rex equivalent
 		by = Rex.gsub(by, "\\${2}", "$"); // escape double dollar signs
 		return Rex.gsub(s,r,by, global ? null : 1);
 	}

+ 2 - 2
std/lua/_std/Reflect.hx

@@ -61,12 +61,12 @@ import lua.Boot;
 		}
 	}
 
-	public inline static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic  {
+	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic  {
 		if (args == null || args.length == 0){
 			return func(o);
 		} else {
 			var self_arg = false;
-			if (o != null && Type.getClass(o) != null){
+			if (o != null ){
 				// if o is not null, it means we need to pass it as the "self"
 				// parameter.  However, we should also check to see if it's
 				// a valid class instance in the first place.

+ 2 - 1
std/lua/_std/Std.hx

@@ -39,7 +39,8 @@ import lua.NativeStringTools;
 	}
 
 	public static function int( x : Float ) : Int {
-		return lua.Boot.clamp(x);
+		if (!Math.isFinite(x) || Math.isNaN(x)) return 0;
+		else return lua.Boot.clamp(x);
 	}
 
 	public static function parseInt( x : String ) : Null<Int> {

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

@@ -192,7 +192,7 @@ enum ValueType {
 	}
 
 	public inline static function enumParameters( e : EnumValue ) : Array<Dynamic> {
-		return untyped e.slice(2);
+		return (cast e : Array<Dynamic>).slice(2);
 	}
 
 	public inline static function enumIndex( e : EnumValue ) : Int {

+ 1 - 1
std/neko/Web.hx

@@ -23,7 +23,7 @@ package neko;
 
 /**
 	This class is used for accessing the local Web server and the current
-	client request and informations.
+	client request and information.
 **/
 class Web {
 

+ 1 - 1
std/neko/net/ServerLoop.hx

@@ -137,7 +137,7 @@ class ServerLoop<ClientData> {
 	}
 
 	/**
-		Called when an error occured. This enable you to log the error somewhere.
+		Called when an error occurred. This enable you to log the error somewhere.
 		By default the error is displayed using `trace`.
 	**/
 	public function onError( e : Dynamic ) {

+ 3 - 3
std/neko/vm/Loader.hx

@@ -40,7 +40,7 @@ enum LoaderHandle {
 	Loaders can be used for sandbox security. When a Module is loaded with a given
 	Loader, this loader can manager the module security by filtering which
 	primitives can be loaded by this module or by rewrapping them at loading-time
-	with custom securized versions. Loaders are inherited in loaded submodules.
+	with custom secured versions. Loaders are inherited in loaded submodules.
 **/
 class Loader {
 
@@ -78,8 +78,8 @@ class Loader {
 	/**
 		The default loader contains a cache of already loaded modules. It's
 		ensuring that the same module does not get loaded twice when circular
-		references are occuring. The same module can eventually be loaded twice
-		but with different names, for example with two relative paths reprensenting
+		references are occurring. The same module can eventually be loaded twice
+		but with different names, for example with two relative paths representing
 		the same file, since the cache is done on a by-name basic.
 	**/
 	public function getCache() : Map<String,Module> {

+ 1 - 1
std/neko/vm/Thread.hx

@@ -80,7 +80,7 @@ class Thread {
 
 	/**
 		The function [f] will be called by this thread if it's in [osLoop].
-		[sync] returns immediatly. See [osInitialize] remarks.
+		[sync] returns immediately. See [osInitialize] remarks.
 	**
 	public function sync( f : Void -> Void ) {
 		os_sync(handle,f);

+ 1 - 1
std/php/Boot.hx

@@ -267,7 +267,7 @@ function _hx_array_assign($a, $i, $v) { return $a[$i] = $v; }
 class _hx_break_exception extends Exception {}
 
 function _hx_cast($v, $type) {
-	if(Std::is($v, $type)) {
+	if(_hx_instanceof($v, $type)) {
 		return $v;
 	} else {
 		throw new HException('Class cast error');

+ 3 - 3
std/php/Web.hx

@@ -25,7 +25,7 @@ import haxe.io.Bytes;
 
 /**
 	This class is used for accessing the local Web server and the current
-	client request and informations.
+	client request and information.
 **/
 class Web {
 
@@ -245,14 +245,14 @@ class Web {
 		case, you will have to use `php.Web.getMultipart()` or
 		`php.Web.parseMultipart()` methods.
 	**/
-	public static function getPostData() {
+	public static function getPostData() : Null<String> {
 		var h = untyped __call__("fopen", "php://input", "r");
 		var bsize = 8192;
 		var max = 32;
 		var data : String = null;
 		var counter = 0;
 		while (!untyped __call__("feof", h) && counter < max) {
-			data += untyped __call__("fread", h, bsize);
+			data = untyped __php__('{0} . fread({1}, {2})', data, h, bsize);
 			counter++;
 		}
 		untyped __call__("fclose", h);

+ 1 - 1
std/php/_std/Std.hx

@@ -22,7 +22,7 @@
 @:coreApi class Std {
 
 	public static function is( v : Dynamic, t : Dynamic ) : Bool {
-		return untyped untyped __call__("_hx_instanceof", v,t);
+		return untyped __call__("_hx_instanceof", v,t);
 	}
 
 	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {

+ 2 - 2
std/php/_std/StringTools.hx

@@ -118,7 +118,7 @@
 	/**
 		Character codes of the characters that will be escaped by `quoteWinArg(_, true)`.
 	*/
-	public static var winMetaCharacters = [" ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code];
+	public static var winMetaCharacters = [";".code, ",".code, " ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code];
 
 	/**
 		Returns a String that can be used as a single command line argument
@@ -136,7 +136,7 @@
 	public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String {
 		// If there is no space, tab, back-slash, or double-quotes, and it is not an empty string.
 		if (!~/^[^ \t\\"]+$/.match(argument)) {
-			
+
 			// Based on cpython's subprocess.list2cmdline().
 			// https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620
 

+ 1 - 1
std/php/_std/sys/FileSystem.hx

@@ -39,7 +39,7 @@ class FileSystem {
 	}
 
 	public static function stat( path : String ) : FileStat {
-		untyped __php__("$fp = fopen($path, \"r\"); $fstat = fstat($fp); fclose($fp);");
+		untyped __php__("$fstat = stat($path);");
 		return untyped {
 			gid   : __php__("$fstat['gid']"),
 			uid   : __php__("$fstat['uid']"),

+ 7 - 7
std/php7/Boot.hx

@@ -633,14 +633,14 @@ private class HxString {
 		}
 	}
 
-	public static function indexOf( str:String, search:String, startIndex:Int = 0 ) : Int {
-		if (startIndex < 0) startIndex += str.length;
-		var index = Global.strpos(str, search, startIndex);
-		if (index == false) {
-			return -1;
-		} else {
-			return index;
+	public static function indexOf( str:String, search:String, startIndex:Int = null ) : Int {
+		if (startIndex == null) {
+			startIndex = 0;
+		} else if (startIndex < 0) {
+			startIndex += str.length;
 		}
+		var index = Global.strpos(str, search, startIndex);
+		return (index == false ? -1 : index);
 	}
 
 	public static function lastIndexOf( str:String, search:String, startIndex:Int = null ) : Int {

+ 40 - 0
std/php7/NativeStructArray.hx

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C)2005-2017 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package php;
+
+/**
+	This type can be used in places where externs use associative arrays as a list of configuration options.
+	This type is a special case for Haxe->Php generator: object declaration is generated as php array declaration whenever
+	that object declaration is passed directly to a variable or a function argument of this type.
+**/
+@:forward
+abstract NativeStructArray<T:{}>(NativeArray) to NativeArray {
+	@:from @:pure(false)
+	static function __fromObject<T:{}>(obj:T):NativeStructArray<T> {
+		return cast Syntax.array(obj);
+	}
+
+	@:to
+	inline function __toObject():T {
+		return Boot.createAnon(this);
+	}
+}

+ 1 - 3
std/php7/Resource.hx

@@ -1,7 +1,5 @@
 package php;
 
-import sys.io.File.FileHandle;
-
 abstract Resource(Dynamic) {
 
-}
+}

+ 3 - 3
std/php7/Web.hx

@@ -28,7 +28,7 @@ import php.SuperGlobal.*;
 
 /**
 	This class is used for accessing the local Web server and the current
-	client request and informations.
+	client request and information.
 **/
 class Web {
 
@@ -265,14 +265,14 @@ class Web {
 		case, you will have to use `php.Web.getMultipart()` or
 		`php.Web.parseMultipart()` methods.
 	**/
-	public static function getPostData() {
+	public static function getPostData() : Null<String> {
 		var h = fopen("php://input", "r");
 		var bsize = 8192;
 		var max = 32;
 		var data : String = null;
 		var counter = 0;
 		while (!feof(h) && counter < max) {
-			data += fread(h, bsize);
+			data = Syntax.binop(data, ' . ', fread(h, bsize));
 			counter++;
 		}
 		fclose(h);

+ 2 - 0
std/php7/_std/StringBuf.hx

@@ -41,6 +41,8 @@ import php.Syntax;
 			Syntax.binop(b, '.=', 'null');
 		} else if( Global.is_bool(x) ) {
 			Syntax.binop(b, '.=', ((x:Dynamic) ? 'true' : 'false'));
+		} else if( Global.is_string(x) ) {
+			Syntax.binop(b, '.=', x);
 		} else {
 			b += x;
 		}

+ 17 - 4
std/php7/_std/haxe/CallStack.hx

@@ -15,9 +15,15 @@ enum StackItem {
 	LocalFunction( ?v : Int );
 }
 
-@:dox(hide)
-@:noCompletion
 class CallStack {
+	/**
+		If defined this function will be used to transform call stack entries.
+		@param String - generated php file name.
+		@param Int - Line number in generated file.
+	*/
+	static public var mapPosition : String->Int->Null<{?source:String, ?originalLine:Int}>;
+
+	@:ifFeature("haxe.CallStack.exceptionStack")
 	static var lastExceptionTrace : NativeTrace;
 
 	/**
@@ -73,7 +79,7 @@ class CallStack {
 		}
 	}
 
-	@:keep
+	@:ifFeature("haxe.CallStack.exceptionStack")
 	static function saveExceptionTrace( e:Throwable ) : Void {
 		lastExceptionTrace = e.getTrace();
 
@@ -84,7 +90,7 @@ class CallStack {
 		for (i in -(count - 1)...1) {
 			var exceptionEntry:NativeAssocArray<Dynamic> = Global.end(lastExceptionTrace);
 
-			if(!Global.isset(exceptionEntry['file'])) {
+			if(!Global.isset(exceptionEntry['file']) || !Global.isset(currentTrace[-i]['file'])) {
 				Global.array_pop(lastExceptionTrace);
 			} else if (currentTrace[-i]['file'] == exceptionEntry['file'] && currentTrace[-i]['line'] == exceptionEntry['line']) {
 				Global.array_pop(lastExceptionTrace);
@@ -130,6 +136,13 @@ class CallStack {
 				}
 			}
 			if (Global.isset(entry['file'])) {
+				if (mapPosition != null) {
+					var pos = mapPosition(entry['file'], entry['line']);
+					if (pos != null && pos.source != null && pos.originalLine != null) {
+						entry['file'] = pos.source;
+						entry['line'] = pos.originalLine;
+					}
+				}
 				result.push(FilePos(item, entry['file'], entry['line']));
 			} else if (item != null) {
 				result.push(item);

+ 2 - 0
std/php7/_std/haxe/io/BytesInput.hx

@@ -60,6 +60,8 @@ class BytesInput extends Input {
 	}
 
 	public override function readByte() : Int {
+		if( len == 0 ) throw new Eof();
+		--len;
 		return b[pos++];
 	}
 

+ 5 - 3
std/php7/_std/sys/db/Mysql.hx

@@ -69,7 +69,7 @@ private class MysqlConnection implements Connection {
 	}
 
 	public function close() : Void {
-		close();
+		db.close();
 	}
 
 	public function escape( s : String ) : String {
@@ -180,7 +180,9 @@ private class MysqlResultSet implements ResultSet {
 
 	function withdrawFetched() : Dynamic {
 		if (fetchedRow == null) return null;
-		return Boot.createAnon(fetchedRow);
+		var row = fetchedRow;
+		fetchedRow = null;
+		return Boot.createAnon(row);
 	}
 
 	function correctArrayTypes(row:NativeAssocArray<String>):NativeAssocArray<Scalar> {
@@ -235,4 +237,4 @@ private class MysqlResultSet implements ResultSet {
 
 	function get_length() return result.num_rows;
 	function get_nfields() return result.field_count;
-}
+}

+ 6 - 6
std/python/_std/sys/net/Socket.hx

@@ -126,7 +126,7 @@ private class SocketOutput extends haxe.io.Output {
     public var output(default,null) : haxe.io.Output;
 
     /**
-        A custom value that can be associated with the socket. Can be used to retreive your custom infos after a `select`.
+        A custom value that can be associated with the socket. Can be used to retrieve your custom infos after a `select`.
     ***/
     public var custom : Dynamic;
 
@@ -164,7 +164,7 @@ private class SocketOutput extends haxe.io.Output {
     }
 
     /**
-        Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
+        Connect to the given server host/port. Throw an exception in case we couldn't successfully connect.
     **/
     public function connect( host : Host, port : Int ) : Void {
         __init();
@@ -207,7 +207,7 @@ private class SocketOutput extends haxe.io.Output {
     }
 
     /**
-        Return the informations about the other side of a connected socket.
+        Return the information about the other side of a connected socket.
     **/
     public function peer() : { host : Host, port : Int } {
         var pn = __s.getpeername();
@@ -215,7 +215,7 @@ private class SocketOutput extends haxe.io.Output {
     }
 
     /**
-        Return the informations about our side of a connected socket.
+        Return the information about our side of a connected socket.
     **/
     public function host() : { host : Host, port : Int } {
         var pn = __s.getsockname();
@@ -237,14 +237,14 @@ private class SocketOutput extends haxe.io.Output {
     }
 
     /**
-        Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
+        Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocking value.
     **/
     public function setBlocking( b : Bool ) : Void {
         __s.setblocking(b);
     }
 
     /**
-        Allows the socket to immediatly send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
+        Allows the socket to immediately send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
     **/
     public function setFastSend( b : Bool ) : Void {}
 

+ 4 - 4
std/python/lib/net/Socket.hx

@@ -44,7 +44,7 @@ extern class Socket {
     function close() : Void;
 
     /**
-        Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
+        Connect to the given server host/port. Throw an exception in case we couldn't successfully connect.
     **/
     function connect( addr : python.lib.net.Address ) : Void;
 
@@ -71,12 +71,12 @@ extern class Socket {
     function accept() : Tuple2<Socket,Address>;
 
     /**
-        Return the informations about the other side of a connected socket.
+        Return the information about the other side of a connected socket.
     **/
     function getpeername() : python.lib.net.Address;
 
     /**
-        Return the informations about our side of a connected socket.
+        Return the information about our side of a connected socket.
     **/
     function getsockname() : python.lib.net.Address;
 
@@ -91,7 +91,7 @@ extern class Socket {
     function waitForRead() : Void;
 
     /**
-        Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
+        Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocking value.
     **/
     function setblocking( b : Bool ) : Void;
 

+ 2 - 2
std/sys/FileStat.hx

@@ -22,7 +22,7 @@
 package sys;
 
 /**
-	File informations, as given by `sys.FileSystem.stat`.
+	File information, as given by `sys.FileSystem.stat`.
 **/
 typedef FileStat = {
 
@@ -47,7 +47,7 @@ typedef FileStat = {
 	var mtime : Date;
 
 	/**
-		The creation time for the file (not all filesystems support this).
+		The creation time for the file (not all file systems support this).
 	**/
 	var ctime : Date;
 

+ 6 - 6
std/sys/net/Socket.hx

@@ -38,7 +38,7 @@ extern class Socket {
 	var output(default,null) : haxe.io.Output;
 
 	/**
-		A custom value that can be associated with the socket. Can be used to retreive your custom infos after a `select`.
+		A custom value that can be associated with the socket. Can be used to retrieve your custom infos after a `select`.
 	***/
 	var custom : Dynamic;
 
@@ -63,7 +63,7 @@ extern class Socket {
 	function write( content : String ) : Void;
 
 	/**
-		Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
+		Connect to the given server host/port. Throw an exception in case we couldn't successfully connect.
 	**/
 	function connect( host : Host, port : Int ) : Void;
 
@@ -88,12 +88,12 @@ extern class Socket {
 	function accept() : Socket;
 
 	/**
-		Return the informations about the other side of a connected socket.
+		Return the information about the other side of a connected socket.
 	**/
 	function peer() : { host : Host, port : Int };
 
 	/**
-		Return the informations about our side of a connected socket.
+		Return the information about our side of a connected socket.
 	**/
 	function host() : { host : Host, port : Int };
 
@@ -108,12 +108,12 @@ extern class Socket {
 	function waitForRead() : Void;
 
 	/**
-		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
+		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocking value.
 	**/
 	function setBlocking( b : Bool ) : Void;
 
 	/**
-		Allows the socket to immediatly send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
+		Allows the socket to immediately send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
 	**/
 	function setFastSend( b : Bool ) : Void;
 

+ 16 - 0
tests/display/src/cases/Issue5988.hx

@@ -0,0 +1,16 @@
+package cases;
+
+class Issue5988 extends DisplayTestCase {
+	/**
+	class Main {
+		static function f():Int;
+
+		static function main() {
+			{-1-}
+		}
+	}
+	**/
+	function test() {
+		eq(true, Toplevel.hasToplevel(toplevel(pos(1)), "type", "Array"));
+	}
+}

+ 17 - 0
tests/display/src/cases/Issue6029.hx

@@ -0,0 +1,17 @@
+package cases;
+
+class Issue6029 extends DisplayTestCase {
+	/**
+		typedef A = {}
+		typedef B = {}
+
+		typedef C = {
+			>A{-1-},
+			>B{-2-},
+		}
+	**/
+	function test() {
+		eq("cases.A", type(pos(1)));
+		eq("cases.B", type(pos(2)));
+	}
+}

+ 29 - 0
tests/display/src/cases/Issue6068.hx

@@ -0,0 +1,29 @@
+package cases;
+
+class Issue6068 extends DisplayTestCase {
+	/**
+	class Main {
+		static function main() {
+			var a:{i:Int};
+			a({-1-});
+
+			Main({-2-});
+		}
+	}
+	**/
+	function test() {
+		check(function() signature(pos(1)));
+		check(function() signature(pos(2)));
+	}
+
+	function check(fn) {
+		numTests++;
+		var result = try {
+				fn();
+				false;
+			} catch (e:DisplayTestContext.HaxeInvocationException) {
+				e.message.indexOf("Not a callable type") != -1;
+			}
+		assert(result);
+	}
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است